1、绕过 编译阶段 为集合添加数据
- 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以 为集合存入其他任意类型的元素的 。
- 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在 编译成Class文件进入 运行阶段 的时候,其真实类型都是不带泛型的集合,泛型相当于被擦除了。
package com.csdn.d6_reflect_genericity; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; public class ReflectDemo {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//需求:反射实现泛型擦除后,加入其他类型的元素ArrayList<String> list1 = new ArrayList<>();ArrayList<Integer> list2 = new ArrayList<>();System.out.println(list1.getClass());//class java.util.ArrayListSystem.out.println(list2.getClass());//class java.util.ArrayListSystem.out.println(list1.getClass() == list2.getClass());//trueSystem.out.println("===============================");ArrayList<Integer> list3 = new ArrayList<>();list3.add(23);list3.add(22);Class<? extends ArrayList> aClass = list3.getClass();Method add = aClass.getDeclaredMethod("add", Object.class);boolean rs = (boolean) add.invoke(list3, "反射");System.out.println(rs);//trueSystem.out.println(list3);//[23, 22, 反射]ArrayList list4 = list3;list4.add("注解");list4.add(false);System.out.println(list3);//[23, 22, 反射, 注解, false]} }
1.1、反射为何可以给约定了泛型的集合存入其他类型的元素?
- 编译成Class文件进入运行阶段 的时候,泛型会自动擦除 。
- 反射是作用在 运行时 的技术,此时已经不存在泛型了 。
2、通用框架的底层原理
需求
- 给定任意一个对象,在不清楚对象字段的情况下,可以把对象的字段名称和对应值存储到文件中去。
分析
- 定义一个 方法 ,可以接收任意类的对象
- 每次收到一个对象后,需要解析这个对象的 全部成员变量名称
- 这个对象可能是 任意 的,那么怎么样才可以知道这个对象的全部成员变量名称呢
- 使用 反射 获取对象的 Class类对象 ,然后获取全部成员变量信息
- 遍历成员变量信息,然后提取本成员变量在对象中的 具体值
- 存入成员变量名称和值到 文件 中去即可
package com.csdn.d7_reflect_framework; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.lang.reflect.Field; /*** 目标:提供一个通用框架,支持保存所有对象的具体信息。*/ public class ReflectDemo {public static void main(String[] args) {Student student = new Student("反射", '男', 100, "JavaSE", "暴力访问");MybatisUtil.save(student);Teacher teacher = new Teacher("注解", '女', 10000);MybatisUtil.save(teacher);} }class MybatisUtil {public static void save(Object object) {try {try (PrintStream ps = new PrintStream(new FileOutputStream("reflect\\src\\main\\java\\com\\csdn\\d7_reflect_framework\\object.txt",true))) {//1、提取这个对象的全部成员变量:只能反射可以解决Class<?> aClass = object.getClass();ps.println("==============" + aClass.getSimpleName() + "================");//2、提取它的全部成员变量Field[] fields = aClass.getDeclaredFields();//3、获取成员变量的信息for (Field field : fields) {String name = field.getName();//提取本成员变量的object对象中的值(取值)field.setAccessible(true);String value = field.get(object) + "";ps.println(name + "=" + value);}}} catch (IllegalAccessException | FileNotFoundException e) {throw new RuntimeException(e);}} }@Data @AllArgsConstructor @NoArgsConstructor class Student {private String name;private char sex;private int age;private String className;private String hobby; }@Data @AllArgsConstructor @NoArgsConstructor class Teacher {private String name;private char sex;private double salary; }
3、反射的作用?
- 可以在运行时得到一个 类的 全部成分 然后操作
- 可以 破坏封装性(很突出)
- 也可以 破坏泛型的约束性(很突出)
- 更重要的用途是适合:做 Java 高级框架