Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
一、关于Class
1、Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例
二、反射的基本知识
String s = new String("AAA");
//通过类名.class方法获得
System.out.println(String.class.getName());
// 通过全类名获取
System.out.println(Class.forName("java.lang.String").getName());
//通过对象的getClass()方法获取
Class c = s.getClass();
System.out.println(s.getClass().getName());
我们还可以获得父类的class信息
System.out.println(c.getSuperclass().getName());
Constructor[] con = c.getConstructors();//获得构造器
Field[] fieldArray = c.getDeclaredFields();//获得属性
Method[] methods = c.getMethods();//获得方法
Class[] InterArray = c.getInterfaces();//获得接口信息
在这个过程中,我们可以得到他们的修饰符、返回值信息等
除此之外还包括注解等信息
可以得出结论,利用反射,我们可以重现原来的JAVA文件,这一点在动态代理中特别重要
三、通过反射机制为集合添加元素
public static void TestGeneric(){
List list1 = new ArrayList(); // 没有泛型
List<String> list2 = new ArrayList<String>(); // 有泛型
/*
* 1.首先观察正常添加元素方式,在编译器检查泛型,
* 这个时候如果list2添加int类型会报错
*/
list2.add("Hello Java");
//list2.add(1); // 报错!list2有泛型限制,只能添加String,添加int报错
/*
* 2.然后通过反射添加元素方式,在运行期动态加载类,首先得到list1和list2
* 的类类型相同,然后再通过方法反射绕过编译器来调用add方法,看能否插入int
* 型的元素
*/
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1 == c2); // 结果:true,说明类类型完全相同
// 验证:我们可以通过方法的反射来给list2添加元素,这样可以绕过编译检查
System.out.println("list2的长度是:"+list2.size());
try {
Method m = c2.getMethod("add",Object.class); // 通过方法反射得到add方法
m.invoke(list2, 1); // 给list2添加一个int型的,上面显示在编译器是会报错的
m.invoke(list2,false);
System.out.println("list2的长度是:" + list2.size());
// 结果:2,说明list2长度增加了,并没有泛型检查
} catch (Exception e) {
e.printStackTrace();
}
/*现在list2的产生是3,说明运行期间,泛型就不起作用了*/
}