反射的作用之动态对实例对象进行操作
前提:我认为,反射概念在JavaSE内容中算是一个比较绕的知识点,反射本身好理解,但实际运用起来总会让人感觉好像又不是很对;对于反射的学习,我是先学具体使用再了解的作用,对于反射的作用之一,在这里做个笔记。
任务需求:对被Integer泛型约束的List集合,添加其他类型的元素
一、必备知识
1、反射机制概念:对任何一个class类,在其运行时,都可以直接取得该Class对象和其全部成分;反射认为类中的每个成分都是单独的对象(符合Java的‘一切皆对象’概念),支持动态获取类信息以及动态调用类成分。
2、反射的“动态”:指越过编译阶段,可以直接对运行时Runtime阶段产生效果。
3、泛型:JDK5引入的一种特性,作用是在编译阶段约束数据类型并检查,只支持引用类型。
4、当泛型数据被编译成Class对象进入运行阶段,其真实类型取的是大范围类型,泛型被擦去。
5、泛型标识和通配符:包括T、E、K、V等,和?;其实二者对代码的作用是一样的,区别只是给程序员一个提示,不同字母有对应的提示意义;后者相较更代表一切类型,当无法确定类型时使用;但是二者依然还是作符号作用,对应的类是Object。
6、在对Class具体成分进行操作时,要有实例对象,指定实例对象(成分不可能脱离实例单独存在,比如-- 我的身高体重,不可能脱离我实际存在)。
7、因为反射作用于运行阶段,所以报错只在运行时才会出现,并且报错提示也比较不友好哈。
二、操作
· 明了《一》的7点内容,操作步骤是简单的,重在理解 !具体代码如下:
1、直接添加非Integer内容 --- 【报错】
//1、创建list集合实例 List<Integer> list = new ArrayList<>(); list.add(11); list.add(22); // list.add("aaa"); 报错
2、注意取到的Method add的第二个参数,'Object.class',作用(相当于反射的泛型,填了什么类型,通过反射添加就是什么类型,否则在运行阶段也会报错);要确保可以不止add一种类型数据,就要传参Object类(invoke传参受其限制)。
//2、使用运行阶段获取Class对象 方法 Class c = list.getClass(); //3、取Method对象(给集合添加数据的方法add) //add方法实际上的参数类型是不限的,所以使用泛型约束,确切定位时可以用Object类型,不影响使用 Method add = c.getDeclaredMethod("add", Object.class); boolean flag = (boolean) add.invoke(list,"aaa"); System.out.println(list);
【触发方法的传参和约定参数类型不一致,报错】
5、为什么泛型只作用于编译阶段(一、4)
4、查看运行结果
三、总结
总结就是,要分清楚实例和类的区别,实例的成员的修改,类成员的获取。