== 与 equals的区别

==: 

  它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)

equals():

  它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

    ● 情况1: 类没有覆盖equals() 方法。则通过equals( 比较该类的两个对象时,等价于通过"==”比较这两个对象。

    ● 情况2: 类覆盖了equals() 方法。一般,我们都覆盖equals() 方法来两个对象的内容相等;若它们的内容相等,则返回true (即,认为这两个对象相等)。

例:

public class Test {
    public static void main(String[] args) {
        String a = new String("ab"); // a为一个引用
        String b = new String("ab"); // b为另一个引用,对象的内容一样
        String aa = "ab"; //放在常量池中
        String bb = "ab"; //从常量池中查找
        if (aa == bb) // true   同一地址
            System.out.println("aa==bb");
        if (a == b) // false, 非同一对象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }

    }
}

  

运行结果:

  

结果说明:

  ● String中的equals 方法是被重写过的,因为object 的equals 方法是比较的对象的内存地址,而String 的equals 方法比较的是对象的值。

  ● 当创建String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。

新建一个Student类不重写equals和hashcode,并在上测试类中添加以下代码:

Student student1 = new Student(18, "zhangsan"); //两个对象地址不同值相同
Student student2 = new Student(18, "zhangsan");
System.out.println("stusent1"+student1);
System.out.println("stusent2"+student2);
if (student1==student2){  //false 非同一地址
        System.out.println("stu1==stu2");
}
if (student1.equals(student2)){   //false 值相等但未重写equals方法,故等价于使用==
        System.out.println("stu1EQUstu2");
}

输出结果:

  两个对象地址不同值相同。

  

只重写equals:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                name.equals(student.name);
    }

输出结果:

  只重写equals就可以判断两个地址不相同的对象是否值相等了。

  

此时在测试类中将两个对象放入一个散列集合中:

        HashSet<Student> set = new HashSet<>();
        set.add(student1);
        set.add(student2);
        System.out.println(set);        

输出结果:

  此时未重写hashcode发现两个值一样的对象被存入了散列集合中,这与散列集合的特性相违背。(也重写了toString便于观察)

  

 重写hashcode方法:

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }

输出结果:

  此时可以看到两个对象引用的对象其实是一个地址,即只有一个实例化的Student对象,而且set散列集合中也只有一个对象。避免对象存储于散列集合是出现不必要的错误。

  这里虽然两个引用指向对象的值和地址都相同即指向堆中的同一个对象,但是这两个引用的物理地址是不相同,故不满足"stu1==stu2"

  

注意:如果要比较两个对象的值是否相等,必须重写equals方法,如果还要将此对象存储于散列集合中必须要重写hashcode

原文地址:https://www.cnblogs.com/firecode7/p/13232267.html