我声明并立即实例化的字段是 null
。这是一个示例代码:
public class NullFieldSSCCE {
static abstract class Parent {
List<String> values;
Parent() {
values = getValues();
}
protected abstract List<String> getValues();
}
static class Child extends Parent {
String param1="test1";
String param2="test2";
Child() {
}
@Override
protected List<String> getValues() {
return Arrays.asList( new String[] {param1, param2} );
}
}
public static void main(String[] args) {
Child child = new Child();
System.out.println("Child p1="+child.values.get(0)+", p2="+child.values.get(1));
}
}
运行这个的结果是
Child p1=null, p2=null
虽然我希望
Child p1=test1, p2=test2
这怎么可能?这些字段在类被实例化的同时被实例化,不是吗?
最佳答案
怎么了
您遇到的情况在 8.3.2
和 8.8
章节中的 JLS 中进行了描述。您可以找到一些不太详细但可能更容易阅读的信息 here 。
这里的问题是对象的初始化顺序。
以下是您的示例的初始化顺序:
Parent
字段被实例化:values
成为 ArrayList
Child
构造函数调用 super()
,因此调用 Parent
构造函数 getValues()
被调用;在这种情况下,它是 Child.getValues()
; Child
字段被实例化: param1
和 param2
将它们的值分配给 Child
构造函数继续 - 在你的情况下什么也不做 您假设给定层次结构中所有类的所有字段都同时实例化,
4
发生在 3
之前,并且与 1
大致同时。不幸的是,这种假设是错误的。学习初始化顺序
即使您已经阅读了我给您的链接,您也可能不确定在特定情况下事情会如何运作。每当您对初始化顺序有疑问时,请不要犹豫,添加
printf
来检查它。这次我为你做了:public class NullFieldSSCCE {
static abstract class Parent {
List<String> values = new ArrayList<String>() {{
System.out.println("Parent.values instantiation");
}};
Parent() {
System.out.println("Parent()");
values.addAll(getValues());
}
protected abstract List<String> getValues();
}
static class Child extends Parent {
String param1="test1";
String param2="test2";
Object param3 = new Object() {{System.out.println("Child.param3 instantiation"); }};
Child() {
System.out.println("Child()");
}
@Override
protected List<String> getValues() {
System.out.println("Child.getValues()");
return Arrays.asList( new String[] {param1, param2} );
}
}
public static void main(String[] args) {
System.out.println("start");
Child child = new Child();
System.out.println("Child p1="+child.values.get(0)+", p2="+child.values.get(1));
}
}
输出是:
start
Parent.values instantiation
Parent()
Child.getValues()
Child.param3 instantiation
Child()
Child p1=null, p2=null
关于java - 为什么我的字段应该立即实例化,但它为空?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19488746/