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

时间:2013-05-05 08:49:17

标签: java oop generics instance equals

我有一个接受泛型类型的类,我想以一种非笨拙的方式覆盖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,你可以清楚地看到,所以请稍微详细解释一下!

5 个答案:

答案 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 solutionMichal'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;
    }