运行时泛型类型确定

时间:2013-09-27 09:08:57

标签: java generics type-parameter

为什么会这样。如果我将匿名泛型类传递给类型确定方法 - 一切都很好。但是如果我在这个方法中传递对象 - 控制台输出是E.

public static void main(String[] args) {

    printType(new ArrayList<Integer>() {});
    printType(new ArrayList<Integer>());

}

public static void printType(final List<?> list) {
    System.out.println(((ParameterizedType) list.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}

控制台:

class java.lang.Integer

E

请向我解释。

1 个答案:

答案 0 :(得分:7)

第一次调用是传递ArrayList<Integer>的匿名子类的实例。所以,它类似于:

class YourClass extends ArrayList<Integer>

并且您将该方法调用为:

printType(new YourClass());

YourClass的通用超类或您案例中的匿名类仅为ArrayList<Integer>。所以,这个输出是清楚的。


至于你的第二个案例,你正在传递一个ArrayList<Integer>本身的实例。这个类的定义如下:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

因此,这里的通用超类是AbstractList<E>

通用类型的实例化共享相同的Class实例:

请注意,ArrayList的所有实例化都在运行时共享同一个类:

new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass();

以上比较将为您提供true。因为getClass()调用都会回复给您:

class java.util.ArrayList

请参阅JLS 8.1.2: Generic Classes and Type Parameters

  

泛型类声明定义了一组参数化类型   (§4.5),每个可能的类型参数部分调用一个   按类型参数。所有这些参数化类型都共享相同的内容   在课程时间上课。

     

例如,执行代码:

    Vector<String>  x = new Vector<String>(); 
    Vector<Integer> y = new Vector<Integer>(); 
    boolean b = x.getClass() == y.getClass();
     

将导致变量b保持值true

换句话说,getGenericSuperClass()方法不会为您提供实例化类时使用的实际类型参数,而是在它所扩展的类中使用的类型参数。现在,由于java.util.ArrayList的通用超类是AbstractList<E>。因此,您获得的类型参数仅为E