摘要:
首先记录反射的基础Class类的理解,然后记录反射的概念并对类的各种元素的反射运用,最后记录数组和Object的关系和其反射关系。
1.Class的定义、获取方式以及反射概念
在讲到Class之前,先回顾下在线程中同步的静态方法所使用的锁旗标是谁?就是这个类对应的Class对象。它就是现在我们要讲的重点。
Class 对象代表某个类的对应的字节码。它不是程序员创建而是jvm在加载字节码时生成对应的class对象。这个对象描述了类的所有信息,例如:成员变量、构造方法、成员函数等等。
获取Class对象的方式有三种:
类名.class 实例对象.getClass() class.forName(String className);
class.forName函数的作用是加载字符串指定的类到jvm中并且将生成的class对象返回。
反射的概念:反射就是将类中的元素映射成对应的java类。需要完成这些功能则类的基本信息是基础,所以包含类基本信息的class对象就成了反射的基石。
2.构造函数的反射运用
i.不带参数的构造函数
类名.class.newInstance();
ii.带参数的构造函数
Construct construc = 类名.class.getConstruct(Class[]{});
Object object = construct.newInstance(Object[]);
通过上述的2中方式我们就可以调用构造函数获取实例对象。
3.成员变量的反射作用
i.获取代表成员变量的Field对象
类名.class.getFile(String name);//这种方法不能获取私有private的成员变量
类名.class.getDeclaredFile(String name);//可以获取任何成员变量
ii.获取某个实例对象的成员变量的值
Field.get(Object target);//返回target对应的Field成员变量,不能获取私有成员变量的值
如果需要获取私有成员变量的值需要Field.setAccessible(true)来设置可访问属性。
iii.设置成员变量的值
Field.set(Object target,Object value);;//实现为target对象的field成员变量设置值为value对象。
4.成员方法的反射
i.获取代表方法的Method对象
Method method = 类名.class.getMethod(String name,Class[] parameterType);
ii.执行某个对象的method方法
method.invoke(target,Object[]{});//执行target对象的method成员方法
当调用类的静态方法时,只要设置target对象为null即可。
5.数组和Object的关系及其反射类型
先看如下几段代码:
int[] aa = new int[3];
int[] bb = new int[4];
String[] cc = new String[3];
System.out.println(aa.getClass()==bb.getClass());//输出true
System.out.println(aa.getClass().getName());//输出[I
System.out.println(cc.getClass().getName());//输出[Ljava.lang.String;
i. java中的中的任何类型都有对应class对象
ii.具有相同维数和相同元素类型是相同的类型即具有相同的class对象
iii.基本类型的一维数组可以当成Object对象使用但是不能作为Object[]使用
iv.非基本类型的一维数组可以既可以当做Object对象使用也可以作为Object[]使用
基于上述的特点在使用Arrays.asList(T ....a)等可变参数的函数时需要注意通过如下方法才能将数组对象正确的传递给参数(java1.4是通过Object[]数组来实现可变参数)
ArrayList.asList(new Object[]{int[] aa});
ArrayList.asList((Object)int[] aa);
总结:
反射在实际开发中可能不会用到但它是框架的基础和底层原理,只有在理解底层原理的基础上才能够真正的理解一个框架的工作过程,这样才能将框架吃透,为我们学习框架打好基础,这样无论学习任何框架都可以加快我们的学习深度和速度。