zoukankan      html  css  js  c++  java
  • "==" equals和hashCode的联系和区别

    写这篇文章的目的是自己彻底把三者搞清楚,也希望对你有所帮助。

    1."=="运算符对与基本类型(int long float double boolean byte char short),比较的是他们的值。但是对于复合数据类型,比较的是他们的内存地址。

    public class TestString {
        public static void main(String[] args){
            String s1="Hello";
            String s2="Hello";
            if(s1==s2){
                System.out.println("s1==s2");
            }else{
                System.out.println("s1!=s2");
            }
        }
        
    }

    运行结果 s1==s2

    public class TestString {
        public static void main(String[] args){
            String s1=new String("Hello");
            String s2=new String("Hello");
            if(s1==s2){
                System.out.println("s1==s2");
            }else{
                System.out.println("s1!=s2");
            }
        }
        
    }

    运行结果 s1!=s2

    分析:

    当我们用String s1="Hello",再创建String s2="Hello"的时候,他会先去字符串缓冲池寻找相同的对象,因为我们之前创建了s1,s1被放在了字符串缓冲池中,

    所以s2创建的时候,就找到了相同的值s1,s1和s2指向同一个对象。

    当我们使用new的时候,就会新开辟一个内存地址,无论你怎么比较都不会相等的。

    public class TestString {
        public static void main(String[] args){
            String s1="Hello";
            String s2=new String("Hello");
            if(s1==s2){
                System.out.println("s1==s2");
            }else{
                System.out.println("s1!=s2");
            }
        }
        
    }

    所以这个比较结果返回的也是s1!=s2,因为当我们用String s1="Hello"的时候,这个时候字符串缓冲池存在值Hello,但是接下来String s2=newString("Hello");他会怎么办呢,他会先去字符串缓冲池去找,如果池子没有Hello,他会在字符串缓冲池创建一个字符串常量“Hello”,如果存在就不在字符串缓冲池中创建。然后会在堆中创建一个新的对象(无论字符串缓冲池有没有都会执行)。所以说两者内存地址不相等。

    2.equals是Object基类中的一个方法,java中所有的类都是继承Object 这个基类的。这个方法初始也是比较两者的内存地址的,这是原始的Object中的equals方法源码

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

    很明显的看到方法里面的==,说明比较的是内存地址。

    但是有一些类中有自身的equals方法把原本的方法覆盖掉了,就不再是比较两者的内存地址了,而是比较的内容值,例如String中的equals源码

     public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }

    解释:如果是对象类型直接比较内存地址,如果是String类型逐一比较内容值。

    public class TestString {
        public static void main(String[] args){
            String s1="Hello";
            String s2=new String("Hello");
            if(s1.equals(s2)){
                System.out.println("s1==s2");
            }else{
                System.out.println("s1!=s2");
            }
        }
        
    }

    结果返回:s1==s2。

    注意:那这样的代码又会返回什么结果呢?

    public class TestString {
        public static void main(String[] args){
            String s1="Hello";
            String s2=new String("Hello");
            s2=s2.intern();
            if(s1==s2){
                System.out.println("s1==s2");
            }else{
                System.out.println("s1!=s2");
            }
        }
        
    }

    返回结果:s1==s2。为什么??答案:String#intern方法,这个方法是一个 native 的方法,“如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回”。

    3.hashCode方法也是从Object类中继承过来的,它是用来鉴定两个对象是否相等,Object类中的的hashCode返回的是对象在内存中地址转换成的一串int数值,如果没有重写hashCode方法,任何对象的hashCode都不会相等的。恰恰String的hashcode重写了,你说气人不。如果两个对象equals相等,则hashCode必须相等,反之不成立。一般来说你重写了equals,也要重写HasCode。

  • 相关阅读:
    重温数据结构与算法(1) 构建自己的时间测试类
    读<<CLR via C#>>总结(11) 详谈事件
    读<<CLR via C#>>总结(13) 详谈泛型
    重温数据结构与算法(2) 编程中最常用,最通用的数据结构数组和ArrayList
    由String类的Split方法所遇到的两个问题
    读<<CLR via C#>>总结(6) 详谈实例构造器和类型构造器
    让我们都建立自己的知识树吧
    读<<CLR via C#>>总结(5) 如何合理使用类型的可见性和成员的可访问性来定义类
    读<<CLR via C#>>总结(10) 详谈委托
    读<<CLR via C#>>总结(4) 值类型的装箱和拆箱
  • 原文地址:https://www.cnblogs.com/yyfyl/p/10285363.html
Copyright © 2011-2022 走看看