本篇文章主要从下面几个方面讲解反射
一、反射是什么
引用书本的定义,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。反射是一种具有与类进行动态交互能力的一种机制 为什么要强调动态交互呢?因为一般情况下都是动态加载,也就是在运行的时候才会加载,而不是在编译的时候,在需要的时候才进行加载获取,或者说你可以在任何时候加载一个不存在的类到内存中,然后进行各种交互,或者获取一个没有公开的类的所有信息,换句话说,开发者可以随时随意的利用反射的这种机制动态进行一些特殊的事情。反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。
解释下两个名词:
编译:正向过程
就是将.java源码转成.class字节码文件的过程
反编译:反向过程
将.class字节码文件转成.java源文件的过程
反射其实就是一种反编译,通过反向来获取java类的信息,并进行操作(此过程是在运行中),回想下我们在正常编写代码时,如果一个类中有私有属性或者方法,那这个私有的属性或者方法,是不是只能在该类中进行调用,在其它地方就访问不到了。而通过反射技术就可以在任意时候操作这个类中私有的属性或者方法,可以说是非常规的手段。
二、反射的作用
反射可以将一个类的构造函数,成员变量,成员方法映射成一个个对应的对象,构造函数-->Constructor对象,成员变量-->Field对象,成员方法--->Method对象。通过反射技术可以解决以下几个方面的问题
● 需要访问隐藏属性(private)或者调用方法改变程序原来的逻辑,这个在开发中很常见的,由于一些原因,系统并没有开放一些接口出来,这个时候利用反射是一个有效的解决方法。
● 自定义注解,注解就是在运行时利用反射机制来获取的。
●在开发中动态加载类,比如在Android中的动态加载解决65k问题等等,模块化和插件化都离不开反射,离开了反射寸步难行。
三、反射的原理
我们知道,每个java文件最终都会被编译成一个.class文件,这些Class对象承载了这个类的所有信息,包括父类、接口、构造函数、方法、属性等,这些class文件在程序运行时会被ClassLoader加载到虚拟机中。当一个类被加载到内存以后,Java虚拟机就会在内存中自动为之创建一个Class对象,每一个类只会创建一个Class对象。而这个Class对象就拥有这个类里面所有的信息,那如果我们拥有了这个Class对象的引用,就可以获取这个类里面所有的属性和调用里面定义的方法,在Java中,有了对象的引用就有了一切,剩下怎么发挥是开发者自己的想象力所能决定的了。每一个类(任意一种数据类型(包含基本数据类型))都有对应的Class对象,比如,String对应的Class对象就是String.class,int类型对应的Class对象就是int.class。以下引用一个类被加载到内存的流程图
四、反射的使用
从上面的原理可以看出,要对某一个类进行反射的必要前提条件是要先获取这个类对应的Class对象(所以只有这个类已经被加载了,才可以对它进行反射操作,因为只有被加载之后才有Class对象),然后才能操作里面的成员变量和方法。
一、获取类的Class对象(三种方式)
1、通过Object.getClass()获取
public class Car {
public class Test {
public static void main(String[] args) {
Car car = new Car();
Class clazz = car.getClass();
}
}
注意,这种方法不适合基本类型如 int、float 等等。
2、通过类的属性.class获取
public class Test {
public static void main(String[] args) {
Class clazz = Car.class;
Class cls1 = int.class;
Class cls2 = String.class;
}
}
3、通过Class.forName()方法获取(推荐)
public class Test {
public static void main(String[] args) {
try {
Class clz = Class.forName("com.example.Car");
} catch (ClassNotFoundExcep