当前位置: 首页 > 知识库问答 >
问题:

在Java中运行构造函数代码之前是否初始化了字段?

郭凯
2023-03-14

有人能解释一下以下程序的输出吗?我以为构造函数是在实例变量之前初始化的。所以我希望输出是“xzy”。

class X {
    Y b = new Y();

    X() {
        System.out.print("X");
    }
}

class Y {
    Y() {
        System.out.print("Y");
    }
}

public class Z extends X {
    Y y = new Y();

    Z() {
        System.out.print("Z");
    }

    public static void main(String[] args) {
        new Z();
    }
}

共有3个答案

谢豪
2023-03-14

调用构造函数时,实例变量初始值设定项在构造函数主体之前运行。你认为以下程序的输出是什么?

public class Tester {
    private Tester internalInstance = new Tester();
    public Tester() throws Exception {
        throw new Exception("Boom");
    }
    public static void main(String[] args) {
        try {
            Tester b = new Tester();
            System.out.println("Eye-Opener!");
        } catch (Exception ex) {
            System.out.println("Exception catched");
        }
    }
}

main方法调用Tester构造函数,该构造函数引发异常。您可能希望catch子句捕获此异常,并打印捕获的异常。但是如果你试着运行它,你会发现它没有做任何类似的事情,它会抛出一个stackoverflowerrror

司寇瑾瑜
2023-03-14

如果查看类文件的反编译版本

class X {
    Y b;

    X() {
        b = new Y();
        System.out.print("X");
    }
}

class Y {
    Y() {
        System.out.print("Y");
    }
}

public class Z extends X {

    Y y;

    Z() {
        y = new Y();
        System.out.print("Z");
    }

    public static void main(String args[]) {
        new Z();
    }
}

您可以发现实例变量y在构造函数中移动,因此执行顺序如下

  1. 调用Z

所有实例变量都是使用构造函数语句初始化的。

艾泉
2023-03-14

正确的初始化顺序是:

  1. 静态变量初始值设定项和静态初始值设定块,如果类以前没有初始化过,则按文本顺序
  2. 构造函数中的super()调用,无论是显式的还是隐式的
  3. 实例变量初始化器和实例初始化块,按文本顺序排列
  4. super()之后构造函数的剩余主体

参见Java虚拟机规范§2.17.5-6节。

 类似资料:
  • 问题内容: 谁能解释以下程序的输出?我认为构造函数要在实例变量之前初始化。因此,我期望输出为“ XZYY”。 问题答案: 正确的初始化顺序是: 如果该类先前尚未初始化,则按文本顺序的静态变量初始化程序和静态初始化块。 构造函数中的super()调用,无论是显式的还是隐式的。 实例变量初始化程序和实例初始化块,按文本顺序。 super()之后构造函数的其余主体。

  • 假设你有这个代码片段 例如,如果编译器决定让它看起来像 这将是一个问题,因为calculateWaitTime()生成一个新线程,该线程可能会将集合视为null或其中没有1。 那么问题又来了,这种重新排序可能吗?或者所有在构造函数之外初始化的最终字段都是在构造函数之前初始化的,或者至少总是由编译器移动到构造函数的顶部

  • 问题内容: 如果未将ArrayList初始化为字段,则将项目添加到ArrayList时出现NullPointerException。谁能解释为什么? 当我将ArrayList初始化为字段时起作用: 当我将ArrayList声明为字段然后在Class构造函数中对其进行初始化时,它不起作用: 问题答案: 因为构造函数中的版本正在创建一个新变量,而该变量恰好与您的成员字段名称相同,而成员字段仍未设置。这

  • 问题内容: 有没有在Java构造函数中使用最终变量的解决方案?问题是,如果我初始化一个最终字段,例如: 那么我就不能在构造函数中使用它。Java首先运行构造函数,然后运行字段。有没有一种解决方案可以让我访问构造函数中的final字段? 问题答案: 我不太明白你的问题。那 执行如下:

  • 我想在构造函数中初始化二维数组。但是,我在类中声明数组的实例变量时遇到了一个问题。如果我这样做就错了: 我怎么解决这个问题?

  • 问题内容: 我最近一直在用C#和Java进行编程,并且很好奇初始化我的类字段的最佳位置。 我应该在申报时这样做吗: 还是在构造函数中?: 我真的很好奇你们中的一些资深人士认为这是最佳做法。我要保持一致,并坚持一种方法。 问题答案: 我的规则: 不要在声明中的默认值初始化()。 如果你没有用于更改字段值的构造函数参数,则最好在声明中进行初始化。 如果字段的值由于构造函数参数而改变,则将初始化放入构造