【问题标题】:StringBuilder .equals JavaStringBuilder .equals Java
【发布时间】:2013-09-05 02:51:23
【问题描述】:
class strb
{

    static public void main(String...string)
    {
         StringBuilder s1 = new StringBuilder("Test");
         StringBuilder s2 = new StringBuilder("Test");

         System.out.println(s1);
         System.out.println(s2);
         System.out.println(s1==s2);
         System.out.println(s1.equals(s2)); //Line 1
         System.out.println(s1.toString()==s2.toString()); //Line 2
         if(s1.toString()==s2.toString())System.out.println("True"); //Line 3
    }

}

输出是

Test
Test
false
false

对 .equals 有一个简短的问题。

无论对象内容如何,​​.equals 是否仅在两个对象引用都指向同一个对象时才返回 true ?


编辑:现在我了解了关于.equals 的部分,但是为什么第2 行和第3 行也没有返回true?

编辑:我相信== 会查看引用变量的地址,因此 s1 和 s2 不能相等。如果我的假设不正确,请纠正我

【问题讨论】:

标签: java


【解决方案1】:

对于您的第一个答案,请查看@abmitchell 的答案

为了您的编辑:

在 Java 中,String 是一个对象,我们不能使用 == 比较对象的值相等性

== 用于比较原始值或对象引用。

为了比较 Object 的值,我们在 Java 中使用 equals()

【讨论】:

    【解决方案2】:

    是的,StringBuilder does not override Object's .equals() function,表示两个对象引用不一样,结果为假。

    对于StringBuilder,您可以使用s1.toString().equals(s2.toString())

    对于您的编辑,您在两个不同的 String 对象上调用 == 运算符。 == 运算符将返回 false,因为对象不同。要比较字符串,需要使用String.equals() 或String.equalsIgnoreCase()

    这和你之前遇到的问题一样

    【讨论】:

    • 你知道StringBuilder为什么不重写equals()方法吗,好像很奇怪。
    • 基本上,如果我不得不猜测,如果您有两个 StringBuilder,您更有可能测试它们是否是构建字符串的相同 StringBuilder,而不是使用相同字符串的两个不同构建器.我想不出很多情况下两个不同的实例化 StringBuilder 会构建相同的东西。
    • 关于你的第一句话,我认为“==”测试了引用,“.equals()”测试了对象值?
    • 我认为 StringBuilder() 不能只比较对象值!!
    【解决方案3】:

    Object 类的.equals 的默认实现如您所述。

    其他类可以覆盖此行为。 StringBuilder 不是其中之一。

    String 是其中之一,它会覆盖它以确保两个对象的 String 表示产生相同的字符序列。 String API

    请参阅相关特定对象的文档。

    【讨论】:

      【解决方案4】:

      StringBuilder和StringBuffer没有覆盖Object类的equals函数,但是string覆盖了equals方法。 Object的作用是这样的

      public boolean equals(Object obj) {
          return (this == obj);
          }
      

      你可以这样写代码。

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

      【讨论】:

        【解决方案5】:

        StringBuilder 类没有像 String 类中那样实现 equals() 方法。

        所以它执行默认的 Object 类功能,它再次只检查地址等效性,在这种情况下是不同的。所以它打印错误。

        注意 1:您也可以在对象上使用== 运算符,但它只是检查两个对象的地址是否相同。

        注意2:==运算符在比较字符串常量池中创建的两个String对象时起到了很好的作用,以判断它是否真的在字符串常量池中创建了一个新对象。

        【讨论】:

          【解决方案6】:

          同意以上两个回答,但我值得注意的是实际比较你可以做的内容:

          System.out.println(s1.toString().equals(s2.toString())); //Line 1
          

          【讨论】:

            【解决方案7】:

            查看equals方法的合约:

            它必须是一致的(如果对象没有被修改,那么它必须保持返回相同的值)。

            这就是为什么 StringBuilder 无论其内容如何都不会覆盖它的原因。

            我们以上面的例子为例。

                 StringBuilder s1 = new StringBuilder("Test");
                 StringBuilder s2 = new StringBuilder("Test");
            

            也许,对您而言,由于当前的运行时间值,s1.equals(s2) 会返回 true。

            但是如果你改变添加行呢:

                s1.append("abc");
            

            那么s1和s2会有不同的字符串内容,s1.equals(s2)应该是false。但这与一致性相矛盾。

            【讨论】:

            • “检查equals方法的契约”很好地解释了为什么StringBuilder没有实现.equals()。很好的答案。
            • 我很抱歉,但这仍然违反了最小惊讶。以您对章程的解释:“如果未修改对象”。那么对象被修改了。 equals() 方法的目标是评估两个对象的功能等效性。根据您的评估,“一致性”永远不会被任何对象违反,因为任何对象,无论是可变的还是其他的,都不会属于该类别。当一个对象发生突变时(例如.append()),equals() 的契约应该总是反映内容的变化。
            【解决方案8】:

            StringBuilder 类不提供重写的equals() 方法。因此,当在StringBuilder 的实例上调用该方法时,将执行该方法的Object 类实现,因为StringBuilder extends Object。

            源代码是

            public boolean equals(Object obj) {
                return (this == obj);
            }
            

            这只是比较引用相等性。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-06-22
              • 1970-01-01
              • 2011-01-26
              • 1970-01-01
              • 2012-02-20
              相关资源
              最近更新 更多