使用Java中的==运算符进行对象比较

时间:2017-07-02 09:02:14

标签: java

据我所知,==运算符用于参考比较,即两个对象是否指向相同的存储位置。 为了测试这个,我创建了一个小的java程序,但结果并不一致。有没有人对此有任何线索?

import java.util.HashSet;
import java.util.Set;

public class EqualOperatorTest {
    public static void main(String[] args) {
        boolean result;
        Employee employee1 = new Employee();
        employee1.setId(1);
        employee1.setName("XYZ");

        Employee employee2 = new Employee();
        employee2.setId(1);
        employee2.setName("XYZ");

        result = employee1.equals(employee2);
        System.out.println("Comparing two different Objects with equals() method: " + result);  //1. This returns True. Ok as we have overridden equals

        result = (employee1 == employee2);
        System.out.println("Comparing two different Objects with == operator: " + result);   //2. This returns False. Why? hashcode of both employee1 and employee2 are same but still == comparison returning false.

        //3. Validating hashcode of reference variables employee1 and employee2. We can see both has same hashcode (bcos we have overridden hashcode too in Employee class). But then why above employee1 == employee2 is returning false. Afterall == compares the memory location (or hashcode) and both have the same hashcodes,
        System.out.println("employee1 : " + employee1);   //employee1 and employee2 has same hashcode   
        System.out.println("employee2 : " + employee2);   //employee1 and employee2 has same hashcode   

        // Creating hashset and storing the same employee references.
        Set empSet = new HashSet();
        empSet.add(employee1);
        empSet.add(employee2);

        System.out.println(empSet);   //returns only one memory location(hashcode) as we have overridden hashcode in Employee class. Ok

        employee1 = employee2;      //Setting employee2 in employee1
        result = (employee1 == employee2);
        System.out.println("Comparing two reference pointing to same Object with == operator: " + result);  //This returns True. Ok 

    }
}
  

需要理解为什么==运算符的行为在2和3处不相同。

我的Employee类很简单,有两个类级变量,它们的getter和setter以及重写的equals和hashcode方法

public class Employee {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

2 个答案:

答案 0 :(得分:1)

If the character is '@', all characters where isalpha() returns TRUE are included. Normally these are the characters a to z and A to Z, plus accented characters. To include '@' itself use "@-@". 比较两个变量的引用这一事实是正确的,引用与哈希码不同。

哈希码是您编写的此方法返回的数字:

==

引用是存储对象的内存位置。它们完全不同。

你有这种误解是可以理解的。如果您没有覆盖@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } ,它将返回对象的内存位置,因此哈希代码将与内存位置相同。但是,由于您已覆盖hashCode,因此它们不再相同。

答案 1 :(得分:0)

运算符==检查两个引用是否指向内存中的同一对象(对于intdouble运算符==等基本类型检查相等的值。)

Employee a = new Employee(...); 
Employee b = new Employee(...);

System.out.println(a == b); // false
System.out.println(b == a); // false
System.out.println(a == a); // true
System.out.println(b == a); // true

Employee c = b;
System.out.println(a == c); // the same as a == b
System.out.println(b == c); // the same as b == b

Object#equals(Object)检查两个对象的内容是否相同。

Employee a = new Employee(1, "XYZ");
Employee b = new Employee(1, "XYZ");

// if Employee#equals(Object); is overridden so that, 
// it checks both id and name for equality 
// then we can expect that all these lines returns true
System.out.println(a.equals(b)); // true
System.out.println(b.equals(a)); // true
System.out.println(a.equals(a)); // true
System.out.println(b.equals(b)); // true

Employee c = b;
System.out.println(a.equals(c)); // this is the same as a.equlas(b);

Employee d = new Employee(2, "ABC");
System.out.println(a.equals(d)); // false 

Object#hashCode()返回标识内容的整数(如果两个对象相等,则哈希码必须相同)。

Employee a = new Employee(1, "XYZ");
Employee b = new Employee(1, "XYZ");

System.out.println(a.hashCode() == b.hashCode());  // true expected since a and b are equal

Employee c = b;
System.out.println(a.hashCode() == c.hashCode()); // the same as a.hashCode() == b.hashCode()

Employee d = new Employee(1, "xyz");
// might be false, but can be true, 
// it all depends on quality of hashCode() implementation
System.out.println(a.hashCode() == d.hashCode()); 
基于哈希的数据结构中使用

Hashcodes 来查找对象i的desination索引。即index索引存储对象的位置。假设Employee#hashCode()20返回1, "XYZ"。如果hashmap的基础数组的大小为11,则目标索引将为20 modulo 11;9)。因此,当您调用hashSet.contains(new Employee(1, "XYZ"));时,它将查看索引9。请注意,完美哈希函数会返回给定值的唯一编号不存在,也就是说,您的hashCode()实现可能会返回编号{{ 1}}也用于属性值:20(小写),它产生相同的哈希索引"1, "xyz"。因此,在hashset在索引9找到对象之后,它还必须执行相等性检查以确保存储在索引9的对象等于在9中传递的对象。