您的位置:首页 > 其它

包装一个简单的反射工具类

2019-05-28 14:42 281 查看

开发工具与关键技术:工具:MyEclipse 10 技术:Java
作者:范子超  撰写时间:2019-05-28

  我们为什么要包装反射工具类呢?因为我们都想偷“懒”。在我们编写代码的时候,往往都会有很多地方出现相同的语句,虽然复制粘贴可以方便我们编写这些相同的代码,但是它的代码量却不会减少,而使用反射工具类的话则能使它的代码量减少许多,同时调用这个工具类也非常简单。下面说说应该怎样包装这个反射工具类以及包装的思路。
  首先说一下查询数据的步骤:
  第一步:我们需要查询某张表的数据,那么就需要为这张表建立一个实例类来接收表内数据,实体类内容如下

public class Client {
private int clientid;// 客户id
private boolean sex;// 性别
private String clientname;// 客户名称
private String clientnumber;// 客户编号
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public int getClientid() {
return clientid;
}
public void setClientid(int clientid) {
this.clientid = clientid;
}
public String getClientname() {
return clientname;
}
public void setClientname(String clientname) {
this.clientname = clientname;
}
public String getClientnumber() {
return clientnumber;
}
public void setClientnumber(String clientnumber) {
this.clientnumber = clientnumber;
}
}

  实体类准备好后开始写查询数据的方法,把查询到的数据返回,方法内容如下

public List<Client> findAll() {
List<Client> clients = new ArrayList<Client>();
String sql = "SELECT * FROM CLIENT";
try {
con = DButil.getConnection();
ps = con.prepareStatement(sql);
rs = ps.executeQuery();         //------
Client client = null;
while (rs.next()) {
client = new Client();
client.setClientid(rs.getInt("clientid"));
client.setSex(rs.getBoolean("sex"));
client.setClientname(rs.getString("clientname"));
client.setClientnumber(rs.getString("clientnumber"));
clients.add(client);
}                               //------
} catch (SQLException e) {
e.printStackTrace();
} finally {
DButil.close(con, ps, rs);
}
return clients;
}

数据就查询出来了。

  大家可以看到,上面两个//------中间的代码,这段代码的作用就是把查询到的数据给到实体类,并把实体类添加到实体类集合中。在我们每次查询的时候都需要写这么一段大同小异代码,这就是显得有点麻烦,而包装一个反射工具类就能很好的解决这个麻烦。接下来看我们的反射工具类有什么内容:
  反射工具类中利用反射处理结果集的方法,注意这里为了演示我就直接抛出了根异常,大家不要像这里一样。
大概的思路:把查询数据的结果集,以及用来接收数据的实体类的Class对象传过来,申明这个实体类的集合用来接收数据并返回,再获取到描述结果集中所有列的对象,然后使用循环判断是否有下一条数据,在循环内创建实例类的对象并再写一个循环用来处理每一个列的字段名称,把这个字段名称处理的和实例类的成员变量名称一致,还要根据这个处理好的字段利用反射获取它在实例类中的数据类型,最后根据这个数据类型调用实例的set方法把数据给到实例类中。
  利用反射处理结果集的方法:

public static <T> List<T> getResult(ResultSet rs, Class<T> obj) throws Exception {
List<T> list = new ArrayList<T>();
ResultSetMetaData metaDate = rs.getMetaData();
while (rs.next()) {
T instance = obj.newInstance();
int count = metaDate.getColumnCount();
for (int i = 1; i <= count; i++) {
String name = metaDate.getColumnName(i);
name = toJavaField(name); // toJavaField()处理字段的方法
// 获取类型
Class<?> type = obj.getDeclaredField(name.toLowerCase()).getType();
Method setMethod = obj.getDeclaredMethod("set" + name,
type);
// ---判断读取数据的类型
if (type.isAssignableFrom(String.class)) {
setMethod.invoke(instance, rs.getString(i));
} else if (type.isAssignableFrom(int.class)
|| type.isAssignableFrom(Integer.class)) {
setMethod.invoke(instance, rs.getInt(i));
} else if (type.isAssignableFrom(short.class)
|| type.isAssignableFrom(Short.class)) {
setMethod.invoke(instance, rs.getShort(i));
} else if (type.isAssignableFrom(Boolean.class)
|| type.isAssignableFrom(boolean.class)) {
setMethod.invoke(instance, rs.getBoolean(i));
} else if (type.isAssignableFrom(Date.class)) {
setMethod.invoke(instance, rs.getDate(i));
} else if (type.isAssignableFrom(double.class)
|| type.isAssignableFrom(Double.class)) {
setMethod.invoke(instance, rs.getDouble(i));
}
}
list.add(instance);
}
return list;
}

  处理字段的方法:

public static String toJavaField(String str) {
StringBuilder builder = new StringBuilder();
String string = str.substring(0, 1).toUpperCase()
+ str.substring(1).toLowerCase();
builder.append(string);
return builder.toString();
}

  最后把两个//------中间的代码替换成下面这一句就OK了。并且数据也传递过来了。

clients = JdbcHelper.getResult(rs, Client.class);


  总结:这个反射的写法是不固定的,关键就在于你的实体类中的成员变量是怎么命名的,主要就是要把结果集中的字段拿出来处理一下,把它变的和实例类的成员变量相同,然后用反射获取数据类型。在处理一下,让他变的和实例类中的set方法名一致,用反射调用方法设置数据值。所以要想这么简便的使用放射来进行这些设置,那么你就要灵活的处理结果集中的字段使得它和实例类中的成员名称相同才可以调用的到。要不然就处理字段的方法不该变,但是实例类中的成员名称命名却要非常规范保证反射工具类那边字段处理后能够调用的到就行。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: