我知道JVM中的字符串池以及 literals 和字符串对象之间的区别。我知道文字是自动实习的,但这一行的目的是什么:
public static final String PARAMETER = "value".intern();
在我的问题上,我总是找到大量的文字,这些文字解释了我同样强调文字和对象之间的区别,并提到文字已经被实习。因此,我想知道使用intern()
超过文字的棘手行的基础知识。
答案 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();
仅用于检查字符串常量池。如果它可用,那么它的返回不会再次添加到池中。