简体   繁体   English

为什么此Java代码成功编译

[英]Why this Java Code is compiling successfully

I haven't overridden much of hashCode() and equals() methods so I may be wrong My question is for the last line where 我没有重写很多hashCode()equals()方法,所以我可能是错的。我的问题是最后一行

dep1.equals(emp2) is being compiled successfully(why) (I am expecting compilation error as they have different types) and after compiling I get following dep1.equals(emp2)正在成功编译(为什么)(我期望编译错误,因为它们具有不同的类型),并且在编译之后,我得到以下结果

15   15    false

where I am expecting 15 15 true since I am checking the hashcode in the equals method. 我期望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));
    }
}

First, for the reason why this compiles: all classes in Java inherit from java.lang.Object , which defines equals(Object) method, and provides a default implementation. 首先,出于这样的原因进行编译:Java中的所有类都继承自java.lang.Object ,该类定义了equals(Object)方法,并提供了默认实现。 This is the method that you call when you compare an Employee and a Department , not one of the overloads that you have provided. 这是在比较EmployeeDepartment时调用的方法,而不是您提供的重载之一。

Your equals code compiles fine, because the compiler does not know that you thought you were overriding equals when you actually didn't. 您的equals代码可以很好地编译,因为编译器不知道您认为自己实际上覆盖了equals ,而实际上却没有。 The compiler thinks that you want to make a new method 编译器认为您想创建一个新方法

public boolean equals(Department department)

to compare Department objects to other Department objects. 比较Department对象和其他Department对象。

If you are writing a code that overrides a method of a superclass, add @Override annotation to it, like this: 如果要编写覆盖超类方法的代码,请向其添加@Override注释,如下所示:

@Override
public boolean equals(Department department)

Now the compiler will correctly complain to you that your method does not in fact override a method in its base class, alerting you to the problem at compile time. 现在,编译器将正确地向您抱怨您的方法实际上并未覆盖其基类中的方法,从而在编译时向您发出警告。

To fix your code change the signatures of equals to take Object , add @Override , check for null and for the correct type, do the cast, and then do the actual comparison: 要修复您的代码,请将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;
}

Note: Implementing equals like this 注意:这样实现equals

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

is very fragile. 非常脆弱 Although it works in your case, when hash code is a unique ID of the object, this wouldn't survive a code refactoring when hashCode is replaced with some other implementation, for example, an implementation that considers both id and name . 尽管它适用于您的情况,但是当哈希码是对象的唯一ID时,如果将hashCode替换为某些其他实现(例如,同时考虑idname的实现),则代码重构将无法幸免。 If you want to rely on comparing IDs, compare IDs directly, without calling hashCode to get them. 如果要依靠比较ID,则直接比较ID,而无需调用hashCode来获取它们。

That's because both of classes Employee and Department still have not overriden methods public boolean equals(Object obj) inherited from Object class. 这是因为EmployeeDepartment类仍然没有重写从Object类继承的方法public boolean equals(Object obj)

Exactly this method is invoked in dep1.equals(emp2) , not public boolean equals(Department department) . 确切地说,此方法是在dep1.equals(emp2)调用的,而不是在public boolean equals(Department department)调用的。

More specifically, read JLS : 更具体地说,请阅读JLS

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true: ... The signature of mC is a subsignature (§8.4.2) of the signature of mA. 类C声明或由类C继承的实例方法mC,从C重写在类A中声明的另一方法mA, 前提是以下所有条件均成立:... mC的签名是签名的子签名(第8.4.2节)毫安

In this case boolean equals(Department department) is not subsignature of boolean equals(Object obj) . 在这种情况下, boolean equals(Department department) 不是 boolean equals(Object obj)签名。

First, this code dep1.equals(emp2) calls default implementation of Object class. 首先,此代码dep1.equals(emp2)调用Object类的默认实现。

Second, U didnt overrides the default implementation in both of your class becoz u cant override equal method for specific customizied types. 其次,由于您无法覆盖特定自定义类型的equal方法,因此您在这两个类中均未覆盖默认实现。

If u need ur answer to be 15 15 true 如果你需要你的答案是15 15 true

replace 更换

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

by 通过

@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