Java 如何使用“instanceof”为泛型实现“equals”方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16382887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement "equals" method for generics using "instanceof"?
提问by David T.
I have a class that accepts a generic type, and I want to override the equals
method in a non-awkward way (i.e. something that looks clean and has minimal amount of code, but for a very general use case).
我有一个接受泛型类型的类,我想以equals
一种非尴尬的方式覆盖该方法(即看起来干净且代码量最少的东西,但对于非常通用的用例)。
Right now I have something like this:
现在我有这样的事情:
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;
}
}
Which, I'm guessing, is pretty flawed - I'm doing a cast to SingularNode<T>
on the other
object, which could potentially throw an error.
我猜这是非常有缺陷的 - 我正在SingularNode<T>
对other
对象进行强制转换,这可能会引发错误。
Another thing is - when I do if(other instanceof SingularNode<?>)
I'm actually not checking exactly the right thing. I actually want to check against type T
and not type ?
. Whenever I try to make the ?
into T
, I get some error like:
另一件事是 - 当我这样做时,if(other instanceof SingularNode<?>)
我实际上并没有检查完全正确的东西。我实际上想检查 typeT
而不是 type ?
。每当我尝试?
进入时T
,我都会收到一些错误,例如:
Cannot perform instanceof check against parameterized type
SingularNode<T>
. Use the formSingularNode<?>
instead, since further generic type information will be erased at runtime
无法对参数化类型执行 instanceof 检查
SingularNode<T>
。改用表单SingularNode<?>
,因为进一步的泛型类型信息将在运行时被删除
How can I get around this? Is there some way to do T.class.isInstance(other);
?
我怎样才能解决这个问题?有T.class.isInstance(other);
什么办法吗?
I suppose there's one really ugly hack solution like this:
我想有一个非常丑陋的黑客解决方案是这样的:
@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;
}
But that just looks really awkward with the extra method parameter, and it's also not a built-in function like equals
is.
但这对于额外的方法参数看起来真的很尴尬,而且它也不是像equals
is那样的内置函数。
Any one who understand generics please explain this? I'm not that proficient with Java, as you can clearly see, so please explain with a tad bit more detail!
任何了解泛型的人请解释一下?我对Java不是很精通,你可以清楚地看到,所以请解释得更详细一些!
采纳答案by Evgeniy Dorofeev
This version gives no warnings
这个版本没有警告
public boolean equals(Object other){
if (other instanceof SingularNode<?>){
if ( ((SingularNode<?>)other).value.equals(value) ){
return true;
}
}
return false;
}
As for casting to SingularNode<T>
it does not help anything, you cannot assume that T
can be anything but Object
.
至于投射到SingularNode<T>
它没有任何帮助,您不能假设T
除了Object
.
Learn more about how generics are compiled in Java at
了解有关如何在 Java 中编译泛型的更多信息,请访问
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
回答by Michal Borek
I put answer here to put code..
我把答案放在这里放代码..
In your example you have (in pseudo code) Integer(5).equals(Char('k'))
which is false
, according to following equals implementation on java.lang.Integer
:
在你的例子中,你有(在伪代码中)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;
}
Going that way you don't have to worry about casting.
这样做你不必担心铸造。
回答by Paul Bellora
Evgeniy's solutionand Michal's reasoningare correct - you don't need to worry about the type of T
here. The reason is that the equals
method doesn't depend on generics to work correctly. Instead, it is declared by Object
and it takes an Object
. Thus, it's responsible for checking the runtime type of whatever was passed in.
Evgeniy 的解决方案和Michal 的推理是正确的 - 您无需担心T
这里的类型。原因是该equals
方法不依赖于泛型才能正常工作。相反,它是由声明的Object
,它需要一个Object
. 因此,它负责检查传入的任何内容的运行时类型。
If this
happens to be SingularNode<String>
and you compare it with a SingularNode<Integer>
, then ((SingularNode<?>)other).value.equals(value)
is perfectly fine because calling Integer.equals
with a String
argument will correctly return false
.
如果this
恰好是SingularNode<String>
并且您将其与 a 进行比较SingularNode<Integer>
,则((SingularNode<?>)other).value.equals(value)
完全没问题,因为Integer.equals
使用String
参数调用将正确返回false
。
回答by Atish Narlawar
You dont need to use any casting. Best equals to implementation I see like this
您不需要使用任何铸造。最好等于实现我是这样看的
@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;
}
回答by JiangHongTiao
I have the same problem, however it is more general. I have a class where I do have 3 generic types. I do not need to store any variable of those types because this class is used for transformation. However there are stored 'request' variables and I do use cache based on this class, so I need to implement equals() method that is based on those generics.
我有同样的问题,但它更普遍。我有一个班级,我确实有 3 个泛型类型。我不需要存储这些类型的任何变量,因为这个类用于转换。但是,存储了“请求”变量,并且我确实使用了基于此类的缓存,因此我需要实现基于这些泛型的 equals() 方法。
Do you know if there is any approach how to do it without reflection? Maybe internal variable of that type.. However it's null then.
你知道是否有任何方法可以在没有反思的情况下做到这一点?也许是那种类型的内部变量。但是它是空的。
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());
}
}
For a better imagination... I have set of DAO objects getting data from database. On the other hand, we do have another set of API providers that provide similar data in different format (REST, internal systems..) We need a mapping function from one type to another. We use caching for better performance and the only man-in-the-middle is this class.
为了更好的想象......我有一组从数据库中获取数据的 DAO 对象。另一方面,我们确实有另一组 API 提供程序,它们以不同的格式(REST、内部系统……)提供类似的数据。我们需要一个从一种类型到另一种类型的映射函数。我们使用缓存来获得更好的性能,唯一的中间人就是这个类。