Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.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
新字符串(“X”)与新字符串(“X”)和“x2B”之间的字符串初始化差异;Java中的新字符串(“Y”)_Java - Fatal编程技术网

新字符串(“X”)与新字符串(“X”)和“x2B”之间的字符串初始化差异;Java中的新字符串(“Y”)

新字符串(“X”)与新字符串(“X”)和“x2B”之间的字符串初始化差异;Java中的新字符串(“Y”),java,Java,我用JDK1.8运行上面的代码,我想我会得到两个“false”,因为在我看来,很明显s1和str1位于堆中,s2和str2位于字符串池中,但我得到了一个“false”和一个“true”。 问题来了:是什么导致了“真实” 以上是原始问题。 现在,为了确定这个问题与这些所谓的重复问题相去甚远,我想谈谈我的新发现:代码的第二部分在JDK1.6中得到了“false”结果,而在JDK1.8中得到了“true”结果。一些博客说intern()的行为在JDK1.7发布后发生了变化 如果池中不包含与此字符串对

我用JDK1.8运行上面的代码,我想我会得到两个“false”,因为在我看来,很明显s1和str1位于堆中,s2和str2位于字符串池中,但我得到了一个“false”和一个“true”。 问题来了:是什么导致了“真实”


以上是原始问题。 现在,为了确定这个问题与这些所谓的重复问题相去甚远,我想谈谈我的新发现:代码的第二部分在JDK1.6中得到了“false”结果,而在JDK1.8中得到了“true”结果。一些博客说intern()的行为在JDK1.7发布后发生了变化

如果池中不包含与此字符串对象相等的字符串,则此字符串对象将不会添加到池中,而对此字符串对象的引用将添加到池中。这意味着池中的引用将被分配给位于其他地方(如堆)的string对象,下一次文本字符串的初始化等于早期字符串的初始化时,也将被分配给string对象。这正好描述了关于“true”结果的代码第2部分

这个理论在我解释上述代码结果的过程中确实起了作用。但是很明显,这个理论与intern()文档所包含的内容不同,这在JDK6/8API中几乎是一样的


现在的问题是:对于JDK1.6和JDK1.8中相同代码的不同结果,有没有更好的解释?我上面提到的理论真的会发生什么吗?

返回字符串对象的规范表示形式,因此,如果希望在字符串池中引用该规范表示形式,则需要将其赋值

public static void main(String[] args) {
    String s1 = new String("aa");
    s1.intern();
    String s2 = "aa";
    System.out.println(s1 == s2);

    //wrong in JDK1.6 but true in JDK1.8
    String str1 = new String("str") + new String("01");
    str1.intern();
    String str2 = "str01";
    System.out.println(str1 == str2);

}
这里的
s1
仍然是您声明的对象,并且在堆中

你需要做什么

String s1 = new String("aa");
s1.intern();
如果需要文本字符串

String s1Itern = s1.intern();
对于第二种情况,Max的回答很好地解释了这一点。

首先让我们看看For
字符串。intern()

调用intern方法时,如果池已包含 等于此字符串对象的字符串,由等于(对象)确定 方法,则返回池中的字符串否则,这个 字符串对象被添加到池中,并引用此字符串 对象返回

然后让我们看看您的代码:

s1 == s2 is false
s1Itern == s2 is true
您可以在这里创建3字符串对象。添加到字符串池中的字符串literal
“aa”
,新字符串(“aa”),它是由
“aa”
构建的副本,但是另一个实例,第二个字符串literal
“aa”
,再次从池中获取(因此它与第一个
“aa”
的实例相同)。当您调用
intern()
时,字符串池已经有一个等于
s1
的字符串(它是从文本
“aa”
构造的),因此
“aa”
返回,但您不使用它,
s1
仍然是一个不同的实例。因此
s1==s2
false

    final String s1 = new String("aa");
    s1.intern();
    final String s2 = "aa";
    System.out.println(s1 == s2);

您可以在这里创建6字符串对象。放入池中的文本
“str”
“01”
。然后从这些文本创建两个副本。然后是这两个字符串的串联,即
str1
。此连接不会立即放入池中,但当您在
str1
上调用
intern()
时,它将被放入池中,因此
str1
本身现在位于池中。因此,当您将str2创建为String literal
“str01”
时,它将从池中获取,因此与str1

intern()
…?如果您阅读intern()方法的文档,它应该会变得更清晰。您不应该假设任何关于对象放置的内容。您可以知道会发生什么,但JVM和自动内存分配的目的是将您与之隔离。编译器可能会在这里做一些技巧,它可能会保持字符串常量缓存,或者根本不进行优化。这种行为不是语言的一部分,可能会在没有通知的情况下随时发生变化,所以您永远不应该依赖它。请注意,我没有说任何关于intern()方法的内容,而是关于内存布局的内容。即使intern()方法也不涉及堆/堆栈分配的主题,而是通过将字符串映射到公共引用来消除重复。您可以依赖API,并且该方法是该API的一部分-您不能依赖于对编译器内部的预测和实验。@Lebecca-准确地说,这不仅仅是Java问题。这同样适用于任何基于VM的语言,因此当您学习和使用.NET、python、NodeJS、Ruby、Smalltalk、任何LISP方言等时,您应该应用相同的思路。您似乎在说s2和str2的声明不同,或者具有不同的类型,而它们不是也没有。真的,我误解了,我将删除我的回答也谢谢你的意见``我仍然不明白为什么实习生()让s1留在堆中,而str1像你说的那样转向池中。“s1仍然是一个不同的实例”,为什么str1会改变。s1.intern()和str1.intern()的模式相同。请你解释清楚一点好吗?我知道了``谢谢,我已经投了赞成票,所以不能投反对票,但是当你说“同等”时,你的答案中有2分,而你真正的意思是“相同的实例”。@cpp初学者谢谢,我编辑了我的答案!据我所知,第二个
println
输出的是真还是假还没有确定。字符串常量str01可以在str1.intern()之前或之后构造。intern()将str01放入池中。第二种情况的结果取决于您选择的字符串。如果您选择一个由引导程序插入的字符串,则它将
    final String str1 = new String("str")+new String("01");
    str1.intern();
    final String str2 = "str01";
    System.out.println(str1 == str2);