Java反射(六)----- 通过反射了解集合泛型的本质

java中的泛型是JDK5中引入的新特性,允许在定义类和接口的时候使用类型参数,声明的类型参数在使用时用具体的类型来替换,泛型最主要是应用在集合类框架中。下面我们通过反射来进一步理解泛型的本质。

先放上示例代码

MethodDemo4.java文件

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class MethodDemo4 {
    public static void main(String[] args) {
        //该list1中可以放任何类型
        ArrayList list1 = new ArrayList();
        //该list2中只能放String类型
        ArrayList list2 = new ArrayList<>();

        list1.add("hello");
        list2.add("hello");
        //list2.add(20);    //错误
        Class c1 = list1.getClass();
        Class c2 = list2.getClass();
        System.out.println(c1 == c2);       //结果 true(说明编译之后的集合的泛型是去泛型化的)

        //反射的操作都是运行时操作,即编译之后的操作

        //java中集合的泛型是防止错误输入的e,只在编译阶段有效,通过编译就无效了

        //通过方法的反射来绕过编译进行验证
        try {
            Method m = c2.getMethod("add", Object.class);
            //注意:在上面的list2中时只能放入String类型,此处通过反射加入int类型100
            m.invoke(list2, 100);
            System.out.println(list2.size());       //运行结果为2,说明100被成功添加进list2
            System.out.println(list2);      //运行结果  [hello, 100]      (此时不能通过for/foreach来遍历,会报类型错误)
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

代码中,集合list1中可以放入任何类型,但集合list2中只能放入String类型,我们通过反射绕过编译之后,成功在list2中加入int类型的100,可看出,在编译之后,集合List已经没有了类型限制,这种情形称为类型擦除。List在前面指定类型只是为了防止错误输入,以便在编译时可以及时发现。

你可能感兴趣的:(java)