写这篇文章主要想讲两个问题:
- 什么是反射
- 反射存在的意义
- 反射能做哪些事
什么是反射
反射,简单的来讲,是一种在程序运行时生成对象的技术。为什么说是运行时呢,相比我们平时写代码时创建对象,比如:
1 | public static void main(){ |
我们创建对象的代码是事先写好的,那么程序在编译的时候,也就是.java
文件被编译成.class
文件的时候,这个对象就已经在class
文件中了。而反射讲的是,这个对象在编译器是不存在,在程序运行的时候,因为某种需求,它才被创建出来。
反射存在的意义
学习一种技术,更重要的是要明白它存在的意义。那么为什么要有反射呢?
反射一个最大的用途就是用在各大框架中,如Spring
,Struts2
现在的各种框架都是配置型的。下面的xml
是Stucts2
中的一个配置文件。当后台收到这个login
请求后,经过各种过滤器,最后它会和这个配置文件对应,这个配置文件里面描述了当收到这种请求后我要调用哪个类(这里就是 org.ScZyhSoft.test.action.SimpleLoginAction
类),以及类中的哪个方法(这里就是execute
方法)。但这个类其实配置文件只写了一个类名,也就是说等到真正这个请求到了,需要用到这个类的时候它才被创建,这里创建的技术就是反射。
1 | <action name="login" |
反射能做哪些事
创建实例
使用反射创建实例,首先要获得Class
对象,你可以认为它就是我们所写的类的对象类型。这句话可能有点绕,俗话说“万事万物皆对象”(当然除了基本数据类型),所以类本身也是对象,它是Class
类的对象,获取Class
对象有三种方法:
Class.forName()
比如
Class.forName(org.ScZyhSoft.test.action.SimpleLoginAction)
直接获取某个对象的
class
属性
如Class<?> klass = obj.class
调用某个对象的
getClass()
方法如
Class<?> klass = obj.getClass()
获取Class
对象之后,就可以使用Class
对象来创建实例了
- 对于默认构造函数的对象,我们可以
1 | Class<?> c = String.class; |
- 对于带参的构造函数,我们可以
1 | //获取String所对应的Class对象 |
获取方法和成员变量
获取某个Class对象的方法集合,主要有以下几个方法:
getDeclaredMethods
方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
1 | public Method[] getDeclaredMethods() throws SecurityException |
getMethods
方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。
1 | public Method[] getMethods() throws SecurityException |
getMethod
方法返回一个特定的方法,public的,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象。
1 | public Method getMethod(String name, Class<?>... parameterTypes) |
getDeclaredField
:所有已声明的成员变量,不问访问权限,但不能得到其父类的成员变量
getFileds
:访问公有的成员变量,包括继承的公用方法
getField(String name)
获取指定的变量(public)
调用方法
invoke()