问题 在字段中实例化和在构造函数中实例化之间有什么区别?


这样做有什么区别:

public class SomeClass {
    SomeObject obj = new SomeObject();
    //rest of the code
}

和这个

public class SomeClass {
    SomeObject obj;
    public SomeClass(){
       obj = new SomeObject();
    }
    //rest of the code
}

6701
2017-10-18 16:13


起源

备份 stackoverflow.com/questions/1568722/... - non sequitor


答案:


根据这一章 12.5创建新的类实例 Java语言规范:

就在提到新的之前   创建的对象作为返回   结果,指示的构造函数是   处理以初始化新对象   使用以下程序:

  1. 将构造函数的参数分配给新创建的参数   此构造函数的变量   调用。
  2. 如果此构造函数以显式构造函数调用开头   同一个类中的另一个构造函数   (使用此),然后评估   参数和进程构造函数   使用这些递归调用   同样的五个步骤。如果那个构造函数   然后,调用突然完成   这个程序突然完成了   同样的原因;否则,继续   第5步。
  3. 此构造函数不以显式构造函数开头   调用另一个构造函数   同一个班级(使用此)。如果这   构造函数是用于除了之外的类   对象,然后这个构造函数将   以明示或暗示开头   调用超类构造函数   (使用超级)。评估参数   并处理超类   构造函数调用递归   使用这五个相同的步骤。如果说   构造函数调用完成   突然,然后这个程序   为此突然完成   原因。否则,继续步骤
  4. 执行实例初始值设定项和实例变量初始值设定项   这个类,分配的值   实例变量初始化器   相应的实例变量,in   他们的从左到右的顺序   在源代码中以文本形式出现   为了上课。如果执行任何   这些初始化器导致了   例外,然后没有进一步   初始化程序已处理完毕   程序突然完成   同样的例外。否则,继续   与第5步。(在一些早期   实现,编译器   错误地省略了代码   如果字段初始化字段   初始化表达式是一个常量   值等于的表达式   默认的初始化值   它的类型。)
  5. 执行此构造函数的其余部分。如果执行   突然完成,然后这个   程序突然完成   同样的道理。否则,这个程序   正常完成。

所以差异只是步骤(步骤4或步骤5),但结果是相同的。


15
2017-10-18 16:28





唯一的区别在于 哪一步 引用已初始化。最终的效果是一样的。


2
2017-10-18 16:21





这只是一种风格问题,它编译成相同的代码。

我个人倾向于将实例的所有初始化都放在构造函数中,因为它适用于所有情况。


1
2017-10-18 18:05





第一个例子, obj将在构造函数运行之前初始化。当你有子类时,这是一个重要的细微差别。构造函数和初始化块的顺序将是:

  1. 超类初始化器
  2. 超类构造函数
  3. 子类初始化器
  4. 子类构造函数

0
2017-10-18 16:18



这不是我对JLS第12.5节的解释,我不认为这是真的。 - Pascal Thivent
这是不对的。 javac在构造函数中生成代码 后 对超级构造函数的调用。我理解C#是不同的(但你不能使用 this 在这样的表达中)。 - Tom Hawtin - tackline


尚未提及的一个方面:

public class SomeClass {
    SomeObject obj = new SomeObject();
    //rest of the code
}

将obj初始化为固定值。但是在构造函数中进行初始化时,可以让初始化依赖于构造函数的参数,或者(使用多个构造函数)使用完全不同的初始化表达式,例如:

public class SomeClass {
    private SomeObject obj;
    public SomeClass(int length){
       obj = new SomeObject(3 * length + 7);
    }
    //rest of the code
}

0
2017-11-05 18:07





施工时间。第一个是在输入main之前完成的。另一个对象的构造被延迟,直到调用SomeClass的ctor。


-3
2017-10-18 16:17



如何在主要之前完成第一个?这不是静态的...... - Zed
我的坏...... :(第一个例子会在构造函数运行之前创建SomeObject ...正确吗? - dicroce
答案就像@Pascal从JLS中复制一样,见#4和#5。 - non sequitor