我知道类中的静态和初始化 block 及其执行顺序。但是下面的代码引起了一些疑问。
class Test1 {
Test1(int x) {
System.out.println("Constructor value : " + x);
}
}
public class Test2 {
Test1 t1 = new Test1(10); ----- line 8
Test2(int i) {
t1 = new Test1(i);
}
public static void main(String[] args) {
Test2 t2 = new Test2(5);
}
}
此代码的输出:
构造函数值:10
构造函数值:5
我的问题是实例变量(第 8 行)在创建类(Test2)的对象或发生其他一些事情后立即执行。
最佳答案
初始化程序和初始化 block 的执行就像它们被插入到每个构造函数的顶部(在基类中)或在调用 super(...)
之后一样。 (在一个子类中)。¹所以你的 Test2
在功能上等同于:
public class Test2 {
Test1 t1;
Test2(int i) {
t1 = new Test1(10);
t1 = new Test1(i);
}
public static void main(String[] args) {
Test2 t2 = new Test2(5);
}
}
¹事实上,如果您查看字节码,这确实是真的......
例如,假设我们向
Test2
添加第二个构造函数。 :public class Test2 {
Test1 t1 = new Test1(10);
Test2(int i) {
t1 = new Test1(i);
}
Test2(int i, String s) {
t1 = new Test1(i);
}
public static void main(String[] args) {
Test2 t2 = new Test2(5);
}
}
然后编译它,并使用
javap -c Test2
查看字节码(大致):编译自“Test2.java”
公共(public)类Test2 {
测试1 t1;
测试2(int);
代码:
0:aload_0
1: invokespecial #1//方法 java/lang/Object."
4:aload_0
5: new #2//类 Test1
8:重复
9:双推 10
11: invokespecial #3//方法 Test1."
14: putfield #4//字段 t1:LTest1;
17:加载_0
18: new #2//类 Test1
21:重复
22:iload_1
23: invokespecial #3//方法 Test1."
26: putfield #4//字段 t1:LTest1;
29:返回
Test2(int, java.lang.String);
代码:
0:aload_0
1: invokespecial #1//方法 java/lang/Object."
4:aload_0
5: new #2//类 Test1
8:重复
9:双推 10
11: invokespecial #3//方法 Test1."
14: putfield #4//字段 t1:LTest1;
17:加载_0
18: new #2//类 Test1
21:重复
22:iload_1
23: invokespecial #3//方法 Test1."
26: putfield #4//字段 t1:LTest1;
29:返回
公共(public)静态无效主(java.lang.String[]);
代码:
0: new #5//类 Test2
3:重复
4:iconst_5
5: invokespecial #6//方法 "
8:astore_1
9:返回
}
你可以看到
t1 = new Test1(10)
在两个构造函数中。
关于java - 实例变量的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60018407/