4

调用时私有静态方法中的静态最终字符串是否会实例化一个新对象?

private static String Test() {
    final String foo = "string literal";
    return foo;
}

或者编译器是否知道方法内部只有一个字符串文字?还是应该将其设为私有静态最终类字段?这会通过在类中散布代码来降低可读性。

4

4 回答 4

9

不,特定字符串将从字符串文字池中重用。如果是例如:

final String foo = new String("string literal");

然后确实会在每次调用该方法时创建一个新的。

这是一个证据:

public static void main(String[] args) throws Exception {
    String s1 = test1();
    String s2 = test1();
    System.out.println(s1 == s2); // true

    String s3 = test2();
    String s4 = test2();
    System.out.println(s3 == s4); // false
}

private static String test1() {
    final String foo = "string literal";
    return foo;
}

private static String test2() {
    final String foo = new String("string literal");
    return foo;
}

请注意,final修饰符在这种特殊情况下没有任何影响。它只禁止重新分配变量。

于 2010-10-16T01:51:21.570 回答
1

您不必太担心字符串文字。JVM 对字符串文字进行了特殊处理,以提高性能并减少内存开销。在代码中任何地方(本地或其他地方)使用的字符串文字都会被 JVM 汇集和重用。这样做是为了减少在 JVM 中创建的 String 对象的数量。每次您的代码创建字符串文字时,JVM 首先检查池中的字符串文字。如果该字符串已存在于池中,则返回对池实例的引用。如果池中不存在字符串,则实例化一个新的 String 对象,然后将其放入池中。Java 可以进行这种优化,因为字符串是不可变的,并且可以共享而不必担心数据损坏。但是,这种行为仅适​​用于字符串文字,而不适用于使用“new”创建的对象

总之,使字符串文字成为类变量(私有静态最终类字段)或将其保留为局部变量具有相同的效果。

于 2010-10-16T02:04:29.103 回答
1

String为字符串文字创建了一个 a 实例。这些存储在String班级的“实习生池”中。因此,鉴于这些String初始化:

String copy = new String("x");
String alias = copy.intern();

陈述copy != "x"alias == "x"都是真实的。

在这种情况下,如果您只有一个字段,它将更具可读性。

于 2010-10-16T01:53:38.947 回答
0

foo 将在每次调用您的函数时被实例化,因为它是方法内的局部变量。这种特定方法是静态的这一事实是无关紧要的。foo 是 final 对它的实例化时间也没有影响,它只是意味着 foo 在初始分配后不能改变。

使其成为私有静态类变量,以确保它只被实例化一次。

于 2010-10-16T01:54:01.213 回答