面试时遇到一个问题,泛型如何获取真实的类型?GG,下来以后查了相关资料,看了几遍才懂是啥意思,写在这里牢记!
泛型——就是将类型的明确推迟到创建对象或执行方法时再进行。泛型相当于一个参数,修饰这个类实际上是什么。
举例来说:
ArrayList
整个ArrayList
定义一个含泛型参数T的类,然后在类中设置一个T变量,和在类中直接定义一个Object类相比,有如下的好处:
在实例化一个泛型类时,如果不使用<>指定类型,或者使用<?>指定类型,那么泛型参数就相当于Object,泛型类就失去了泛型的作用。
在实例化一个泛型类时,如果使用<?>定义,可以在?后面附加条件extends A或 super A。前者表示届时这个参数化类型变量应该是A的子类,后者表示届时这个参数化类型变量应该是B的超类(祖先类)。
此外,在定义时,可以使用
泛型类在编译后,<>中的类型信息会被擦除,在内存中实际表现为Object类。而在get()等方法需要返回确切类型的地方,实际的泛型参数类型会被直接写入。
例如ArrayList
E get(){/* ... */}
变成
Integer get(){/*  ... */}
以ArrayList
既然有泛型擦除的概念,那么对于一个表面定型,其实不定型的ArrayList
    ArrayList<Integer> ai = new ArrayList<>();
    ai.add(123);
    try {
        ai.getClass().getDeclaredMethod("add",Object.class).invoke(ai,"string");
    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    }
    for (Object o:ai)
        System.out.println(o);
    for (Integer i:ai)
        // 运行时会报ClassCastException,因为有一个String无法被转为Integer
        System.out.println(i);
泛型如何获取到真实类型呢?我们分为三种情况来分析
    private static class Generic<T extends Number>{
        T data;
        int id;
    }
    private static class ExtendedGeneric extends Generic<Integer>{
        private void te(){
        }
    }
    public static void main(String[] args) throws Exception {
        Type t= ((ParameterizedType) ExtendedGeneric.class.
                getGenericSuperclass()).getActualTypeArguments()
                [0];
        System.out.println(t.getTypeName());
    }
运行结果:java.lang.Integer
    private interface GenericInterface<P>{
        P getP();
    }
    private static class ImplGeneric implements GenericInterface<Pipe>{
        @Override
        public Pipe getP() {
            return null;
        }
    }
    public static void main(String[] args) throws Exception {
        Type t= ((ParameterizedType) ImplGeneric.class.
                getGenericInterfaces()[0]).getActualTypeArguments()
                [0];
        System.out.println(t.getTypeName());
    }
运行结果:java.nio.channels.Pipe
提示:这里和情况1很类似,只是父类只能有一个,接口可以有很多,所以getGenericSuperclass()返回的是一个Type,而getGenericInterfaces()返回的是一个Type[]数组。
这种情况下没有什么靠谱的方法,如果能确保这个泛型类型不为空,且值是统一的(不存在前述的那种反射写入其他类型的情况),可以通过不靠谱的方法得到。代码如下:
    public static void main(String[] args) throws Exception {
        ArrayList<String > strings = new ArrayList<>();
        strings.add("123");
        Class<?> c= ArrayList.class.getDeclaredMethod("get", int.class)
                .invoke(strings,0).getClass();
        System.out.println(c.getName());
    }
运行结果:java.lang.String原文:https://www.cnblogs.com/pravez/p/12542190.html