8
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

第 1 行返回,第 3 行返回 false。

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

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

有人可以解释 line1 和 line3 输出吗?

4

12 回答 12

8

因为他们都是不同的objects

String object!= StringBuilder object.

但是,你的疑问是

name1.equals(s)  returning true

因为在 String 类中,equals 方法以这种方式被过度验证。

并获得所需的输出将您转换StringBuilderString.

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    }

如果您通过,该行 if (anObject instanceof String) { 总是返回 false StringBuilder

于 2013-08-31T05:27:10.050 回答
6

这两种false情况的原因是这就是指定equals(Object)各自方法的工作方式。

  • 对于String.equals(Object),javadoc 是这样说的:

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

  • 对于StringBuilder.equals(Object),该equals方法是从 继承的Object,javadoc 是这样说的:

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

所以在第 1 行和第 3 行,String.equals(Object)返回false因为sbis not a String

如果你反转它并调用sb.equals(name1),否则sb.equals(s)你也会得到false......因为sb.equals(...)正在测试同一个对象。


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

正如您所看到的,它与编译器无关……而与指定equals方法的方式有关。

于 2013-08-31T05:54:01.503 回答
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
于 2013-08-31T05:26:29.127 回答
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);
}
于 2013-08-31T05:31:26.263 回答
2

关于比较字符串和对象值 Java的问题已复制到此问题,因此在此处发布答案

由于String和正在实现StringBuffer,您可以使用String中的方法检查内容的相等性StringBuilderCharSequencecontentEquals

    "java".contentEquals(new StringBuffer("java")); // true
    "java".contentEquals(new StringBuilder("java")); // true
于 2016-11-08T05:41:13.020 回答
1

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

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

System.out.println(s.equals(sb.toString()));
于 2013-08-31T05:27:39.653 回答
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”的引用,其中 String 类型和 sb 包含对 StringBuilder 类型对象的引用,因此它们具有完全不同的引用。因此equals返回false。

现在,为什么要System.out.println(name1.equals(s));打印 true ,因为字符串文字可以被实习,并且当你这样做时String s = new String("Test");,使用实习字符串对象的引用,因此它们包含相同的引用。

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

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

于 2013-08-31T05:32:21.863 回答
0

StringBuilder 不会覆盖 equals 方法。它从 Object 类继承 equal 方法。除非您将引用与相同的对象进行比较,否则它将返回 false。

String 覆盖了 equals 方法,所以如果它们有意义地等价,对象将返回 true。

于 2013-08-31T06:54:23.920 回答
0

“name1”和“s”是“String”类型的对象。但是“sb”的类型是“StringBuilder”。

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

但是 StringBulider 对象“sb”和 s,name1 不是相同的 wrt 类型。所以它返回false。

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

于 2013-08-31T05:44:16.827 回答
0

一个简单的答案是,你不比较苹果和橘子。我们人类知道这些是相同的,编译器是一个不能充当人类智能的程序。

同理,你不能说两个物体,一个是汽车,另一个是同一辆车的拆卸零件。虽然两者具有相同的配置:)

StringBuilder 和 String 是完全不同的对象。

于 2013-08-31T05:44:59.940 回答
0

String并且StringBuilder是两个不同的类别。 equals()实现在检查内容之前检查类型相等性。

于 2013-08-31T05:36:44.927 回答
0

System.out.println(s.equals(sb));
由于实现了 String 类equals()方法,因此您将得到 false,因此传递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;
    }
于 2013-08-31T05:42:08.097 回答