Tar*_*rik 4 java constructor scjp instance-variables
根据SCJP6(页577),我发现实例变量在超类构造函数完成之前被赋予了默认值,我在Debugg模式中尝试了一个例子,但我看到超级承包商在实例变量获取其默认值之前运行,可以任何一个解释那对我来说?
我想用的例子:
package courseExercise;
class test {
test() {
System.out.println("Super Constructor run");
}
}
public class Init extends test {
private Integer i = 6;
private int j = 8;
Init(int x) {
super();
System.out.println("1-arg const");
}
Init() {
System.out.println("no-arg const");
}
static {
System.out.println("1st static init");
}
public static int d = 10;
{
System.out.println("1st instance init");
}
{
System.out.println("2nd instance init");
}
static {
System.out.println("2nd static init");
}
public static void main(String[] args) {
new Init();
new Init(7);
}
}
Run Code Online (Sandbox Code Playgroud)
初始化序列在JLS 12.5中指定:
规范的相关部分是:
...
如果没有足够的可用空间来为对象分配内存,则使用OutOfMemoryError突然完成类实例的创建.否则,新对象中的所有实例变量(包括在超类中声明的那些变量)都将初始化为其默认值(第4.12.5节).
在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:
...
这是你永远不应该final从构造函数调用非方法的原因之一:该方法可能被子类覆盖,在这种情况下,在子类有机会设置方法可能需要的状态之前,将调用该方法.考虑这个例子:
public class Super {
private final int superValue;
protected Super() {
superValue = getSuperValue();
}
protected int getSuperValue() {
return 1;
}
@Override
public String toString() {
return Integer.toString(superValue);
}
}
public class Sub extends Super {
private final int superValueOverride;
public Sub(int value) {
this.superValueOverride = value;
}
@Override
protected int getSuperValue() {
return superValueOverride;
}
public static void main(String[] args) {
Super s = new Sub(2);
System.out.println(s);
}
}
Run Code Online (Sandbox Code Playgroud)
看起来s.superValue应该是2,对吗?毕竟,Sub覆盖getSuperValue()返回的值superValueOverride初始化为2.但是在Sub初始化任何字段之前调用该方法(除了它们的默认值之外),因此s.superValue实际上是0(默认值superValueOverride).
这是更加古怪,因为superValueOverride是final,但它似乎改变它的价值!它在Super调用时为0 getSuperValue(),并且只有在Super构造函数完成后才将其最终值赋值为2(或者传递给构造函数的任何值).
| 归档时间: |
|
| 查看次数: |
1441 次 |
| 最近记录: |