验证两个泛型类型是否具有相同的参数

时间:2016-08-02 15:34:06

标签: java reflection

假设我有这个通用类A

public class A<E> {

    public A(E e) {}

}

如何知道此类的两个实例是否具有相同的类型参数<E>

我试过了:

public static void main(String[] args) {
    A<String> aString = new A<>("a");
    A<Integer> anInt = new A<>(0);
    System.out.println(aString.getClass().isInstance(anInt));
}

哪个输出true。我想这是有道理的,因为他们有同一个班级。但是,如果您尝试这样做:

A<String> anotherString = new A<Integer>(-1);

它不会编译,因为类型参数不同。如何在运行时知道两个类型参数是否不同/等效?换句话说,我需要一个可以比较两个变量并根据类型参数返回false的方法。

编辑:好的,似乎可能无法实现。我将首先尝试解释为什么我想要做到这一点,也许还有另一种实现方法。如果您希望我发布不同的问题,请告诉我。

我有这个方法:

public void someMethod(A<String> aString) {
    System.out.println("I got called!");
}

如何通过反射确保给出的参数实际上是A<String>

如果我试试这个:

A<Integer> anInt = new A<>(0);
Method method = Main.class.getMethod("someMethod", anInt.getClass());
method.invoke(new Main(), anInt);

它仍会打印出“我被叫了!”信息。我怎样才能确保不会发生这种情况? (如果可能的话)。

4 个答案:

答案 0 :(得分:1)

类型信息仅在编译时使用。因此在运行时类型信息将丢失。如果要在运行时进行某些比较,可以将类类型存储在变量中。

答案 1 :(得分:0)

使用泛型的全部原因是确保如果代码编译,那么它不会导致任何运行时问题。您正在搜索没有问题的问题。您的代码在编译时失败的原因是您明确提供了不兼容的引用类型,只要这些类型具有共同的超类型<E>

,它就不会在运行时发生

答案 2 :(得分:0)

您可以捕获类型的一种方法是使实例成为A的匿名子类:

A<String> aString = new A<String>("a") {};
A<Integer> anInt = new A<Integer>(0) {};

然后你可以看看例如aString.getClass().getGenericSuperclass()在运行时获取泛型类型。

Ideone Demo

如@James_D所述,您可以通过使A抽象来强制执行此操作。

答案 3 :(得分:0)

如其他答案中所述,通用类型信息不会在运行时保留。如果您需要这些信息,那么在我的类中定义一个属性来表示它是有意义的:

public class A<E> {
    private final Class<E> type ;

    private E value ;

    public A(E e, Class<E> type) {
        this.type = type ;
        this.value = value ;
    }

    public Class<E> getType() { return type ; }

    // other methods, etc...
}

然后你可以做

A<Integer> aInt = new A<>(1, Integer.class);
A<String> aString = new A<>("", String.class);

你可以检查

aInt.getType() == aString.getType()