public class Test {
private static final String str1 = new String("en");
private static Test instance = initInstance();
private static final String str2 = new String("en");
private static final String str3 = "en";
private Test() {
}
public static void main(String[] args) {
}
private static Test initInstance() {
instance = new Test();
System.out.println(str1 + ',' + str2 + ',' + str3);
return instance;
}
}
理论上,随处可见静态,应该会产生“en,en,en”。
结果:“en,null,en”
预期:“en,null,null”(因为我发现静态命令实际上很重要)
有人可以解释一下吗? “en”和new String(“en”)有什么不同?
答案 0 :(得分:19)
是。在调用方法时,str2尚未初始化(字段按声明顺序初始化),str3是编译时常量。
编译时常量由类文件中的编译器内联。 new String(“..”)不是常量,因为它使用构造函数。
字符串常量由字符串文字定义:“”,它们放在jvm实例的字符串池中,以便重用它们。与此相反,使用新的String(..)会创建一个新实例,因此应该避免使用。
答案 1 :(得分:11)
这是因为首先使用常量初始化的类变量被初始化,然后只有更复杂的初始化器(如使用new String()
的表达式)完成(然后按源顺序完成) 。见JLS §8.3.2.1:
8.3.2.1。类变量的初始化程序
[...]
在运行时,
static
的{{1}}字段以及使用常量表达式§15.28初始化的字段首先被初始化(§12.4.2)。这也适用于接口(§9.3.1)中的此类字段。这些字段是“常量”,永远不会被观察到具有默认的初始值(§4.12.5),即使是狡猾的程序(§13.4.9)。
答案 2 :(得分:4)
1。因为str3 = "en" is a String literal in literal pool, and str1 = new String("en") is a String object
在String对象池中。
2。由于“en”是一个文字,即“常量”,它将在开头初始化。
3. 它也称为常量折叠,预先计算常量以便更快地执行。