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

问题描述 投票:4回答:4

私有静态方法中的静态final String是否在调用时实例化一个新对象?

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

或者编译器是否知道方法中只有一个字符串文字?或者我应该将其设为私有静态最终类字段?这具有通过在类周围扩展代码来降低可读性的效果。

java final string-literals
4个回答
8
投票

不,特定字符串将从string literal pool重用。如果是例如:

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


1
投票

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

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


1
投票

只为字符串文字创建了一个String实例。这些存储在String类的“实习池”中。所以,鉴于这些String初始化:

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

copy != "x"alias == "x"这两个陈述都是正确的。

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


0
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.