简体   繁体   English

Java Generics:将Object o的类与<E>进行比较

[英]Java Generics: Comparing the class of Object o to <E>

Let's say I have the following class: 假设我有以下课程:

public class Test<E> {
    public boolean sameClassAs(Object o) {
        // TODO help!
    }
}

How would I check that o is the same class as E ? 我如何检查oE是同一类?

Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false;

I can't change the method signature from (Object o) as I'm overridding a superclass and so don't get to choose my method signature. 我无法从(Object o)更改方法签名,因为我覆盖了一个超类,所以不要选择我的方法签名。

I would also rather not go down the road of attempting a cast and then catching the resulting exception if it fails. 我也宁愿不去尝试一个演员然后如果失败就抓住结果异常。

An instance of Test has no information as to what E is at runtime. Test一个实例没有关于E在运行时的信息。 So, you need to pass a Class<E> to the constructor of Test. 因此,您需要将Class<E>传递给Test的构造函数。

public class Test<E> {
    private final Class<E> clazz;
    public Test(Class<E> clazz) {
        if (clazz == null) {
            throw new NullPointerException();
        }
        this.clazz = clazz;
    }
    // To make things easier on clients:
    public static <T> Test<T> create(Class<T> clazz) {
        return new Test<T>(clazz);
    }
    public boolean sameClassAs(Object o) {
        return o != null && o.getClass() == clazz;
    }
}

If you want an "instanceof" relationship, use Class.isAssignableFrom instead of the Class comparison. 如果您想要“instanceof”关系,请使用Class.isAssignableFrom而不是Class比较。 Note, E will need to be a non-generic type, for the same reason Test needs the Class object. 注意, E需要是非泛型类型,出于同样的原因, Test需要Class对象。

For examples in the Java API, see java.util.Collections.checkedSet and similar. 有关Java API中的示例,请参阅java.util.Collections.checkedSet等。

The method I've always used is below. 我一直使用的方法如下。 It is a pain and a bit ugly, but I haven't found a better one. 这是一种痛苦,有点难看,但我找不到更好的。 You have to pass the class type through on construction, as when Generics are compiled class information is lost. 你必须在构造时传递类类型,因为当泛型被编译时类信息丢失了。

public class Test<E> {
    private Class<E> clazz;
    public Test(Class<E> clazz) {
       this.clazz = clazz;
    }
    public boolean sameClassAs(Object o) {
        return this.clazz.isInstance(o);
    }
}

I could only make it working like this: 我只能让它像这样工作:

public class Test<E> {  

    private E e;  

    public void setE(E e) {  
        this.e = e;  
    }

    public boolean sameClassAs(Object o) {  

        return (o.getClass().equals(e.getClass()));  
    }

    public boolean sameClassAs2(Object o) {  
        return e.getClass().isInstance(o);  
    }
}

I was just trying to do the same thing, and one neat trick i just realized is that you can can try a cast, and if the cast fails, ClassCastException will be thrown. 我只是想做同样的事情,我刚刚意识到的一个巧妙的技巧是你可以尝试一个演员表,如果演员表失败,将抛出ClassCastException。 You can can catch that, and do whatever. 你可以抓住它,做任何事情。

so your sameClassAs method should look like: 所以你的sameClassAs方法应该是这样的:

public boolean sameClassAs(Object o) {
    boolean same = false;
    try {
        E t = (E)o;
        same = true;
    } catch (ClassCastException e) {
        // same is false, nothing else to do
    } finally {
        return same;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM