逻辑相等与对象引用相等

Logical Equality versus Object Reference Equality

我正在学习OCA 8 认证。 Java 中的 "Logical Equality" 是什么意思?

我有这个案例:

String s1 = new String("java");
String s3 = new String("java");
StringBuilder s2 = new StringBuilder("java");
StringBuilder s4 = new StringBuilder("java");

if (s1 == s2)      {    System.out.print("1"); } //error
if (s1.equals(s2)) {    System.out.print("2"); } //false
if (s1.equals(s3)) {    System.out.print("3"); } //true
if (s2.equals(s4)) {    System.out.print("4"); } //false

部分:

对象 String 上的方法 equals() 被重新定义以将对象的值与另一个对象的值进行比较。出于这个原因,当我执行该行时:

if (s1.equals(s3)) {    System.out.print("3"); } 

我有结果 3.

在对象 StringBuilder 上,方法 equals() 未重新定义,因此它将比较对象引用是否相等。出于这个原因,当我执行代码行时:

if (s2.equals(s4)) {    System.out.print("4"); }

我有结果false

我的问题是:

  1. Why when i excecute if(s1 == s2) i will be a compile error ?
  2. Why when i excecute s1.equals(s2) it is false ?
  1. 是的。因为 String 不是 StringBuilder。你会得到 "incompatible operand types String and StringBuilder"(因为 String 不是 StringBuilder)。
  2. 同样,因为 String 不是 StringBuilder。您可以使用 s1.equals(s2.toString())(即 true)。
  • Why when i excecute if(s1 == s2) i will be a compile error ?

== 运算符是 reference equality operator。引用 JLS:

It is a compile-time error if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5).

在您的例子中,两个操作数的类型为 StringStringBuilder,它们不兼容:String 无法转换为 StringBuilder和 vice-versa.

  • Why when i excecute s1.equals(s2) it is false ?

StringStringBuilder 是两种不同的类型。 String 中的 equals() 方法检查给定的参数是否也是 String 类型,这里不是这种情况,因此 String 的实例永远不会等于一个StringBuilder.

的实例

我刚刚发现原因here

1012    public boolean equals(Object anObject) {
1013        if (this == anObject) {
1014            return true;
1015        }
1016        if (anObject instanceof String) {
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    }

我很困惑,因为 equals 方法接受了一个类似对象的参数(为此,我认为它在方法内部被视为一个对象,但我看到它是第二个 if 条件仅适用于 String 对象(在此我找到了关于逻辑相等性问题的答案)。 谢谢大家