调用时私有静态方法中的静态最终字符串是否会实例化一个新对象?
private static String Test() {
final String foo = "string literal";
return foo;
}
或者编译器是否知道方法内部只有一个字符串文字?还是应该将其设为私有静态最终类字段?这会通过在类中散布代码来降低可读性。
调用时私有静态方法中的静态最终字符串是否会实例化一个新对象?
private static String Test() {
final String foo = "string literal";
return foo;
}
或者编译器是否知道方法内部只有一个字符串文字?还是应该将其设为私有静态最终类字段?这会通过在类中散布代码来降低可读性。
不,特定字符串将从字符串文字池中重用。如果是例如:
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
修饰符在这种特殊情况下没有任何影响。它只禁止重新分配变量。
您不必太担心字符串文字。JVM 对字符串文字进行了特殊处理,以提高性能并减少内存开销。在代码中任何地方(本地或其他地方)使用的字符串文字都会被 JVM 汇集和重用。这样做是为了减少在 JVM 中创建的 String 对象的数量。每次您的代码创建字符串文字时,JVM 首先检查池中的字符串文字。如果该字符串已存在于池中,则返回对池实例的引用。如果池中不存在字符串,则实例化一个新的 String 对象,然后将其放入池中。Java 可以进行这种优化,因为字符串是不可变的,并且可以共享而不必担心数据损坏。但是,这种行为仅适用于字符串文字,而不适用于使用“new”创建的对象
总之,使字符串文字成为类变量(私有静态最终类字段)或将其保留为局部变量具有相同的效果。
只String
为字符串文字创建了一个 a 实例。这些存储在String
班级的“实习生池”中。因此,鉴于这些String
初始化:
String copy = new String("x");
String alias = copy.intern();
陈述copy != "x"
和alias == "x"
都是真实的。
在这种情况下,如果您只有一个字段,它将更具可读性。
foo 将在每次调用您的函数时被实例化,因为它是方法内的局部变量。这种特定方法是静态的这一事实是无关紧要的。foo 是 final 对它的实例化时间也没有影响,它只是意味着 foo 在初始分配后不能改变。
使其成为私有静态类变量,以确保它只被实例化一次。