Tom*_*ito 42 java null static nullpointerexception
以下代码打印null一次.
class MyClass {
private static MyClass myClass = new MyClass();
private static final Object obj = new Object();
public MyClass() {
System.out.println(obj);
}
public static void main(String[] args) {}
}
Run Code Online (Sandbox Code Playgroud)
为什么在构造函数运行之前没有初始化静态对象?
更新
我只是在没有注意的情况下复制了这个示例程序,我以为我们正在谈论2个Object字段,现在我看到第一个是MyClass字段..:/
Pyr*_*cal 37
因为静态按照源代码中给出的顺序进行初始化.
看一下这个:
class MyClass {
private static MyClass myClass = new MyClass();
private static MyClass myClass2 = new MyClass();
public MyClass() {
System.out.println(myClass);
System.out.println(myClass2);
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印:
null
null
myClassObject
null
Run Code Online (Sandbox Code Playgroud)
编辑
好吧,让我们更清楚地说明这一点.
明白了吗?
编辑2
正如Varman指出的那样,在初始化时,对它自身的引用将为null.如果你考虑一下这是有道理的.
Kev*_*ock 25
让我们尝试一种不同的方式来解释这个......
这是JVM首次引用类时所经历的顺序MyClass.
static { ... }块.myClass静态变量初始化为新的实例MyClass.MyClass已经加载(字节码)并且正在初始化过程中,因此它会跳过初始化.obj仍然是null(因为它不是堆和构造函数初始化变量的一部分).obj为新的实例Object.obj不会是null对Object实例的引用.请记住,Java指定为final变量赋值一次.并不是保证在代码引用它时为其分配值,除非您确保代码在分配后引用它.
这不是一个错误.这是在自己的初始化期间处理类使用的定义方法.如果不是这样,那么JVM将进入无限循环.请参阅步骤#3.3(如果JVM没有跳过初始化过程中的类的初始化,它将继续初始化它 - 无限循环).
请注意,这一切都发生在首次引用该类的同一个线程上.其次,JVM保证在允许任何其他线程使用此类之前完成初始化.
Sla*_*hev 19
那是因为Java按照声明的顺序执行静态部分.在你的情况下,顺序是
当执行#1时,obj仍未初始化,因此它打印为null.尝试以下操作,您将看到不同之处:
class MyClass {
private static final Object obj = new Object();
private static MyClass myClass = new MyClass();
public MyClass() {
System.out.println(obj); // will print null once
}
}
Run Code Online (Sandbox Code Playgroud)
一般来说,最好一起避免这种结构.如果您正在尝试创建单例,那么代码片段应该是这样的:
class MyClass {
private static final MyClass myClass = new MyClass();
private Object obj = new Object();
private MyClass() {
System.out.println(obj); // will print null once
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17533 次 |
| 最近记录: |