Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么常量字符串使用intern()?_Java_String - Fatal编程技术网

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

Java 为什么常量字符串使用intern()?,java,string,Java,String,我知道JVM中的字符串池以及文本和字符串对象之间的区别。我知道文字是自动被拘留的,但这行的目的是什么: 公共静态最终字符串参数=“value”.intern(); 关于我的问题,我总是找到大量的文本,这些文本强调文字和对象之间的区别,并提到文字已经存在。因此,我想知道使用intern()而不是literal的棘手行的基础知识。Java自动实习生字符串literal。这意味着在许多情况下,==运算符对字符串的作用方式与对int或其他基本值的作用方式相同 由于字符串文本的插入是自动的,因此inte

我知道JVM中的字符串池以及文本和字符串对象之间的区别。我知道文字是自动被拘留的,但这行的目的是什么:

公共静态最终字符串参数=“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”作为字符串,其引用是say
2020

->现在,通过
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库时保持一致。