1.反射是什么
在说明反射之前,有两个概念必须说明一下,那就是动态加载和静态加载。
静态加载
在创建实例对象时,被实例化的类需要在编译之前被引入到程序中的加载方式。例如:
Test test = new test();
在实例化test对象之前,系统必须要先把Test类进行编译,调用构造方法,否则就会报错。
动态加载
类在编译之后,运行时才进行加载。例如:
Class test = Class.forName("Test");
test.newInstance()
这个地方的Test类就算不存在,程序在编译的时候仍然不会报错,只有在运行到这里的时候 ,找不到Test类才会报错。
简单的说,反射是以动态加载的方式,获取一个对象的所有属性,包括成员变量、方法、类名等等信息,并且可以直接进行对象方法的调用的一种机制。
2.反射的使用方式
在java中,一切皆是对象,一个类的实例是对象,一个类本身也是一个对象。
Apple apple = new Apple();
上面的代码表示apple是Apple类的对象,但是这里还有一个隐藏的概念:Apple类也是java.lang.Class类的对象,这个Class类被称为类类型“Class type“,任何类都是Class类的实例对象。
获取类类型的方式一共有三种:
Class c1 = apple.getClass();
Class c2 = Apple.class;
Class c3 = Class.forName('Apple');
一个类就是Class类的一个实例对象,也就是说这里的c1==c2==c3。
当获取到类类型后,我们就能够自由获取这个类的所有属性了,例如:
String className = c1.getClassName(); //获取类的全名
Field[] field = c1.getFields(); //获取类的成员变量
Constructor constructor= c1.getConstructor(new Class[]); //获取类的构造方法
Method method = c1.getMethod(methodName,param1,param2 ...); //根据方法名和参数获取类的指定方法
...
获取到这些信息后,我们能够利用这些进行实例化对象或是方法调用等操作,比如:
Object obj1 = constructor.newInstance({new object(){}) //调用构造方法实例化对象
Object obj2 = method.invoke(apple,param1,param2 ...) //调用已经获取到的方法
3.反射的应用
1.工厂设计模式的对象创建:根据用户输入的类名称,调用此类的构造方法返回用户需要的对象。
2.读取配置文件:读取用户在配置文件中的类名称构造相应对象,用户指定一个配置文件,由于反射是动态加载的,因此用户在修改配置文件后可以立即读取文件中的内容,动态产生相应的对象,不用重新编译,这使得程序更加灵活。
3.多功能接口:发布一个接口,这个接口接收执行方法和执行对象两个参数,用户在调用接口时制定执行对象和执行方法,程序就可以自行生成执行对象调用执行方法,而不用为了多个功能提供多个接口。
以上只列举了部分应用场景,更多应用场景需要继续探索,总的说来反射机制是一个非常灵活的机制,但是反射比起直接调用会在一定程度上降低程序执行速度,请谨慎使用。