Java:对象的初始化序列 [英] Java: initialization sequence of object
问题描述
有一个代码是作为初级Java开发人员的任务提供的。我在五年内使用Java,这段代码让我很困惑:
There is a code which is given as a task for a junior Java developers. I use Java during five years and this piece of code completely confusing me:
public class Main {
String variable;
public static void main(String[] args) {
System.out.println("Hello World!");
B b = new B();
}
public Main(){
printVariable();
}
protected void printVariable(){
variable = "variable is initialized in Main Class";
}
}
public class B extends Main {
String variable = null;
public B(){
System.out.println("variable value = " + variable);
}
protected void printVariable(){
variable = "variable is initialized in B Class";
}
}
输出结果为:
Hello World!
variable value = null
但是如果我们改变 String variable = null;
到字符串变量;
我们将:
But if we change String variable = null;
to String variable;
we will have:
Hello World!
variable value = variable is initialized in B Class
第二项输出对我来说更清楚。
所以,据我所知,Java中的inizialisation序列是这样的:
The second output is more clear for me. So, as far as I know the sequence of inizialisation in Java like this:
- 我们去了类的根层次结构(对于Java,它总是Object类),当我们来到这个根父类时:
- 所有静态数据字段都已初始化;
- 执行所有静态字段初始值设定项和静态初始化块;
- 初始化所有非静态数据字段;
- 全部非执行-static字段初始值设定项和非静态初始化块;
- 执行默认构造函数;
- We go to the root of the class hierarchy (for Java it is always Object class), when we come to this root parent class:
- All static data fields are initialized;
- All static field initializers and static initialization blocks are executed;
- All non-static data fields are initialized;
- All non-static field initializers and non-static initialization blocks are executed;
- The default constructor is executed;
还有一篇文章描述了<$ c的行为$ c>超级类上下文中的关键字 - 从基类方法调用基类重写函数
Also there is post which describes the behavior of the
this
keyword in context of a superclass - Calling base class overridden function from base class method根据上面给出的规则,我假设有这样的序列:
Based on the rules given above, I assume to have sequence like this:
- 我们将创建一个新的类实例
B
; - 我们转到零件类
Main
; - 使用null初始化
main.variable
; - 然后我们转到类
Main的默认构造函数
; - 构造函数调用方法
b.printVariable()
类Main
; (为什么不调用main.printvariable
?我们这里没有这个
关键字。) - 字段
b.variable
变量在B类中初始化 - 现在我们回到班级
B
; - 我们应该初始化字段
b.variable
具有空值,我是对吗? - 类
B
执行的默认构造函数
- We are going to create a new instance of class
B
; - We go to the part class
Main
; - Initialize
main.variable
with null; - Then we move to the default constructor of class
Main
; - Constructor calls method
b.printVariable()
in classMain
; (Why doesn't it callmain.printvariable
? We don't havethis
key word here.) - The field
b.variable
"variable is initialized in B Class" - Now we come back to the class
B
; - We should initialize field
b.variable
with null value, am I right?; - The default constructor of class
B
executed
请有人给出完整和完整的解释,说明这种继承inizialisation序列是如何工作的。以及为什么将
String variable = null;
改为字符串变量;
导致另一个输出。Please, can someone give a complete and full explanation of how this inheritance inizialisation sequence works. And why changing
String variable = null;
toString variable;
leads to another output.推荐答案
序列是:
- Main - >Hello
- Main - > new B()
- B() - > Main() - > b.printVariable() - >设置变量
- 返回初始化B,因此变量= null。
- Main -> "Hello"
- Main -> new B()
- B() -> Main() -> b.printVariable() -> sets the variable
- Back to initialising B, so variable=null occurs.
所以基本上,超级对象Main()是在B类的任何初始化事件之前构造的。这意味着变量= null以后发生。这是有道理的,否则B可以打破Main的初始化。
So basically, the super object Main() is constructed before any intialisation events of class B. Which means variable=null occurs later. This makes sense as otherwise B could break the initialisation of Main.
Joshua Bloch在他有效的java书中讲述了很多关于危险的继承是如何做对的好事,我会推荐它。
Joshua Bloch covers a lot of good ground in his effective java book about how dangerous inheritance is to get right, I would recommend it.
这篇关于Java:对象的初始化序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!