如何使用“instanceof”实现generics的“equals”方法?

我有一个接受generics类型的类 ,我想以一种非笨拙的方式覆盖equals方法(即看起来很干净并且代码量很少的东西,但对于非常一般的用例)。

现在我有这样的事情:

 public class SingularNode { private T value; @SuppressWarnings("unchecked") @Override public boolean equals(Object other){ if(other instanceof SingularNode){ if(((SingularNode)other).value.equals(value)){ return true; } } return false; } } 

我猜,这是非常有缺陷的 – 我正在对other对象的SingularNode进行强制转换,这可能会引发错误

另一件事是 – 当我这样做if(other instanceof SingularNode)我实际上并没有检查到正确的东西。 我实际上想检查类型T而不是类型? 。 每当我试图制作? 进入T ,我得到一些错误:

无法对参数化类型SingularNode执行instanceof检查。 请改为使用SingularNodeforms,因为在运行时将删除其他generics类型信息

我怎么能绕过这个? 有没有办法做T.class.isInstance(other);

我想有一个非常难看的黑客解决方案是这样的:

 @SuppressWarnings("unchecked") public boolean isEqualTo(Class c, Object obj){ if(c.isInstance(obj) && c.isInstance(this)){ if(((SingularNode)obj).value.equals(value)){ return true; } } return false; } 

但是使用额外的方法参数看起来真的很尴尬,而且它也不像equals是内置函数。

任何了解仿制药的人都请解释一下吗? 我不是那么精通Java,你可以清楚地看到,所以请稍微详细解释一下!

此版本不提供任何警告

 public boolean equals(Object other){ if (other instanceof SingularNode){ if ( ((SingularNode)other).value.equals(value) ){ return true; } } return false; } 

至于转换为SingularNode它没有任何帮助,你不能假设T可以是除了Object任何东西。

了解有关如何使用Java编译generics的更多信息

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Evgeniy的解决方案和Michal的推理是正确的 – 你不需要担心这里的T类型。 原因是equals方法不依赖于generics来正常工作。 相反,它由Object声明,它需要一个Object 。 因此,它负责检查传入的任何内容的运行时类型。

如果this恰好是SingularNode并且你将它与SingularNode进行比较,则((SingularNode)other).value.equals(value)完全正常,因为使用String参数调用Integer.equals将正确返回false

我把答案放在这里放代码..

在你的例子中,你有(伪代码) 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; } 

这样,你不必担心投射。

我有同样的问题,但它更一般。 我有一个class级,我有3个generics类型。 我不需要存储这些类型的任何变量,因为此类用于转换。 但是存在“请求”变量,我确实使用基于此类的缓存,因此我需要实现基于这些generics的equals()方法。

你知道在没有反思的情况下是否有任何方法可以做到这一点? 也许那种类型的内部变量..然而它是null。

 public class TheClass { private ClassA param1; private ClassB param2; private ClassC param3; private BiFunction, I, Optional> mapping; public ClassD doSomething(ClassD 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,内部系统……)我们需要从一种类型到另一种类型的映射函数。 我们使用缓存来获得更好的性能,而这个类中唯一的中间人。

你不需要使用任何铸件。 最好等于实现我看到这样

 @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; }