如何使用"instanceof"实现泛型的"equals"方法?

Dav*_* T. 19 java oop generics equals instance

我有一个接受泛型类型的类,我想以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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

另一件事是 - 当我这样做时,if(other instanceof SingularNode<?>)我实际上并没有检查正确的事情.我实际上想要检查类型T而不是类型?.每当我尝试?进入时T,我会得到一些错误:

无法对参数化类型执行instanceof检查SingularNode<T>.请改用表单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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

Evg*_*eev 21

此版本不提供任何警告

public boolean equals(Object other){
    if (other instanceof SingularNode<?>){
        if ( ((SingularNode<?>)other).value.equals(value) ){
            return true;
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

至于铸造SingularNode<T>对它没有任何帮助,你不能认为T可以是任何东西Object.

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

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

  • 有时你根本无法避免SuppressWarnings或使用原始类型.请参阅JDK Collections.swap impl - > List l = list; 在某些情况下甚至J.Bloch必须忽略泛型并使用原始类型 (2认同)

Pau*_*ora 5

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

如果this恰好是SingularNode<String>你并将它与a进行比较SingularNode<Integer>,那么((SingularNode<?>)other).value.equals(value)完全没问题,因为Integer.equals使用String参数调用将正确返回false.