【问题标题】:Java - weird static String behavior - new String("xxx") vs "xxx"Java - 奇怪的静态字符串行为 - 新字符串(“xxx”)与“xxx”
【发布时间】:2012-07-19 18:29:46
【问题描述】:
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") 有什么不同?

【问题讨论】:

  • +1 因为我不知道你可以这样初始化内联...

标签: java string static initialization


【解决方案1】:

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

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

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

【讨论】:

  • 应该把inlined改成interned吗?
【解决方案2】:

1.因为str3 = "en" is a String literal in literal pool, and str1 = new String("en") is a String object在String对象池中。

2.由于“en”是一个字面量,即“常量”,它会在开头初始化.

3.也称为Constant Folding,预先计算常数以更快地执行。

【讨论】:

    【解决方案3】:

    这是因为用 constants 初始化的类变量首先被初始化,然后才完成更复杂的初始化程序(例如使用 new String() 的表达式)(然后按源顺序完成)。见JLS §8.3.2.1

    8.3.2.1。类变量的初始化器

    [...]

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多