问题描述
这是来自equals()
班的String
public boolean equals(Object anObject)
{
if (this == anObject)
{
return true;
}
else
{
if (anObject instanceof String)
{
String aString = (String) anObject;
if (this.coder() == aString.coder())
{
return this.islatin1() ? Stringlatin1.equals(this.value,aString.value) : StringUTF16.equals(this.value,aString.value);
}
}
return false;
}
}
- 那么为什么它被定义为
equals(Object anObject)
而不是equals(String anObject)
? 如果除String
之外的任何其他对象都返回 false,那么有机会接收任何对象有什么意义? - 如果我创建
MyOwnClass
,我应该将equals()
方法重写为equals(Object obj)
或作为equals(MyOwnClass obj)
如果和第一个选项一样,那么为什么?
P.S.:覆盖时协方差在返回类型中起作用。我认为如果协方差在重写时在返回类型中起作用,那么它也必须在函数参数中起作用。
{
public A foo(A o)
{
return new A();
}
}
class B extends A
{
@Override // everything OK
public B foo(A o)
{
return new B();
}
}
解决方法
到目前为止,没有答案触及问题的核心。
Java 的类型系统是协变的(直到您进入泛型,您可以在其中选择所需的变体)。
给定class Apple extends Fruit
和class Fruit extends Object
,那么所有的苹果也是水果,所有的水果也是物体,所有的苹果也是物体。
而 Object,因为 java.lang.Object
是这样说的,所以有一个 equals(Object other)
方法。这意味着苹果必须也有这个方法:
- 所有的苹果都是物体。
- 所有对象都有一个
equals(Object)
方法 - 因此,苹果有一个
equals(Object)
方法。
那为什么对象有这个方法呢?因为有用。因为它使 ArrayList
的 contains(Object other)
方法打勾,它使 java.util.Set 工作。一旦你决定所有对象都有一个 equals(Object other)
方法,剩下的(特别是,苹果有一个 equals(Object other)
方法,如果你问它是否等于某个非苹果对象)被锁定;现在是这种情况,仅仅是因为我们在这里设置的系统(这是一个协变类型系统,所有类型继承的基本类型都有一个 equals(Object)
方法)规定它必须如此。
是的,java语言规范实际上保证了这一点;您无法从 Apple 中“删除”equals(Object)
方法。然而,问题的关键在于为什么Java 规范是这样工作的。
那么为什么它被定义为 equals(Object anObject) 而不是 as 等于(字符串 anObject)?
class String
覆盖具有以下签名的 Object#equals
:
public boolean equals(Object obj)
在覆盖的情况下,子类中的方法签名(名称和参数)必须与超类中的相同。如果您更改参数的数量和/或类型,该方法将被重载,而不是被覆盖。
如果我创建 MyOwnClass 我应该将 equals() 方法重写为 equals(Object obj) 或 as equals(MyOwnClass obj)
您应该将其覆盖为
public boolean equals(Object obj)
否则不会被覆盖;相反,它会像上面提到的那样过载。
,如果对于 String 以外的任何其他对象返回 false,那么有机会接收任何对象有什么意义?
给定两个 Object
,您可以合法地询问它们是否相等,即使具体类型是 Integer
和 String
。
Object first = 0; // first is an Integer
Object second = ""; // second is a String
boolean equal = second.equals(first);
equals
方法需要接受最通用的类型。
我应该将 equals() 方法覆盖为 equals(Object obj)
还是 equals(MyOwnClass obj)
如果在第一个选项中那么为什么?
第一个。如果您使用第二种方式,则只有当接收者和参数都是 MyOwnClass
类型时才会调用它(如 receiver.equals(parameter)
)。否则,将调用 equals(Object)
中的 Object
,因为方法重载由编译器解决,而 equals(Object)
是编译器知道的唯一匹配接收器和参数的方法。