1. 什么是反射?
反射主要是指程序可以访问,检测和修改它本身的状态或行为的一种能力。
初读概念可能难以知道反射有什么作用。那我们接着往下看。
2. 反射有何用途?
Java中的反射是一种强大的工具,它能够创建灵活的代码,这些代码可以在运行时装配,无须在组件之间进行链接。
当我们从数据库中查询数据,并返回了一个ResultSet,但我们需要将ResultSet中的数据转成我们需要的List形式。常规的做法是遍历ResultSet,并在遍历体中将值赋给List。若是我们的数据表较少,并且查询的字段也足够少,我们勉强能接受这种“笨”方法。若是表很多并且一张表中有多达三四十个字段呢?那我们得写多少遍历?一个遍历中得写多少类似于rs.getXX("字段名")这样的代码?
我们既然知道数据库中返回的是什么字段,并且基本与我们的某个实体类属性相吻合,我们能否让他们自己去匹配呢?
答案当然是可以的,我们用JAVA的反射机制就可以实现这一功能。用反射创建灵活的代码!
我们需要一个可以在运行时将ResultSet中的一行结果与我们的目标实体类相互匹配,将相匹配的字段自动从当前ResultSet行填充到实体类中,若字段名不匹配则跳过,并依次循环添加到List中。这样我们就可以运用反射功能完成数据的自动填充。
我们对ResultSet进行遍历并将他的列明存入一个List<String>:
/** * 获取ResultSet各列名 * * @param rs * @return * @throws SQLException */ private List<String> getColumnNames(ResultSet rs) throws SQLException { int count = rs.getMetaData().getColumnCount(); // String[] columnName = new String[count]; List<String> columnName = new ArrayList<>(); for (int i = 1; i <= count; i++) { columnName.add(rs.getMetaData().getColumnName(i)); } return columnName; }
接下来我们需要用ResultSet的列名与我们需要返回的实体类属性相匹配,已知实体类类名XX.getClass(),需要返回什么类型我们不知道,用泛型T来代替。方法申明如下:
<span style="white-space:pre"> </span>public <T> List<T> toList(ResultSet rs, Class<T> clazz)
获取T类型字段:
try { t = clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 获取T类型各字段 Field[] t_fields = t.getClass().getDeclaredFields();
那么ResultSet的各列名与目标实体类属性我们都已经获取到了,接下来让他们两辆配对,两两配对我们必定要用到循环嵌套:
for (Field field : t_fields) { fieldName = field.getName(); Method method; for (String columnName : columnNames) { if (columnName.toLowerCase().equals( fieldName.toLowerCase())) { if (rs.getObject(columnName) != null) { String setMethodName = getMethodName(fieldName); method = t.getClass().getDeclaredMethod( setMethodName, field.getType()); method.invoke( t, convertDataType(field.getType(), rs .getObject(field.getName()) .toString())); } columnNames.remove(columnName); break; } } if (columnNames.size() == 0) { break; } }
比较的时候注意大小写同步,如果已经匹配成功,我们则要将ResultSet行中对应列名的值赋值给实体类t,此时我们需要能访问t的setter方法来赋值,已知属性名查询对应set方法名:
/** * 查询方法名 * * @param fieldName * @return */ private String getMethodName(String fieldName) { String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); return methodName; }
方法名知道了我们还需要去获取到这个方法:
Method method = t.getClass().getDeclaredMethod(setMethodName, field.getType());
Method我们已经获取成功了,接下来就是最后一部通过set方法给实体类赋值了:
method.invoke(t,convertDataType(field.getType(), rs.getObject(field.getName()).toString()));
至此我们通过反射来给实体类赋值就结束了。
有兴趣的可以去查询下反射类的API,主要从以下几个类获取方法:
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
完整类代码链接:http://download.csdn.net/detail/wang124454731/9457303