String和StringBuilder之间的Java .equals

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输出吗?

因为它们都是不同的objects

 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 } 

if (anObject instanceof String) {如果传递StringBuilder则总是返回false。

两个false情况的原因是这是指定相应的equals(Object)方法的工作方式。

  • 对于String.equals(Object) ,javadoc说:

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

  • 对于StringBuilder.equals(Object)equals方法inheritance自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方法的方式有关的一切。

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

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

StringBuilder根本不重写equals并inheritanceObject.equals

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

直接使用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 

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

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

 System.out.println(s.equals(sb.toString())); 
 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"); 使用interned string对象的引用,因此它们包含相同的引用。

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

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

StringStringBuilder是两个不同的类。 equals()实现在检查内容之前检查类型相等。

System.out.println(s.equals(sb));
由于实现了String类equals()方法,因此传递nullString对象以外的函数会给出false。

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

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

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

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

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

StringBuilder不会覆盖equals方法。它从Object类inheritanceequal方法。除了与相同对象进行比较的引用之外,它将返回false。

String会覆盖equals方法,因此如果对象有意义等效,则返回true。

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

这是因为你不能说两个物体是汽车而另一个是同一辆汽车的拆卸部件。 虽然两者都有相同的配置:)

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

关于比较字符串和对象值的问题问题Java已经复制到这个问题,所以在这里发布答案

由于StringStringBufferStringBuilder正在实现CharSequence您可以通过在String中使用contentEquals方法来检查内容的相等性

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