繁体   English   中英

为什么此Java代码成功编译

[英]Why this Java Code is compiling successfully

我没有重写很多hashCode()equals()方法,所以我可能是错的。我的问题是最后一行

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

15   15    false

我期望15 15为真,因为我正在用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));
    }
}

首先,出于这样的原因进行编译: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替换为某些其他实现(例如,同时考虑idname的实现),则代码重构将无法幸免。 如果要依靠比较ID,则直接比较ID,而无需调用hashCode来获取它们。

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

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

更具体地说,请阅读JLS

类C声明或由类C继承的实例方法mC,从C重写在类A中声明的另一方法mA, 前提是以下所有条件均成立:... mC的签名是签名的子签名(第8.4.2节)毫安

在这种情况下, boolean equals(Department department) 不是 boolean equals(Object obj)签名。

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

其次,由于您无法覆盖特定自定义类型的equal方法,因此您在这两个类中均未覆盖默认实现。

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

更换

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

通过

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM