Java中的String和StringBuilder之间的.equals方法

12
class returntest
{



public static void main(String...args)
{

String name1 = "Test";
String s = new String("Test");
StringBuilder sb = new StringBuilder("Test");

System.out.println(name1.equals(sb)); //Line 1
System.out.println(name1.equals(s));  //Line 2
System.out.println(s.equals(sb));     // Line 3
System.out.println(s.equals(name1));  //Line 4
}

}
以下是输出结果。
false
true
false
true

第一行返回并且第三行返回 false。

我不明白为什么编译器不认为"name1"和"sb"包含相同的值。

同样,编译器不认为"s"和"sb"包含相同的字符串(两者都是非原始类型)。

有人能解释一下第一行和第三行的输出吗?


另外,第2行的name1.equals(s)和第4行的s.equals(name1)进行了相同的比较。 - Upulie Han
12个回答

9
因为它们是不同的 "对象"。
String object!= StringBuilder object.

但是,你的疑问是什么?
name1.equals(s)  returning true

因为在String类中,equals方法被重写了。

为了获得所需的输出,请将您的StringBuilder转换为String

System.out.println(s.equals(sb.toString())); //return true.

如果您查看String#equals()的源代码

,您会发现:

1012    public boolean  equals(Object anObject) {
1013        if (this == anObject) {
1014            return true;
1015        }
1016        if (anObject instanceof String) {             //key line 
1017            String anotherString = (String)anObject;
1018            int n = count;
1019            if (n == anotherString.count) {
1020                char v1[] = value;
1021                char v2[] = anotherString.value;
1022                int i = offset;
1023                int j = anotherString.offset;
1024                while (n-- != 0) {
1025                    if (v1[i++] != v2[j++])
1026                        return false;
1027                }
1028                return true;
1029            }
1030        }
1031        return false;
1032    }

如果你传递的是 StringBuilder ,那么 if(anObject instanceof String){这行代码始终返回false。


8
两个false的原因是它们对应的equals(Object)方法是这样指定的。
  • 对于String.equals(Object),javadoc指定如下:

    "将此字符串与指定对象比较。当且仅当参数不为null并且是一个表示与此对象相同字符序列的String对象时,结果为true。"

  • 对于StringBuilder.equals(Object)equals方法继承自Object,其javadoc如下:

    "如果该对象和obj参数相同,则返回true;否则返回false。"

因此,第1行和第3行String.equals(Object)返回false,因为sb不是一个String
如果你反过来调用sb.equals(name1)sb.equals(s)也会得到false,因为sb.equals(...)测试的是同一个对象。

我不明白为什么编译器不认为"name1"和"sb"包含相同的值

正如你所看到的,与编译器无关,一切都与equals方法的指定方式有关。

2

使用sb.toString()而不是直接使用sb

这将该字符串与指定对象进行比较。

        System.out.println(name1.equals(sb.toString())); //Line 1
        System.out.println(name1.equals(s));  //Line 2
        System.out.println(s.equals(sb.toString()));     // Line 3
        System.out.println(s.equals(name1));  //Line 4

这将对所有行返回true值。

true
true
true
true

2

String.equals比较的不是内容,而是对象。

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        ...
    }
    return false;
}

StringBuilder没有覆盖equals方法,而是继承了Object.equals方法。

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

2

这个问题“Java中比较字符串和对象值的问题”已经被重复提问,所以在这里发布答案。

由于StringStringBufferStringBuilder都实现了CharSequence接口,因此您可以使用String类中的contentEquals方法来检查内容的相等性。

    "java".contentEquals(new StringBuffer("java")); // true
    "java".contentEquals(new StringBuilder("java")); // true

1
I dont understand why compiler does not think "name1" and "sb" as containing the same value

因为 equals() 检查对象的引用相等而不是它们的内容,如果要使用它来比较这些对象实际包含的内容,则需要重写该方法。正如您所知,字符串类也覆盖了此方法。
在这里,
String name1 = "Test";
StringBuilder sb = new StringBuilder("Test");

name1是一个字符串类型的引用,指向字符串"Test",而sb包含了一个StringBuilder类型对象的引用,因此它们有完全不同的引用。因此equals返回false。

现在,为什么System.out.println(name1.equals(s));打印出true呢?因为字符串字面量可以被interned,当你执行String s = new String("Test");时,使用的是内部化字符串对象的引用,因此它们包含相同的引用。

正如其他人建议的那样,你应该使用sb.toString()而不是sb

查看对象类型和引用类型之间的区别以进一步澄清你的概念。


1

.equals()检查两个对象是否相等。通常涉及检查两个对象是否为相同类型。

如果您只想检查值是否相等,应使用sb.toString()

System.out.println(s.equals(sb.toString()));

0

System.out.println(s.equals(sb));
你会得到false,因为String类的equals()方法实现是传递null或其他非String对象时返回false。

    public boolean equals(Object object){
          if(object instanceOf String){
             //do contnet comparison here
             //if both contents equal return true else fale
          }
          return false;
    }

0

StringStringBuilder是两个不同的类。在equals()实现中,会先检查类型相等性,然后再检查内容。


0

'name1'和's'是"String"类型的对象。但是"sb"是"StringBuilder"类型的。

通常,equals()方法会检查引用和类型。因此,对于上述2个和4个语句,它返回true,因为它们都是相同的。

但是,StringBulider对象"sb"和s、name1在类型上不同。因此,它返回false。

如果您仍然希望获得期望的true结果进行比较,请使用sb.toString()并与上述值(s,name1)进行比较。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接