【问题标题】:java "== " unusual behaviour [duplicate]java“==”异常行为[重复]
【发布时间】:2016-04-16 13:55:28
【问题描述】:
import java.lang.String;
public class Test {
    public static void main(String[] args) {
        String a1="ka";
        String a2="ka"; 
        System.out.println("a1==a2?  "+(a1==a2));
        String a3="k";
        String a4=new String("k");
        System.out.println("a3==a4?  "+(a3==a4))
        System.out.println("a3==a4?  "+(a3==a4.intern()));
        String a5="k";
        String a6=a4+"a";
        System.out.println("a1==a6?  "+(a1==a6));
    }
}

我得到的输出:

a1==a2?  true
a3==a4?  false
a3==a4?  true
a1==a6?  false
  • a1===a2 为真,因为第 5 行不会在字符串池区域中创建新的字符串文字。仅返回对先前创建的字符串的引用。
  • a3==a4? false as a4 将引用字符串对象而不是字符串池区域中字符串中的字符串。我的问题是,如果 a3 引用的是字符串常量而不是 String 对象,它如何能够使用 String 类的方法?
  • a4.intern() 将返回对字符串池中字符串的引用,该字符串恰好与a3 相同
  • a6=a4+"a" 将创建一个新字符串 "ka"。但这实际上利用了 StringBuilder 类及其 append 方法。然后使用 toString() 将其转换为字符串。此进程是否将新创建的字符串“ka”存储在字符串池区域中?由于字符串已经在池中,第 12 行的代码应该返回对它的引用。所以 a1==a6 应该是 true.rt? 我是java新手。请指导我在哪里做错了?

【问题讨论】:

  • 这是“奇怪”行为的答案......stackoverflow.com/a/35899981/982161
  • a6=a4+"a" 将在堆上创建一个新的字符串ka,而不管字符串常量池中是否存在"ka"。此引用将用于与字符串池中的"ka" 进行比较,因此您将得到错误。请注意,当您执行此操作时,"a" 将被添加到字符串常量池中。
  • @smasher 可能是因为这个问题每天至少被问一次。
  • 我知道 == 比较引用而不是比较字符串的内容..
  • @TheLostMind 你能否详细说明为什么新字符串将在堆中创建,而不是在通常存储字符串文字的字符串池区域中创建.. 是否由于 + 运算符在内部使用 StringBuilder 类及其方法?

标签: java string


【解决方案1】:

您错误地比较了字符串(因为您实际上是在比较引用)

Java 中的 String 类是在 java.lang 包中定义的,它就是一个,而不是像 int 或 boolean 这样的原始类型。

String 在 Java 中是不可变的和最终的,在这种情况下,JVM 使用 String Pool 来存储所有 String 对象。

创建字符串对象有哪些不同的方法?

我们可以像任何普通的java类一样使用new操作符来创建String对象,或者我们可以使用双引号(文字赋值)来创建String对象。


你的问题:

当我们使用双引号创建一个字符串时,JVM 会在字符串池中查找是否有任何其他字符串以相同的值存储。如果找到,它只返回对该 String 对象的引用,否则它会创建一个具有给定值的新 String 对象并将其存储在 String 池中。

当我们使用 new 运算符时,JVM 会创建 String 对象,但不会将其存储到 String Pool 中。我们可以使用 intern() 方法将 String 对象存储到 String 池中,或者如果池中已经存在具有相等值的 String,则返回引用。

所以当你这样做时

String s1 = "abc";
String s2 = "abc";

那些在 StringPool 中被检查,因为 s1 已经存在在那里,s2 将采用相同的引用,因此,s1 ==s2 为真。

但是当你这样做时:

String s3 = new String("abc");
String s4 = new String("abc"); 

您正在使用 new 运算符,因此 JVM 不会检查堆中是否已经存在字符串,它只会为 s4 分配一个 new 空间, s3==s4 也是如此???当然没有。

请查看下面的图片以获得更说明性的示例。

【讨论】:

  • 否决我所有的答案也不是办法......
  • 我没有给你投反对票,但你 100% 确定你说的是对的吗?
  • 如果您认为您对其他一些 类似 问题的回答对 OP 有帮助,请发表评论链接到您的回答。复制粘贴完全相同的答案是不可接受的
  • 对不起,但绝对不应该复制粘贴答案。这是不可接受且非常糟糕的行为。如果它是重复的,请将其关闭。不要复制粘贴答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 2018-03-09
  • 1970-01-01
相关资源
最近更新 更多