Java - 奇怪的静态字符串行为 - 新字符串("xxx")与"xxx"

dra*_*ius 16 java string static initialization

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

从理论上讲,它在任何地方都应该产生"en,en,en".

结果:"en,null,en"

预期:"en,null,null"(因为我发现静态命令实际上很重要)

有人可以解释一下吗?"en"和new String("en")有什么不同?

Boz*_*zho 19

是.在调用方法时,str2尚未初始化(字段按声明顺序初始化),str3是编译时常量.

编译时常量由类文件中的编译器内联.new String("..")不是常量,因为它使用构造函数.

字符串常量由字符串文字定义:"",它们放在jvm实例的字符串池中,以便重用它们.与此相反,使用新的String(..)会创建一个新实例,因此应该避免使用.

  • `inlined`应该改为`interned`? (5认同)

T.J*_*der 11

发生这种情况是因为用常量初始化的类变量首先被初始化,然后只有更复杂的初始化器(如表达式使用new String())完成(然后按源顺序完成).见JLS§8.3.2.1:

8.3.2.1.类变量的初始值设定项

[...]

在运行时,首先初始化使用常量表达式(第15.28节)初始化的static字段final(第12.4.2节).这也适用于接口中的这​​些字段(第9.3.1节).这些字段是"常量",永远不会被观察到具有其默认初始值(§4.12.5),即使是狡猾的程序(§13.4.9).