在Java教程- 初始化字段中,对实例初始化块(实例初始化程序)进行了描述:
编译器将初始化程序块复制到每个构造函数中。因此,这种方法可以用于在多个构造函数之间共享代码块。
如果转述是正确的,则对下列代码:
public class ConstructorTest {
public static void main(String[] args) {
Child c = new Child();
}
}
class Parent {
Parent() {
System.out.println("Parent non-argument Constructor");
}
}
class Child extends Parent {
{
System.out.println("Child Instance Initialization Block");
}
Child() {
this(2);
System.out.println("Child no-argument Constructor");
}
Child(int i) {
this(10, i);
System.out.println("Child 1-argument Constructor");
}
Child(int i, int j) {
System.out.println("Child 2-argument Constructor");
}
}
产出应是:
Parent non-parm Constructor
Child Instance Initialization Block
Child 2-argument Constructor
Child Instance Initialization Block
Child 1-argument Constructor
Child Instance Initialization Block
Child no-argument Constructor
但实际产出是:
Parent non-argument Constructor
Child Instance Initialization Block
Child 2-argument Constructor
Child 1-argument Constructor
Child no-argument Constructor
我被误解了那句话的意思,还是描述不够准确?
对于显式构造函数调用的另一个疑问是:
根据两个基本概念:
这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?
谢谢你的回复。
发布于 2012-09-03 20:38:53
编辑:事实证明JLS是准确的,尽管它很难读懂。这一切在第12.5条中都很详细
在作为结果返回对新创建对象的引用之前,将使用以下过程处理指示的构造函数以初始化新对象:
注意突出显示的部分--执行链式构造函数,然后跳过步骤4,它将执行实例初始化程序。
实际上,实例和字段初始化程序只执行一次,从输出中可以看出这一点。
非正式地说,我认为将这一程序描述为:
this(...)
)中链接构造函数,直到到达不以this
开头的构造函数体为止。这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?
是。在类的构造函数链中的某个位置,可以保证最终得到一个构造函数,该构造函数可以隐式或显式地调用super
。这是唯一被调用的超类构造函数。
编辑:注意,您引用的教程显然是不正确的。
样本类:
public class Test {
{
System.out.println("Foo");
}
public Test() {
}
public Test(int i) {
this();
}
}
来自javap -c
的输出
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>": ()V
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #3 // String Foo
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: return
public Test(int);
Code:
0: aload_0
1: invokespecial #5 // Method "<init>":()V
4: return
}
如您所见,Test(int)
的构造函数没有编译实例构造函数的代码。
基本上,只有直接调用超类构造函数的构造函数具有复制到它们中的实例初始化程序代码。当然,所有其他构造函数都将导致通过调用超类构造函数的构造函数执行实例初始化程序代码。
发布于 2012-09-03 20:38:21
初始化块在实例化类的对象时只运行一次(使用任何构造函数<=,这是您的疑问)。当类加载器加载类时,静态初始化块只运行一次。
这是否意味着在子类的构造函数中使用this()将隐式删除对超类的无参数构造函数的默认调用?
不是的。这个()将调用同一个类的另一个构造函数,在本例中是默认构造函数(如果存在的话)。此构造函数(默认构造函数)将调用super()。
发布于 2012-09-03 20:53:21
我认为Java语言规范更准确:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6
类中声明的实例初始化器在创建类的实例时执行。
在http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5步骤4和5中,请描述您观察到的输出:
4.执行这个类的实例初始化器和实例变量初始化器. 5.执行这个构造函数主体的其余部分.
https://stackoverflow.com/questions/12253712
复制相似问题