[英]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)
方法,并提供了默认实现。 这是在比较Employee
和Department
时调用的方法,而不是您提供的重载之一。
您的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
替换为某些其他实现(例如,同时考虑id
和name
的实现),则代码重构将无法幸免。 如果要依靠比较ID,则直接比较ID,而无需调用hashCode
来获取它们。
这是因为Employee
和Department
类仍然没有重写从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.