Java中的参考对比和内容对比

发布于 2025-01-11 13:45:50 字数 3728 浏览 4 评论 0原文

我正在学习参考(或地址)比较和内容比较。下面的说法让我很困惑:

如果一个类没有重写 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)由于什么原因给出了 false ?是因为内容不匹配还是这里发生了参考比较?我确信答案是参考比较,因为我没有重写主类中的 .equals() 方法,并且默认情况下它使用 Object 的方法> 类(如开头的声明中所述)。

但也请考虑以下场景:

st1.equals(st2) 给出 true 是因为什么原因?内容是否匹配?是不是这里也发生了参考比较?或者说,既然内容匹配,那不是参考比较而是内容比较?或者,还有别的什么? 请解释一下。

I was learning about Reference (or Address) comparison and Content comparison. The below statement makes me confused:

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.

Point to note: I haven't overridden the .equals() method and I'm only practicing it in my main class.

Below is my code:

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.*/

    }

}

My confusion is that this t1.equals(t2) gives false because of which reason? Is it because the contents are not matching or reference comparison is happening here? I'm sure that the answer is Reference Comparison since I haven't overridden the .equals() method in my main class and by default it is using the method of the Object class (as stated in the statement at the very beginning).

But consider the below scenario too:

st1.equals(st2) is giving true because of which reason? Contents are matching? Is it not like reference comparison is happening here as well? Or, since contents are matching, it is not a reference comparison but a content comparison? Or, something else?
Please explain.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情域 2025-01-18 13:45:50

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

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

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

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

这里还有两个证据表明 String 覆盖了 Object.equals(Object)

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

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

注意

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

The String class overrides the equals method that is inherited from the Object class and implemented logic to compare the two String objects character by character.

Why you might ask, did the String class override the equals method inherited from the Object class? Because the equals method inherited from Object performs reference equality!

That's why when comparing two Strings using .equals() method, their content is compared, and not their references.

The evidence is provided by your code itself.

Here are two more pieces of evidence the String overrides the Object.equals(Object)

The Javadoc implies so. Notice that equality is based on the contents of the string. Indeed, even the existence of a distinct Javadoc for the String.equals(Object) method implies that the method has been overloaded ... given the way that javadocs are generated.

The source code says so. Clearly, the linked code is an overload. And clearly, it is not simply comparing object references.

Note

As commented, not all Strings in Java are interned. Try reading something from a file or console, those Strings aren't "interned", thus equals() (and also hashcode()) needs to be overridden.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文