为什么常量字符串使用intern()?

时间:2014-01-21 13:51:30

标签: java string

我知道JVM中的字符串池以及 literals 字符串对象之间的区别。我知道文字是自动实习的,但这一行的目的是什么:

public static final String PARAMETER = "value".intern();

在我的问题上,我总是找到大量的文字,这些文字解释了我同样强调文字和对象之间的区别,并提到文字已经被实习。因此,我想知道使用intern()超过文字的棘手行的基础知识。

5 个答案:

答案 0 :(得分:13)

这种代码的主要好处是防止编译时常量被内联。

例如,假设您在一个类中有一个常量,并且您有许多其他类引用该常量。通常,如果更改常量值,则需要重新编译所涉及的所有类。在字段上使用intern()将阻止常量的内联,并且意味着仅重新编译常量类就足够了。从理论上讲,这种方法会有较差的表现,虽然我不知道可能有多重要。

This SO question涵盖相同主题,是一本有用的阅读材料。

答案 1 :(得分:8)

防止编译时内联

我能想到的唯一用例是阻止它被视为编译时常量,因此它会阻止内联

现在有一个原因可能是某人可以使用Reflection 更改值,只有在声明字符串时才会有效。

它还允许你在答案中更改@Duncan所说的包含常量的类文件。这也是一个很好的理由。

这是如何运作的?

当您将String声明为public static final String CONST = "abc";时,它是一个编译时常量,并且将使用该常量在类中内联。

class A{
    private void foo(){
        String newString = CONST + someDynamicValue;
    }
}

编译完成后,如果你反编译你会发现

class A{
   private void foo(){
       String newString = "abc" + someDynamicString;
   }
}

但是当你使用.intern()或任何其他方法声明它时,它不能被视为编译时常量,并且每次从类中获取值时都不能。 Java这样做是有效的。

来自@Marko评论的例子:

  

SWT库使用类似的技巧来阻止内联int   常数,唯一的原因是要保持一致   升级SWT库

答案 2 :(得分:1)

Java自动实习字符串文字。这意味着在许多情况下,==运算符似乎适用于字符串,就像它对整数或其他原始值一样。

由于对于字符串文字是自动的,因此intern()方法将用于使用new String()构建的字符串

使用您的示例:

String s1 = "Shoaib";
String s2 = "Shoaib";
String s3 = "Shoaib".intern();
String s4 = new String("Shoaib");
String s5 = new String("Shoaib").intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

if ( s1 == s4 ){
    System.out.println("s1 and s4 are same" );  // 3.
}

if ( s1 == s5 ){
    System.out.println("s1 and s5 are same" );  // 4.
}

将返回:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

用简单的词语解释:

- >在String pooled region中假设我们将“Shoaib”作为字符串,其引用为2020

- >现在,您new String("Shoaib")创建的任何对象都会指向另一个引用3030

- >但是如果你想在字符串池区域中将reference“Shoaib”分配给new String("Shoaib"),那么我们就在它上面使用intern()。

所以上面你问过“值”.intern(),这在实习的情况下没有任何意义。

答案 3 :(得分:0)

intern()用于访问String Constant Pool的引用ID。

您的变量可能包含相同的值,因此我们不需要再次分配它。

我们只是使用intern()来检查它是否已经在String Constant Pool中?

如果它不在池中,那么只有JVM在池区域中分配并返回它的引用ID&我们曾经共享相同的数据成员,并且好处是我们使用相同的内存。

答案 4 :(得分:0)

这一行的目的

public static final String PARAMETER = "value".intern();

仅用于检查字符串常量池。如果它可用,那么它的返回不会再次添加到池中。