我有一个接受泛型类型的类,我想以一种非笨拙的方式覆盖equals
方法(即看起来干净且代码量极少的东西) ,但对于一般用例)。
现在我有这样的事情:
public class SingularNode<T> {
private T value;
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object other){
if(other instanceof SingularNode<?>){
if(((SingularNode<T>)other).value.equals(value)){
return true;
}
}
return false;
}
}
我猜测,这是非常有缺陷的 - 我正在对SingularNode<T>
对象进行other
投射,这可能会导致抛出错误。
另一件事是 - 当我做if(other instanceof SingularNode<?>)
时,我实际上没有检查到正确的事情。我实际上想要检查类型T
而不是?
类型。每当我尝试将?
转换为T
时,我会收到一些错误:
无法对参数化类型
SingularNode<T>
执行instanceof检查。请改为使用SingularNode<?>
形式,因为在运行时将删除其他通用类型信息
我该如何解决这个问题?有没有办法T.class.isInstance(other);
?
我认为这是一个非常难看的黑客解决方案:
@SuppressWarnings("unchecked")
public boolean isEqualTo(Class<?> c, Object obj){
if(c.isInstance(obj) && c.isInstance(this)){
if(((SingularNode<T>)obj).value.equals(value)){
return true;
}
}
return false;
}
但是使用额外的方法参数看起来真的很尴尬,而且它也不像equals
这样的内置函数。
任何了解仿制药的人都请解释一下吗?我不熟悉Java,你可以清楚地看到,所以请稍微详细解释一下!
答案 0 :(得分:21)
此版本不提供警告
public boolean equals(Object other){
if (other instanceof SingularNode<?>){
if ( ((SingularNode<?>)other).value.equals(value) ){
return true;
}
}
return false;
}
至于投射到SingularNode<T>
它没有任何帮助,你不能认为T
可以是Object
以外的任何东西。
了解有关如何使用Java编译泛型的更多信息
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
答案 1 :(得分:5)
Evgeniy's solution和Michal's reasoning是正确的 - 您无需担心T
的类型。原因是equals
方法不依赖于泛型来正常工作。相反,它由Object
声明,需要Object
。因此,它负责检查传入的任何内容的运行时类型。
如果this
恰好是SingularNode<String>
并且您将其与SingularNode<Integer>
进行比较,那么((SingularNode<?>)other).value.equals(value)
完全正常,因为使用{{1}调用Integer.equals
参数将正确返回String
。
答案 2 :(得分:1)
我把答案放在这里放代码..
在您的示例中,您({伪代码} Integer(5).equals(Char('k'))
为false
,根据以下等于java.lang.Integer
上的实现:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
这样你不必担心施法。
答案 3 :(得分:0)
我有同样的问题,但它更通用。我有一个类,我有3个泛型类型。我不需要存储这些类型的任何变量,因为此类用于转换。但是存储了&#39;请求&#39;变量和我确实使用基于这个类的缓存,所以我需要实现基于这些泛型的equals()方法。
你知道在没有反思的情况下是否有任何方法可以做到这一点?也许是那种类型的内部变量..然而它是null。
public class TheClass<I, O, M> {
private ClassA param1;
private ClassB param2;
private ClassC<M> param3;
private BiFunction<ClassC<M>, I, Optional<O>> mapping;
public ClassD<O, M> doSomething(ClassD<I, M> param) {
...
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (getClass() != o.getClass()) {
return false;
}
TheClass<?, ?, ?> that = (TheClass<?, ?, ?>) o;
return Objects.equals(getParam1(), that.getParam1()) &&
Objects.equals(getParam2(), that.getParam2()) &&
Objects.equals(getParam3(), that.getParam3());
}
}
为了更好的想象力......我有一组DAO对象从数据库中获取数据。另一方面,我们确实有另一组API提供程序,它们以不同的格式提供类似的数据(REST,内部系统......) 我们需要从一种类型到另一种类型的映射函数。我们使用缓存来获得更好的性能,唯一的中间人就是这个类。
答案 4 :(得分:-4)
你不需要使用任何铸造。 最好等于实现我看起来像这样
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof VehicleModel)) return false;
VehicleModel that = (VehicleModel) o;
if (vehicleName != null ? !vehicleName.equals(that.vehicleName) : that.vehicleName != null)
return false;
return true;
}