一、反射是什么?
书本上的反射机制说法很学术,如果需要的话可以自行百度,此处只给出自己对反射的理解。Java的反射机制(reflect)是基于java虚拟机的,用于RTTI,即Run-Time-Type-Information,运行时确定类型信息。使用时需要导入java.lang.reflect包。
二、为什么要用反射?
个人理解,有两种情况下用反射很方便。
第一种,数据库操作。如果数据库中有很多表,那么每个表的增删改查(CRUD)操作都单独写一个DAO类就会很痛苦,而且后续可能还会增加新的表,或者表中结构会有变动,那就要新增DAO或者修改之前的DAO,而这些都是些重复性的、没有创造性的工作,对这部分工作我们应该让程序自动运行。那么问题来了,对于不同的数据库表,字段不同,传入的对象结构不同,如何统一写CRUD语言呢?请看下一节。
第二种,多人协同开发。举个例子吧,在做一个手机app的时候,我负责DAO模块。一开始我约束上层人员传给我数据库table名、条件语句等等,那么上层的工作就会很繁琐。后来我在自己反思的时候,修改了当时的设计模式,上层传给我的就是几个约定好的类对象,我从中去读取信息。因为不知道上层会在什么时候调用我的函数,甚至可能上层也不知道,是在用户使用的时候才会产生,那么对这几个类我就可以用反射合并起来,在运行时读取信息。(这一段可能没有表述清楚,总之反射是可以归并几种重复类型,减少工作量的好方法)
三、如何使用反射?
首先创建一个Class对象c,创建方法有多种,如果有参数Type t传入,可以用t.getClass()获得;如果没有,可以用new Class("类名")。因为c是不确定类型的,就达到了RTTI的目的。之后我们就可以用c做很多事情。下面举几个例子。
c.getFields()获取c中所有public字段,返回值为Fields[];c.getDeclaredFields(),获取c中所有字段,包括public,protected,private;同理的还有c.getMethods(),c.getDecalredMethods(),c.getConstructors(),c.getDeclaredConstructors();
c.getName()可以获取c的类名称全名,c.getSimpleName()可以获取c的简称(不包含包名);
对于上一节的问题,多个数据库表的CRUD操作,可以在DaoImpl层中读取传入的对象,提取其class,然后读取其字段和所有的get方法,获得对象信息,进而拼接sql字符串,操作数据库。
反射最神奇的一点就是可以用字符串访问某个对象中的方法,这也是反射中很重要的技术,因为这样才能在运行时动态获取目标对象的函数。使用方法为,Method m=c.getMethod("getUser",null);(第二个参数表示输入参数类型,是一个Array变量)。调用时用t.invoke(m,Object... args)。