26

我有一个接受泛型类型的类,我想以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<?>)我实际上并没有检查完全正确的事情。我实际上想检查 typeT而不是 type ?。每当我尝试?进入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;
}

但这对于额外的方法参数看起来真的很尴尬,而且它也不是像 is 这样的内置函数equals

任何了解泛型的人请解释一下?正如您清楚地看到的那样,我对Java不是那么精通,所以请更详细地解释一下!

4

5 回答 5

32

这个版本没有警告

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

于 2013-05-05T09:23:57.583 回答
6

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

如果this碰巧是SingularNode<String>并且您将其与 a 进行比较SingularNode<Integer>,那么((SingularNode<?>)other).value.equals(value)就很好了,因为Integer.equals使用String参数调用将正确返回false

于 2013-05-05T16:08:45.670 回答
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;
}

这样你就不用担心选角了。

于 2013-05-05T09:18:06.560 回答
0

我有同样的问题,但它更普遍。我有一门课,我确实有 3 种泛型类型。我不需要存储这些类型的任何变量,因为此类用于转换。但是,存储了“请求”变量,并且我确实使用了基于此类的缓存,因此我需要实现基于这些泛型的 equals() 方法。

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

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、内部系统......)提供类似的数据。我们需要从一种类型到另一种类型的映射函数。我们使用缓存来获得更好的性能,唯一的中间人就是这个类。

于 2018-01-26T16:32:48.150 回答
-5

你不需要使用任何铸造。最好等于我看到的实现

@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;
    }
于 2013-10-22T15:52:38.790 回答