初始化对象时构造函数如何工作?
此代码的输出为7 20。
为什么7先打印,然后打印20?
public class Television { private int channel = setChannel(7); public Television(int channel) { this.channel = channel; System.out.print(channel +""); } public int setChannel(int channel) { this.channel = channel; System.out.print(channel + ""); return channel; } public static void main(String args[]) { new Television(20); } }
创建对象时,将创建其字段。 你有一个class级成员:
private int channel = setChannel(7);
当你这样做时:
new Television(20);
初始化该字段并在调用构造函数之前调用setChannel
,并从那里打印7。
创建对象的所有字段并使用提供的值填充(如果未指定值,则填充默认值)。 您可以将其视为实例的准备。 准备好并初始化这些成员后,将调用构造函数。
有关更多详细信息,请参阅JLS 。
因为这是Java 中初始化的顺序 。 简而言之:
- 静态成员和块
- 实例成员和块
- 构造体
答案可以在Java语言规范中找到 :
在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:
将构造函数的参数分配给此构造函数调用的新创建的参数变量。
如果这个构造函数以同一个类中另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用它)……
…如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super)…
为此类执行实例初始值设定项和实例变量初始值设定项 ,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中,它们以文本方式显示在类的源代码中。 如果执行任何这些初始值设定项导致exception,则不会处理其他初始值设定项,并且此过程会突然完成同样的exception。 否则,继续步骤5。
执行此构造函数的其余部分 。 如果该执行突然完成,则由于同样的原因,此过程突然完成。 否则,此过程正常完成。
总结一下,如果构造函数没有调用另一个构造函数(使用this
)并且它不调用任何超类构造函数(使用super
),则在执行构造函数的代码之前初始化实例变量。
首先,初始化私有字段,然后调用构造函数。
所以输出是7 20。
在java中,实例化一个新对象时发生以下过程:
- 对对象的所有私有字段进行评估。
- 然后,只有这样,才会调用构造函数。
你在类construsctor之外初始化你的字段’channel’,所以在它之前调用这个初始化。
这是你打电话给new Television(20)
时所附加的内容new Television(20)
:
1/this.channel set to 7 (init step) 2/Calling constructor 3/this.chennel set to 20 (constructor code)
因为初始化变量通道的setChannel首先调用init来实现类,然后在构造函数中调用该方法。
当您创建对象的实例时,首先要创建其数据成员(即首先执行该行是private int channel = setChannel(7);
)然后只有构造函数public Television(int channel) {...}
创建宾语。