什么是反射
用比较官方的话来说,反射就是java语言中的一种机制,通过这种机制能够
动态
读写属性,调用方法,实例化对象,它能让我们更灵活的操作代码,对于框架设计来说,反射就是基础.
看到这里,懵逼了吧?哈哈哈哈,换句话说,就是对于任意一个类,都能通过反射获取到属性、方法和实例化对象。什么?还不懂,举个比较通俗的例子:
有个人叫小明,会唱歌跳舞,看成对象,那么,他的name属性就是小明,行为方法就是会唱歌,除了了解他的人,可能才知道他叫小明,他会唱歌,但是不认识他的人呢,他也知道,没错,他就是反射!!
反射的运用案例
有一个学生类,常规我们实例化对象,都是直接这样:
Student stu=new Student();
而反射是这样:
//反射获取类对象
Class<?> clz = Class.forName("com.xiaoyang.Student");
//反射实例化对象
Student newInstance =(Student) clz.newInstance();
看到这,是不是困惑了?反射代码不是更多了吗?但是要知道,我们发布一个项目到服务器,服务器是并不知道我们要实例化什么类的,那么它是怎么获取到我们自己项目中的类对象的呢?看web.xml配置文件:
<servlet>
<servlet-name>jrebelServlet</servlet-name>
<servlet-class>com.xml.JrebelServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jrebelServlet</servlet-name>
<url-pattern>/jrebelServlet</url-pattern>
</servlet-mapping>
项目在发布时,它会有一个请求路径,也就是
<url-pattern>/jrebelServlet</url-pattern>
服务器会通过这个请求路径,通过建模,获取到
<servlet-name>jrebelServlet</servlet-name>
再通过获取到的servlet-name值,在
<servlet>
<servlet-name>jrebelServlet</servlet-name>
<servlet-class>com.xml.JrebelServlet</servlet-class>
</servlet>
中获取到servlet-class,也就是我们项目中的处理操作的类。像tomcat服务器,它也是要获取请求路径,然后获取到项目里的类对象进行记成htppservlet类,然后再进行操作的
反射的常用方法
所有的反射,都是从获取类对象开始的,获取类对象,我们有三种方式:
Class<?> clz = Class.forName("com.xiaoyang.Student");
- 类名.class
Class clz=Student.class;
- 类对象.getClass();
Student stu=new Student(); Class<? extends Student> clz = stu.getClass();
获取类对象后,我们就可以用反射进行操作了,首先是调用构造方法:
//无参构造方法
Class<?> clz = Class.forName("com.xiaoyang.Student");
Object stu = clz.newInstance();
//一个参数的构造方法
Constructor<?> constructor = clz.getConstructor(String.class);
Student newInstance =(Student) constructor.newInstance("s001");
//两个参数的构造方法
Constructor<?> constructor2 = clz.getConstructor(String.class,String.class);
Student newInstance2 = (Student)constructor2.newInstance("s001","zs");` //调用私有构造方法
Constructor<?> declaredConstructor = clz.getDeclaredConstructor(Integer.class);
declaredConstructor.setAccessible(true);
Object newInstance3 = declaredConstructor.newInstance(22);`
用反射读写属性:
//反射获取类对象
Class<?> clz = Class.forName("com.xiaoyang.Student");
//反射实例化对象
Student newInstance =(Student) clz.newInstance();
//给对象赋值
newInstance.setSname("zs");
//反射读取属性
Field field = clz.getDeclaredField("sname");
field.setAccessible(true);
反射读写属性这里,还有一个比较重要的方法就是获取类的所有属性值:
//反射读取类所有属性值
Field[] fields = clz.getDeclaredFields();
for (Field field2 : fields) {
field2.setAccessible(true);
System.out.println(field2.get(newInstance));
}
然后就是反射调用方法:
//反射获取类对象
Class<?> clz = Class.forName("com.xiaoyang.Student");
//反射实例化对象
Object stu = clz.newInstance();
//获取方法
Method method = clz.getMethod("hello");
私有方法:
Method method3 = clz.getDeclaredMethod("add",Integer.class ,Integer.class);
method3.setAccessible(true);
Object invoke3 = method3.invoke(stu,20,5);
需要注意的是,所有的私有
属性、方法,都需要加上这个方法:
setAccessible(true)
尾言
反射对于框架来说,无疑是非常重要的,框架的设计者,并不会知道使用者的项目会建什么类,创建什么方法,使用反射,就可以实现了.所以理解好反射,可以更好的理解框架的原理和灵活操作代码…