反射的作用:绕过编译阶段为集合添加数据
- 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的。
- 泛型只是在编译阶段可以约束集合只能操作某种数据类型,例如:ArrayList<Integer>list=new ArrayList<>();在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。
小案例:
import java.lang.reflect.Method;
import java.util.ArrayList;
public class 反射机制_3绕过编译 {
public static void main(String[] args) throws Exception {
//反射实现泛型擦除后,加入其他类型的元素
ArrayList<String> list1=new ArrayList<>();
ArrayList<Integer> list2=new ArrayList<>();
System.out.println(list1.getClass());
System.out.println(list2.getClass());
System.out.println(list1.getClass()==list2.getClass());//可以发现泛型被擦除了,都是ArrayList类型的了
System.out.println("--------------------------------");
ArrayList<Integer> list3=new ArrayList<>();
list3.add(18);
list3.add(20);
//list3.add("遇安");类型与定义的类型不同,所以无法添加
Class c=list3.getClass();//ArrayList.class ==>public boolean add(E e),此时的add方法没有受到类型约束,因为泛型被擦除了
//定义c类中的add方法
Method add=c.getDeclaredMethod("add",Object.class);
boolean rs= (boolean) add.invoke(list3,"遇安");
System.out.println(rs);
System.out.println(list3);//运行结果:[18, 20, 遇安],我们可以发现定义的是Integer类型,但String类型照样被添加进去了
//突破类型的另一种方法:
ArrayList list4=list3;
list4.add("欢迎");
list4.add(false);
System.out.println(list3);//运行结果:[18, 20, 遇安, 欢迎, false]
}
}
反射做通用框架:
需求:给你任意一个对象,在不清楚对象字段的情况下,可以把对象的字段名称和对应值存储到文件中去。
分析:
1、定义一个方法,可以接收任意类的对象
2、每次收到一个对象后,需要解析这个对象的全部成员变量名称
3、这个对象可能是任意的,那么怎么样才可以知道这个对象的全部成员变量名称呢?
4、使用反射获取对象的Class类对象,然后获得全部成员变量信息
5、遍历成员变量信息,然后提取本成员变量在对象中的具体值
6、存入成员变量名称和值到文件中去即可
通用框架:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
//保存任意类型的对象
public class 反射_3通用框架 {
public static void save(Object obj) {
try( PrintStream ps=new PrintStream(new FileOutputStream("存储的文件路径"));
) {
//提取这个对象的全部成员变量,只有反射可以解决
Class c=obj.getClass();//c.getSimpleName()获取当前类名 c.getName()获取全限名:包名+类名
ps.println("====="+c.getSimpleName()+"=====");//可以知道当前保存的是哪个类的数据
//提取它的全部成员变量
Field []fields=c.getDeclaredFields();
//获取成员变量的信息
for (Field field : fields) {
String name=field.getName();
//提取本成员变量在obj对象中的值(取值)
field.setAccessible(true);
String value=field.get(obj)+"";//因为最后是要存到文件中去的,所以都用的String
ps.println(name+"="+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射的作用:
- 可以在运行时得到一个类的全部成分然后操作
- 可以破坏封装性
- 也可以破坏泛型的约束性
- 更重要的用途是适合做Java高级框架