Java 为什么常量字符串使用intern()?
我知道JVM中的字符串池以及文本和字符串对象之间的区别。我知道文字是自动被拘留的,但这行的目的是什么:Java 为什么常量字符串使用intern()?,java,string,Java,String,我知道JVM中的字符串池以及文本和字符串对象之间的区别。我知道文字是自动被拘留的,但这行的目的是什么: 公共静态最终字符串参数=“value”.intern(); 关于我的问题,我总是找到大量的文本,这些文本强调文字和对象之间的区别,并提到文字已经存在。因此,我想知道使用intern()而不是literal的棘手行的基础知识。Java自动实习生字符串literal。这意味着在许多情况下,==运算符对字符串的作用方式与对int或其他基本值的作用方式相同 由于字符串文本的插入是自动的,因此inte
公共静态最终字符串参数=“value”.intern();
关于我的问题,我总是找到大量的文本,这些文本强调文字和对象之间的区别,并提到文字已经存在。因此,我想知道使用
intern()
而不是literal的棘手行的基础知识。Java自动实习生字符串literal。这意味着在许多情况下,==运算符对字符串的作用方式与对int或其他基本值的作用方式相同
由于字符串文本的插入是自动的,因此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
用简单的语言解释:
->在字符串池区域
中,假设“Shoaib”作为字符串,其引用是say2020
->现在,通过newstring(“Shoaib”)
创建的任何对象都将指向另一个引用,比如3030
->但是,如果您想将字符串池区域中“Shoaib”的引用
分配给新字符串(“Shoaib”)
,那么我们在其上使用intern()
因此,在上面,您询问了“value”.intern(),这在interning中没有任何意义。以防止编译时内联
我能想到的唯一用例是防止它被视为编译时常量,从而防止内联
现在一个原因可能是有人可以使用反射来更改值,这只有在字符串声明为那样时才起作用
它还允许您更改包含常量的类文件,如@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库
这种代码的主要好处是防止编译时常量内联
例如,假设一个类中有一个常量,而有许多其他类引用该常量。通常,如果更改常量值,则需要重新编译所有涉及的类。在字段上使用intern()
将阻止常量的内联,这意味着只需重新编译常量类就足够了。从理论上讲,这种方法的性能较差,尽管我不知道这有多重要
涵盖了相同的主题,是一本有用的读物。intern()用于访问字符串常量池的引用ID
您的变量可能包含相同的值,因此,我们不需要再次分配它
我们只是使用intern()检查它是否已经在字符串常量池中
若它不在池中,那个么就在池区域中分配JVM,并返回它的引用ID&我们过去共享相同的数据成员,其好处是我们使用相同的内存 这条线的目的是什么
public static final String PARAMETER = "value".intern();
仅用于从字符串常量池进行检查。如果它可用,那么它的返回就不会再次添加到池中。我不记得曾经见过这样的代码,而且它确实看起来毫无意义。你在哪里看到的?文字被拘留了;这似乎是多余的。也许有个边缘案件?不过,我怀疑这是否会有关联。我怀疑对货物的崇拜。我更喜欢“value”.intern().intern()
只是为了确定。我在大型项目中看到了这一点,顺便说一句,很明智的保罗)可能是重复的。那么,我从你的回答中推断,你认为没有理由这样做吗?你似乎在这个问题上绕了一圈,提供了一大堆关于实习的信息。这个链接在我看来毫无意义。:/
这个答案与这个问题有关,就像一篇关于高尔夫球的论文与胆囊有关一样。这是一个很好的参考资料,我投票决定作为它的复制品结束。即使问题不匹配,答案也会匹配。@MarkoTopolnik是的,这是一个很棒的问题。虽然我个人不赞成在问题不匹配的情况下以副本形式结束。第二个原因实际上是使用它的原因:)特别是当常量位于JAR依赖项中时。@MarkoTopolnik yes true:)我的想法是相同的,但无法给出正确的用例。例如,SWT库使用类似的技巧停止内联int
常量,唯一的原因是在升级SWT库时保持一致。