【问题标题】:String equality vs equality of location字符串相等与位置相等
【发布时间】:2010-10-10 07:48:08
【问题描述】:
String s1 = "BloodParrot is the man";  
String s2 = "BloodParrot is the man";  
String s3 = new String("BloodParrot is the man");  

System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));

// 输出
真的
真的

真的

如果所有三个字符串都具有相同的内容,为什么不是所有字符串在内存中的位置都相同?

【问题讨论】:

  • 这是 Java 还是 C#。您问题的答案似乎取决于语言。您可能希望相应地标记它。
  • 这不是重复的。这个问题更多的是关于实习字符串而不是比较它们。
  • 我想最后的评论是没有意义的,除非我提到我回滚了一个编辑,说这个问题是另一个问题的重复。如果您不同意,请随时添加链接并投票关闭。

标签: java string equality


【解决方案1】:

Java 只会自动实习字符串 literals。默认情况下,新的 String 对象(使用 new 关键字创建)不被实习。您可以使用 String.intern() 方法来实习现有的 String 对象。调用intern 将检查现有字符串池中是否存在匹配对象,如果存在则返回,如果不匹配则添加。

如果添加行

s3 = s3.intern();

在您创建 s3 后立即添加到您的代码中,您会看到输出的不同。

See some more examples and a more detailed explanation.

这当然引出了一个非常重要的话题,即在 Java 中何时使用 == 以及何时使用 equals 方法。在处理对象引用时,您几乎总是想使用equals。 == 运算符比较参考值,这几乎绝不是您要比较的意思。了解差异有助于您决定何时使用 == 或 equals

【讨论】:

    【解决方案2】:

    您为 s3 显式调用 new,这将为您留下一个新的字符串实例。

    【讨论】:

    • 哦,唯一的区别是使用了“new”关键字。那么不使用new关键字的字符串不是字符串对象的实例吗?
    • 它们是实例,但不一定有专用缓冲区。
    【解决方案3】:

    创建String 实际上是一个快速的过程。尝试查找任何以前创建的String 会慢得多。

    考虑你需要做什么才能让所有Strings 都被拘留。您需要搜索一组所有先前构造的Strings。请注意,这必须以线程安全的方式完成,这会增加开销。因为您不希望它泄漏,所以您需要使用某种形式的(线程安全的)非强引用。

    当然,您不能像这样实现 Java,因为不幸的是该库公开了 Strings 和大多数其他不可变值对象的构造函数。

    【讨论】:

      【解决方案4】:

      new 关键字总是产生一个新的字符串。

      More detail here.

      【讨论】:

        【解决方案5】:

        如果所有三个字符串都具有相同的内容,为什么不是所有字符串在内存中都具有相同的位置?

        因为它们是具有相同内容的不同字符串!

        【讨论】:

        • String s1 = "BloodParrot 是男人"; String s2 = "BloodParrot 是男人"; s1 == s2 => true 看来 s1 和 s2 是相同的字符串。
        • 这两个相同的,指向同一个地址。只有 s3 不同,因为它是作为新字符串显式创建的。
        • 不能保证 s1 和 s2 是同一个对象。
        【解决方案6】:

        有一个名为 String.intern 的方法,本质上,它获取所有相同的字符串并将它们放入哈希表中(我有点撒谎,但对此重要的是概念,而不是现实) .

        String s1 = "BloodParrot is the man";  
        String s2 = "BloodParrot is the man";  
        String s3 = new String("BloodParrot is the man").intern();  
        
        System.out.println(s1.equals(s2));
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1.equals(s3));
        

        应该让它们都是“真实的”。这是因为(我又在这里撒了一点谎,但它仍然只对概念而不是现实很重要) String s1 = "BloodParrot is the man";做了类似 String s1 = "BloodParrot is the man".intern();

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-09
          • 2021-02-15
          相关资源
          最近更新 更多