为什么这个Java代码正在成功编译

时间:2016-12-19 09:55:42

标签: java compilation equals hashcode

我还没有覆盖很多 hashCode() equals()方法,所以我可能错了 我的问题是最后一行

dep1.equals(emp2)正在成功编译(为什么)(我期待编译错误,因为它们有不同的类型)并且在编译之后我得到了以下

15   15    false

我期待 15 15 true 因为我正在检查equals方法中的哈希码。

class Employee {
    private String name;
    private int id;

    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }


    public int hashCode() {
        return this.id; 
    }

    public boolean equals(Employee employee) {
        return this.hashCode() == employee.hashCode();
    }


    public int getEmployeeId() {
        return this.id;
    }
}

class Department {
    private String name;
    private int id;

    public Department(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public int hashCode() {
        return this.id; 
    }

    public boolean equals(Department department) {
        return this.hashCode() == department.hashCode();
    }


    public int getDepartmentId() {
        return this.id;
    }
}


public class JavaCollections {
    public static void main(String args[]) {
        Employee emp2 = new Employee("Second Employee", 15);

        Department dep1 = new Department("Department One", 15);

        System.out.println(dep1.hashCode()+"  "+emp2.hashCode()+"  " + dep1.equals(emp2));
    }
}

3 个答案:

答案 0 :(得分:3)

首先,由于编译的原因:Java中的所有类都继承自java.lang.Object,它定义了equals(Object)方法,并提供了默认实现。这是您在比较EmployeeDepartment时调用的方法,而不是您提供的重载之一。

您的equals代码编译得很好,因为编译器在您实际上没有知道您认为自己是否覆盖了equals。编译器认为您要创建一个新方法

public boolean equals(Department department)

Department个对象与其他Department个对象进行比较。

如果您正在编写覆盖超类方法的代码,请向其添加@Override注释,如下所示:

@Override
public boolean equals(Department department)

现在,编译器会正确地向您抱怨您的方法实际上没有覆盖其基类中的方法,在编译时提醒您注意该问题。

要修复您的代码,请更改equals的签名以Object,添加@Override,检查null以及正确的类型,执行转换,然后做实际比较:

@Override
public boolean equals(Department obj) {
    if (obj == null || !(obj instanceof Department)) {
        return false;
    }
    Department dept = (Department)obj
    return dept.id == id;
}

注意:像这样实施equals

return this.hashCode() == department.hashCode();

非常脆弱。虽然它适用于您的情况,但是当哈希代码是对象的唯一ID时,当hashCode被其他实现替换时,这将无法在代码重构中存活,例如,同时考虑两者的实现{ {1}}和id。如果您想依靠比较ID,请直接比较ID,而无需调用name来获取ID。

答案 1 :(得分:1)

这是因为类EmployeeDepartment仍然没有覆盖从public boolean equals(Object obj)类继承的方法Object

确切地说,此方法是在dep1.equals(emp2)中调用的,而不是public boolean equals(Department department)

更具体地说,请阅读JLS

  

在C类中声明或继承的实例方法mC,覆盖C类中声明的另一个方法mA,iff以下所有条件都为真:   ...    mC的签名是mA签名的子签名(§8.4.2)。

在这种情况下,boolean equals(Department department) 不是 <{1}}的子签名。

答案 2 :(得分:0)

首先,此代码dep1.equals(emp2)调用Object类的默认实现。

其次,U并没有覆盖你的两个类中的默认实现becoz u cant override for specific method for specific customizied types。

如果你需要你的答案是15 15真的

替换

public boolean equals(Department department) {
        return this.hashCode() == department.hashCode();
    }

通过

@override
public boolean equals(Object department) {
        return this.hashCode() == department.hashCode();
    }