这是因为重载该方法不会更改在集合或其他
equals(Object)明确使用该方法的位置中的行为。例如,使用以下代码:
public class MyClass { public boolean equals(MyClass m) { return true; }}如果您将其放在类似
HashSet:
public static void main(String[] args) { Set<MyClass> myClasses = new HashSet<>(); myClasses.add(new MyClass()); myClasses.add(new MyClass()); System.out.println(myClasses.size());}即使您希望所有实例在过载时都相等,并且不会设置第二个实例
2,这将打印出,而不是。
1``MyClass
所以基本上,即使这是
true:
MyClass myClass = new MyClass();new MyClass().equals(myClass);
这是
false:
Object o = new MyClass();new MyClass().equals(o);
后者是集合和其他类用于确定相等性的版本。实际上,此参数将返回的 唯一 地方
true是该参数显式
MyClass为其子类型的实例或其子类型之一。
编辑: 根据您的问题:
覆盖与重载
让我们从覆盖和重载之间的区别开始。通过覆盖,您实际上可以 重新定义 该方法。您删除它的原始实现,然后用您自己的替换。因此,当您这样做时:
@Overridepublic boolean equals(Object o) { ... }您实际上是在重新链接新的
equals实现,以替换中的实现
Object(或最后定义它的任何超类)。
另一方面,当您这样做时:
public boolean equals(MyClass m) { ... }您正在定义一个全新的方法,因为您正在定义一个名称相同但参数不同的方法。当
HashSet来电
equals时,它调用它的类型的变量
Object:
Object k;if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {(该代码来自的源代码
HashMap.put,用作的基础实现
HashSet.add。)
需要明确的是,它会使用不同的唯一时间
equals是当一个
equals方法被 覆盖
,不会过载。如果尝试添加
@Override到重载的
equals方法中,它将因编译器错误而失败,并抱怨它没有覆盖方法。我什至可以
equals在同一个类中声明两个方法,因为它很重载:
public class MyClass { @Override public boolean equals(Object o) { return false; } public boolean equals(MyClass m) { return true; }}泛型
至于仿制药,
equals是 不 通用的。它明确地采用
Object其类型,因此这一点没有意义。现在,假设您尝试执行此操作:
public class MyGenericClass<T> { public boolean equals(T t) { return false; }}这不会与以下消息一起编译:
名称冲突:MyGenericClass类型的equals(T)方法具有与Object类型的equals(Object)相同的擦除,但不会覆盖它
如果您尝试这样
@Override做:
public class MyGenericClass<T> { @Override public boolean equals(T t) { return false; }}您将得到以下信息:
类型MyGenericClass的equals(T)方法必须重写或实现一个超类型方法
所以你赢不了。这里发生的是Java使用擦除实现泛型。Java在编译时完成对所有通用类型的检查后,实际的运行时对象都将替换为
Object。在您看到的所有地方
T,实际的字节码都包含
Object在内。这就是为什么反射不适用于泛型类以及为什么您不能做类似的事情的原因
listinstanceof List<String>。
这也使其无法泛型类型重载。如果您有此类:
public class Example<T> { public void add(Object o) { ... } public void add(T t) { ... }}您会从
add(T)方法中得到编译器错误,因为当类实际完成编译时,这两个方法将具有相同的签名
public void add(Object)。



