1

我正在学习参考(或地址)比较和内容比较。下面的陈述让我感到困惑:

如果一个类没有覆盖 equals 方法,那么默认情况下,它会使用覆盖该方法的最近父类的 equals(Object o) 方法。

需要注意的一点:我没有重写该.equals()方法,我只是在我的主课上练习它。

下面是我的代码:

package com.reference.content.comparison;

public class ReferenceAndContentComparison {

    public static void main(String[] args) {

        /* "==" operator is used for REFERENCE (or address) comparison. It means, it check if both objects point to same memory location or not.
         * ".equals()" method is used for CONTENT comparison (in String class). It means, it check if both objects have same value or not.
         * 
         * MAIN DIFFERENCES ARE:
         * 1. "==" is an operator while ".equals()" is a method (of Object class).
         * 2. Line 7 to 8.
         * 3. ".equals()" method of Object class is used for REFERENCE comparison but in String class, it is used for CONTENT reference (by overriding .equals()).
         * 4. If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.
         * 5. When comparing two Strings using .equals() method, their content is compared, and not their references.
         *    Link for point 5: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-
         */
        String s1 = "HELLO";
        String s2 = "HELLO"; // references s1
        String s3 =  new String("HELLO"); // new instance but same content
 
        System.out.println(s1 == s2); // true; Both s1 and s2 refer to same objects. Their addresses are same.
        System.out.println(s1 == s3); // false; Addresses of s1 and s3 are different.
        System.out.println(s1.equals(s2)); // true; Content of both s1 and s2 are same. Content Reference, because s1 and s2 are string class objects.
        System.out.println(s1.equals(s3)); // true; Content of both s1 and s3 are same. Content Reference, because s1 and s3 are string class objects.
        
        System.out.println("-----");
        
        Thread t1 = new Thread();
        Thread t2 = new Thread();
        Thread t3 = t1;
        String st1 = new String("WORLD");
        String st2 = new String("WORLD");
 
        System.out.println(t1 == t3); // true; Both t1 and t3 refer to same objects. Address of t1 is assigned to t3.
        System.out.println(t1 == t2); //false; Addresses of t1 and t2 are different.
        System.out.println(st1 == st2); // false; Addresses of st1 and st2 are different.
        System.out.println(t1.equals(t2)); /* false; Here, t1 and t2 are both Thread class objects (not String class objects) and we haven't overridden the
                                            .equals() method for Thread class anywhere so by default (as per point 4), .equals() of Object class will be
                                            in effect and hence as per point 3, .equals() will be used as REFERNCE Comparison.
                                            And since addresses are different, it's false.*/
        System.out.println(st1.equals(st2)); /* true; Unlike above scenario, st1 and st2 are String class objects and hence as per point 5, content reference is
                                                happening here and since their contents are same, it is true.*/

    }

}

我的困惑是,这是t1.equals(t2)因为什么原因而给出错误的?是因为内容不匹配还是这里发生了参考比较?我确信答案是参考比较,因为我没有覆盖.equals()我的主类中的方法,并且默认情况下它使用Object类的方法(如最开始的声明中所述)。

但也要考虑以下场景:

st1.equals(st2)因为什么原因而给予真实?内容是否匹配?是不是也在这里进行了参考比较?或者,既然内容是匹配的,那就不是参考比较而是内容比较?或者是其他东西?请解释。

4

1 回答 1

1

String 类重写了从 Object 类继承的 equals 方法,并实现了逐字符比较两个 String 对象的逻辑。

为什么你可能会问,String 类是否覆盖了从 Object 类继承的 equals 方法?因为继承自 Object 的 equals 方法执行引用相等!

这就是为什么在使用 .equals() 方法比较两个字符串时,比较的是它们的内容,而不是它们的引用。

证据由您的代码本身提供。

这是 String 覆盖 Object.equals(Object) 的另外两个证据

Javadoc暗示了这一点。请注意,相等性基于字符串的内容。实际上,即使 String.equals(Object) 方法存在不同的 Javadoc,也意味着该方法已被重载……考虑到 javadocs 的生成方式。

源代码是这样说的。显然,链接代码是一个重载。显然,这不仅仅是比较对象引用。

笔记

正如所评论的,并非 Java 中的所有字符串都是实习的。尝试从文件或控制台读取某些内容,这些字符串不是“内部”的,因此需要覆盖 equals()(以及 hashcode())。

于 2022-03-02T20:19:22.443 回答