对于没有字段的 class,equals() 的合适实现是什么?
What's a suitable implementation of equals() for a class with no fields?
假设我有一个没有字段但有一些方法的 class。例如 class 只实现了 interface
:
public class SomeClass implements SomeInterface
{
@Override
public void someMethod(int param) {...}
@Override
public int getSomeValue(OtherClass param) {return ...;}
}
现在我想为此覆盖 equals()
。我可以一直return true
,通过争论"since the objects don't have any state, they are always equal"吗?
这样的实现:
@Override
public boolean equals(Object other)
{
if (null == other || !(other instanceof SomeClass))
return false;
return true;
}
编辑: 由于有人问到这背后的意图,我将详细说明这个问题出现的背景:
这个 class 是一个事件侦听器。我实例化并将其作为异步请求的侦听器传递给异步请求,以及一些其他数据,封装在名为 Config
.
的对象中
换句话说,我有一个名为 Config
的 class,它由 SomeClass
和一些其他数据组成。
public class Config
{
SomeClass someClass;
int otherData;
//...
@Override
public boolean equals(Object other) {/*???*/}
}
实际上我想为此Config
class实现equals
(因为我想防止重复请求)。但是由于 Config
的一部分是 SomeClass
的这个实例,我想知道如何处理它。
附带问题:如果 SomeClass
是一个嵌套的 class 并且对其包含的 class 有隐式引用,那该怎么办? (在我的上下文中,它是。)
这是一个语义问题:这个 class 有两个对象是什么意思? (将其实现为单例甚至有用吗?)
如果可以互换使用,确实可以认为是等同的。 (然后不要忘记覆盖 hashCode()
。)但是,您也可以保留来自 Object
.
的原始定义
仅 returning true
是一个糟糕的实现,因为这意味着您的 class 的任何实例都等于 任何其他对象,这可能不是您想要的。此外,它将打破 equals
的一般交换契约,因为 mySomeClass.equals("Mousa")
将 return true
而 "Mousa".equals(mySomeClass)
将 return false
.
由于 SomeClass
没有状态,实现其 equals
方法是个人喜好问题。让任意两个 SomeClass
实例彼此相等是一个合理的选择,尽管您建议的实现可以改进。由于 other instanceof SomeClass
将 return false
如果 other
是 null
,该方法可以重写为
@Override
public boolean equals(Object other) {
return other instanceof SomeClass;
}
此外,您应该注意,为了维护具有相同 hashCode()
的两个 相等 对象的一般契约,您也应该覆盖该方法。例如:
@Override
public int hashCode() {
return SomeClass.class.hashCode();
}
另一方面,决定也是完全合理的,因为 SomeClass
没有状态,两个对象彼此相等的唯一方法是它们都指向同一个实例(即, ==
运算符的行为)。这种方法是由另一个著名的无状态 class 采取的,您可能从 JDK - java.lang.Object
.
中了解到
假设我有一个没有字段但有一些方法的 class。例如 class 只实现了 interface
:
public class SomeClass implements SomeInterface
{
@Override
public void someMethod(int param) {...}
@Override
public int getSomeValue(OtherClass param) {return ...;}
}
现在我想为此覆盖 equals()
。我可以一直return true
,通过争论"since the objects don't have any state, they are always equal"吗?
这样的实现:
@Override
public boolean equals(Object other)
{
if (null == other || !(other instanceof SomeClass))
return false;
return true;
}
编辑: 由于有人问到这背后的意图,我将详细说明这个问题出现的背景:
这个 class 是一个事件侦听器。我实例化并将其作为异步请求的侦听器传递给异步请求,以及一些其他数据,封装在名为 Config
.
换句话说,我有一个名为 Config
的 class,它由 SomeClass
和一些其他数据组成。
public class Config
{
SomeClass someClass;
int otherData;
//...
@Override
public boolean equals(Object other) {/*???*/}
}
实际上我想为此Config
class实现equals
(因为我想防止重复请求)。但是由于 Config
的一部分是 SomeClass
的这个实例,我想知道如何处理它。
附带问题:如果 SomeClass
是一个嵌套的 class 并且对其包含的 class 有隐式引用,那该怎么办? (在我的上下文中,它是。)
这是一个语义问题:这个 class 有两个对象是什么意思? (将其实现为单例甚至有用吗?)
如果可以互换使用,确实可以认为是等同的。 (然后不要忘记覆盖 hashCode()
。)但是,您也可以保留来自 Object
.
仅 returning true
是一个糟糕的实现,因为这意味着您的 class 的任何实例都等于 任何其他对象,这可能不是您想要的。此外,它将打破 equals
的一般交换契约,因为 mySomeClass.equals("Mousa")
将 return true
而 "Mousa".equals(mySomeClass)
将 return false
.
由于 SomeClass
没有状态,实现其 equals
方法是个人喜好问题。让任意两个 SomeClass
实例彼此相等是一个合理的选择,尽管您建议的实现可以改进。由于 other instanceof SomeClass
将 return false
如果 other
是 null
,该方法可以重写为
@Override
public boolean equals(Object other) {
return other instanceof SomeClass;
}
此外,您应该注意,为了维护具有相同 hashCode()
的两个 相等 对象的一般契约,您也应该覆盖该方法。例如:
@Override
public int hashCode() {
return SomeClass.class.hashCode();
}
另一方面,决定也是完全合理的,因为 SomeClass
没有状态,两个对象彼此相等的唯一方法是它们都指向同一个实例(即, ==
运算符的行为)。这种方法是由另一个著名的无状态 class 采取的,您可能从 JDK - java.lang.Object
.