object==object,不比较引用

object==object, doesn't comparing reference

我已经覆盖了哈希码和等于找到具有相同开始日期和结束日期的值。而且我得到了重复对象的类似哈希码。当等同于这些对象时,我得到布尔值 "false"。在我的理解中,object==object 比较对象的引用,即使引用相同;代码返回 false。你能帮我理解问题是什么吗?我在下面发布了我的代码:

哈希码和等于方法

public int hashCode() {
    final int prime = 31; 
    int result = 1;
    result = prime * result + ((this.startDate == null) ? 0 : this.startDate.getDate());
    result = prime * result + ((this.closingDate == null) ? 0 : this.closingDate.getDate());
    return result;
}

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this==customer;
}

Main.java

public class HashQuestion {
    public static void main(String[]args) {
        Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
        custMap.put(1, createCustomer(1, new Date()));
        custMap.put(2, createCustomer(2, new Date()));
        custMap.put(3, createCustomer(3, new Date()));
        Customer checkCustomer = createCustomer(1, new Date());
        for (Customer cust : custMap.values()) {

            if (cust.equals(checkCustomer)) {
                System.out.println("Duplicate No: "+cust.getCustId()+ ", Start date: " + 
                        cust.getStartDate().toString() + " End date: " +cust.getClosingDate().toString());
            }
            else
                System.out.println("No: "+cust.getCustId()+ ", Start date: " + 
                    cust.getStartDate().toString() + " End date: " +cust.getClosingDate().toString());
        } 
    }

    @SuppressWarnings("deprecation")
    static Customer createCustomer(int number, Date date) {
        Date closeDate = new Date(); 
        Date startDate = new Date(); 
        closeDate.setDate(date.getDate() + number);
        startDate.setDate(date.getDate() - number);
        return new Customer(number, number+1, startDate, closeDate);
    }
}

输出:

No: 1, Start date: Wed Jun 20 19:42:46 IST 2018 End date: Fri Jun 22 19:42:46 IST 2018
No: 2, Start date: Tue Jun 19 19:42:46 IST 2018 End date: Sat Jun 23 19:42:46 IST 2018
No: 3, Start date: Mon Jun 18 19:42:46 IST 2018 End date: Sun Jun 24 19:42:46 IST 2018

checkCustomer 对象引用:Customer@643

对象引用(在地图中):[Customer@643、Customer@625、Customer@607]

此处 object1 与 checkCustomer obj 具有相同的引用。然而 obj==checkCustomer, returns false。

由此变化:

Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
custMap.put(1, createCustomer(1, new Date()));
custMap.put(2, createCustomer(2, new Date()));
custMap.put(3, createCustomer(3, new Date()));
Customer checkCustomer = createCustomer(1, new Date()); //This is a different reference

为此:

Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
Customer checkCustomer = createCustomer(1, new Date());
custMap.put(1, checkCustomer); //Now this is the same reference
custMap.put(2, createCustomer(2, new Date()));
custMap.put(3, createCustomer(3, new Date()));

您正在创建 4 个不同的客户,这将创建三个。

您正在通过

创建两个不同的对象
return new Customer(number, number+1, startDate, closeDate);

所以比较必须是假的。如果你想比较对象的属性,你必须在你的 equals 方法中实现它。

应该看起来更像:

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this.getCustId()==customer.getCustId();
}

如果您创建一个新对象(使用 "new"),这些对象在堆中将始终具有不同的地址,因此如果您比较它们,== 将始终 return 为假。

例如

Integer i1 = new Integer(1);
Integer i2 = new Integer(1);

i1.equals(i2) --> true
i1 == i2 --> false

在最后一行的 equals 方法中,您进行了引用比较 (==),您永远不应该在对象中这样做(仅限基元和枚举)。如果您使用的是 IDE(例如 eclipse),您可以使用标识对象实例的字段生成 equals 和 hashcode 方法。

所以让我把我的回答分成两部分:

(i) 对象引用如何评估为相同---- java.lang.Object提供了toString方法的实现, returns 的字符串是 class 名称后跟“at”符号 (@) 和哈希码的无符号十六进制表示形式,例如 。在你的情况下 检查客户对象参考:Customer@643 对象引用(在地图中):[Customer@643, Customer@625, Customer@607]

映射中的第一个元素和检查引用是完全不同的对象,但 toString() 方法将它们计算为相同是因为散列冲突,而您的自定义 hashCode() 方法对此有所贡献,

public int hashCode() {
    final int prime = 31; 
    int result = 1;
    result = prime * result + ((this.startDate == null) ? 0 : this.startDate.getDate());
    result = prime * result + ((this.closingDate == null) ? 0 : this.closingDate.getDate());
    return result;
}

这完全没问题,因为没有冲突就没有散列函数存在

2) 即使引用相同为什么你的 equals(Object o) 实现没有 return true ---

让我们检查一下您的 equals 方法:

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this==customer;
}

请注意“==”运算符检查两个引用是否指向同一个对象。在您的情况下,它不是 returned false 。

PS:根据经验,请考虑覆盖 toString() 方法。检查 EffectiveJava 第二版中的文章 Item10。

根据我对这个问题的分析,“==”比较的是内存地址,而不是对象引用。以下 Whosebug 问题有助于我理解这一点:

What is the difference between == vs equals() in Java?

Memory address of variables in Java

理解有误请告诉我

谢谢大家