当一个类有自己的静态实例时,我无法理解初始化顺序.此外,为什么这种行为似乎有所不同String.
请参阅以下示例:
public class StaticCheck {
private static StaticCheck INSTANCE = new StaticCheck();
private static final List<String> list =
new ArrayList<String>(Arrays.asList("hello"));
private static final Map<String, String> map =
new HashMap<String, String>();
private static final String name = "hello";
public static StaticCheck getInstance() {
return INSTANCE;
}
private StaticCheck() {
load();
}
private void load() {
if(list != null) {
System.out.println("list is nonnull");
} else {
System.out.println("List is null");
}
if(name != null) {
System.out.println("name is nonnull");
} else {
System.out.println("name is null");
}
if(map != null) {
System.out.println("Map is nonnull");
} else {
System.out.println("Map is null");
}
}
public static void main(String[] args) {
StaticCheck check = StaticCheck.getInstance();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
List is null
name is nonnull
Map is null
Run Code Online (Sandbox Code Playgroud)
我绝对不清楚为什么该字段name不为空.静态字段在以下情况下初始化,如类初始化中所述:http:
//javarevisited.blogspot.in/2012/07/when-class-loading-initialization-java-example.html
看看上面的例子,我的想法是:
如上所述,在Java中的实例初始化之前初始化静态字段.在这里,当我调用静态方法时getInstance(),它将导致类初始化,这意味着静态字段的初始化.在这种情况下,字段map和和list不应为null.
在上面的示例中,由于该字段INSTANCE是静态的,因此load()在未初始化其他字段时会发生其对象初始化并且其构造函数会调用.因为这个字段list和map为空.那么为什么name要初始化?我有点困惑.
的String类型name变量是一个编译时间常数,其通过在编译时,编译器内联.所以,条件:
if (name != null)
Run Code Online (Sandbox Code Playgroud)
编译后将成为:
if ("hello" != null)
Run Code Online (Sandbox Code Playgroud)
这当然是真的.
至于为什么map和list是null,那是因为,当初始化类时,初始化INSTANCE字段,调用构造函数,构造函数又调用该load()方法.请注意,static到目前为止,尚未运行其他初始值设定项.所以,map和list仍在null.所以,用load()方法打印它们null.
常量static变量在初始化任何非static变量之前初始化。JLS第 12.4.2 节规定了类的初始化过程:
\n\n\n\n
\n\n- 否则,记录当前线程正在初始化 C 的 Class 对象,并释放 LC。\n 然后,初始化 C 的静态字段,即常量变量 (\xc2\xa74.12.4, \xc2\ xa78.3.2、\xc2\xa79.3.1)。
\n(其他步骤在这里)
\n\n\n
\n- 接下来,按文本顺序执行类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
\n
因此,INSTANCE在文本上首先列出,在list、map和之前name。为什么三个都还没动呢null?这是因为name是由常量表达式初始化的;它是一个常量变量。它首先被初始化,before INSTANCE,因为它是一个常量变量。
请注意,您可以将初始化行移到andINSTANCE之后,从而使和在之前初始化。listmaplistmapINSTANCE
| 归档时间: |
|
| 查看次数: |
849 次 |
| 最近记录: |