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

Java 私有静态方法中的最后一个字符串在调用时是否实例化了新对象?,java,final,string-literals,Java,Final,String Literals,私有静态方法中的静态最终字符串是否在调用时实例化新对象 private static String Test() { final String foo = "string literal"; return foo; } 或者编译器是否知道方法中只有一个字符串文本?还是应该将其设置为私有静态最终类字段?这会通过在类中传播代码来降低可读性。否,特定字符串将从类中重用。例如,如果是: final String foo = new String("string literal");

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

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
修饰符在这种特殊情况下没有任何影响。它仅禁止重新分配变量。

仅为字符串文本创建一个
字符串的实例。它们存储在
字符串
类的“实习生池”中。因此,考虑到这些
String
初始化:

String copy = new String("x");
String alias = copy.intern();
语句
copy!=“x”
别名==“x”
均为真


在这种情况下,如果您只有一个字段,那么它的可读性会更好。

foo将在每次调用函数时被实例化,因为它是方法中的局部变量。这个特殊的方法是静态的这一事实是不相关的。foo是final也不会影响它被实例化的时间,它只是意味着foo在初始赋值之后不能更改


将其设置为私有静态类变量,以确保它只实例化一次。

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


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

为什么不尝试调用它两次,比较返回的字符串并查看?这只是我方法中字符串的简化。它实际上并没有返回foo,只是用它执行一些工作。