解决实体类噩梦:联合实体类(Java反射+泛型实际应用)
2013-04-19 00:16
363 查看
小菜提到的实体类,即项目中业务或者数据库表的映射,貌似也可以称为模型,不同的语言中叫法不同吧!!
举个例子,比如在某个Web页面中,表单上有大量的数据需要提交,如果是初学者,很可能这样接收参数:
String param1;String param2;String param3;……
这样做的坏处很多,比如:代码会显得很乱,可能会出现大量重复代码,最主要的就是没有做到面向对象的“封装性”,导致程序不容易维护。
由此,聪明的程序员们提出了实体类的概念,也就是用类来封装业务所需要的数据。
public class User {
private String uid;
private String pwd;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
…..
}
这样一来,我们在保存数据时,只需创建一个对象,然后通过“.”的方式来访问对象的属性,提高扩展性、提高复用性、代码简洁等等好处不言而喻。
在实际使用中,实体类往往是和某个业务或者数据库表相对应的,看起来很简单,但随着需求的复杂化,业务和业务之间可能会交叉,表和表之间可能会联合查询。
这样一来,以前一一对应的实体类,便无法满足需求,因为某个实体类中可能找不到我们需要的属性,但是它却在另一个实体类中,而我们又不想随便在某个实体类中添加一个毫不相关的属性,因为这样做可能会打破类的职责单一原则。
因此,我们不得不再新建一个实体类ClassAAndClassB,这个实体类包含了类A和类B的所有属性,对于稍有经验的程序员来说,这绝对是个噩梦,因为组合的可能性是在是太多,而且可能是很多个实体组合,等待我们的将是无数的实体类,导致程序混乱不堪。
小菜一直苦于此事,今天终于通过Java的反射和泛型写了一个“联合实体类”。
通过这个联合实体类,可以把任意多个实体类融合成一个实体类。
联合实体类代码:
调用方法:
说明:
用法很简单,创建联合实体对象的时候必须传入需要融合的实体对象集合。
如果想调用的方法是取值方法,则先调用联合实体对象的getFunction方法,参数是方法的名称,一定要写对!!最好是复制!!这个步骤会查找到指定的方法,并且确定该方法的返回值类型,然后把getFunction方法的返回值作为参数,调用联合实体对象的getValue方法,即可取得属性值。
如果想调用的方法是赋值方法,则先调用联合实体对象的setFunction方法,同理,该方法会确定参数的类型,把setFunction方法的返回值作为参数,调用联合实体对象的setValue方法,再加上需要赋给的值,即可给属性赋值。
由于使用了泛型技术,所以本类比较安全、稳定。调用赋值方法时,如果传入的值和方法的参数类型不同,直接赋值失败,不会抛出异常;调用取值方法时,直接对取出来的值进行强制类型转换即可,无需验证数据类型(例如:int[] items = (int[])ue.getValue(ue.getFunction("getEmp"));)。
注意事项:
使用本类肯定会降低程序效率,慎重使用。
本类只支持带有一个参数的属性赋值方法。
如果多个实体类中有重复的方法名称,则默认使用的是在集合中靠前的那个实体类的方法。
写在后面的话:
本文只是提供一种思路,肯定不是最好的解决方案,也不一定能满足读者的需求,高手勿喷。。。
附:完整演示代码
点我下载
举个例子,比如在某个Web页面中,表单上有大量的数据需要提交,如果是初学者,很可能这样接收参数:
String param1;String param2;String param3;……
这样做的坏处很多,比如:代码会显得很乱,可能会出现大量重复代码,最主要的就是没有做到面向对象的“封装性”,导致程序不容易维护。
由此,聪明的程序员们提出了实体类的概念,也就是用类来封装业务所需要的数据。
public class User {
private String uid;
private String pwd;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
…..
}
这样一来,我们在保存数据时,只需创建一个对象,然后通过“.”的方式来访问对象的属性,提高扩展性、提高复用性、代码简洁等等好处不言而喻。
在实际使用中,实体类往往是和某个业务或者数据库表相对应的,看起来很简单,但随着需求的复杂化,业务和业务之间可能会交叉,表和表之间可能会联合查询。
这样一来,以前一一对应的实体类,便无法满足需求,因为某个实体类中可能找不到我们需要的属性,但是它却在另一个实体类中,而我们又不想随便在某个实体类中添加一个毫不相关的属性,因为这样做可能会打破类的职责单一原则。
因此,我们不得不再新建一个实体类ClassAAndClassB,这个实体类包含了类A和类B的所有属性,对于稍有经验的程序员来说,这绝对是个噩梦,因为组合的可能性是在是太多,而且可能是很多个实体组合,等待我们的将是无数的实体类,导致程序混乱不堪。
小菜一直苦于此事,今天终于通过Java的反射和泛型写了一个“联合实体类”。
通过这个联合实体类,可以把任意多个实体类融合成一个实体类。
联合实体类代码:
import java.lang.reflect.Method; import java.util.List; /** * 联合实体类 * @author 杨元 * */ public class UniteEntity { //联合实体对象集合 List<Object> entitys = null; //方法名称 String fnName = ""; //方法对象 Method method = null; /** * 构造方法 * @param entitys 需要联合的实体对象集合 */ public UniteEntity(List<Object> entitys){ this.entitys = entitys; } /** * 获取某个取值方法 * @param fnName 方法名称 * @return 该取值方法返回值类型 */ public Class getFunction(String fnName){ //保存方法名称 this.fnName = fnName; //查找方法 Method m = findMethod(); //判断方法是否存在 if(m != null){ //获取目标方法的返回值类型 Class type = m.getReturnType(); //保存取值方法对象 method = m; //返回该取值方法返回值类型 return type; }else{ return null; } } /** * 获取某个赋值方法 * @param fnName 方法名称 * @return 该赋值方法参数类型 */ public Class setFunction(String fnName){ //保存方法名称 this.fnName = fnName; //查找方法 Method m = findMethod(); //判断方法是否存在 if(m != null){ //获取目标方法的参数类型 Class type = m.getParameterTypes()[0]; //保存赋值方法对象 method = m; //返回该赋值方法参数类型 return type; }else{ return null; } } /** * 调用某个方法,为属性赋值 * @param <T> 赋值方法的参数类型 * @param c * @param value 值内容 */ public <T> void setValue(Class<T> c,T value){ //遍历实体类集合 for(Object o : entitys){ //出错继续执行 try{ method.invoke(o, value); break; }catch(Exception ex){} } } /** * 调用某个方法,取得属性的值 * @param <T> 取值方法的返回值类型 * @param c * @return 取得值的内容 */ public <T> T getValue(Class<T> c){ //遍历实体类集合 for(Object o : entitys){ //出错继续运行 try{ //由于invoke返回的是Object类型,因此要强制转换成T类型 return (T)method.invoke(o); }catch(Exception ex){} } return null; } /** * 从实体对象集合中查找某个方法 * @return 方法对象 */ private Method findMethod(){ //遍历集合,寻找方法 for(Object o : entitys){ //保证出错能继续运行 try{ //获取对象所有公有方法 Method[] methods = o.getClass().getMethods(); //遍历方法 for(Method m : methods){ //匹配是否有目标方法 if(fnName.equals(m.getName())){ //返回方法对象 return m; } } }catch(Exception ex){} } return null; } }
调用方法:
//创建一个对象集合 List<Object> list = new ArrayList<Object>(); //将需要融合的实体类填入集合 list.add(new User()); list.add(new Enterprise()); //创建联合实体类对象 UniteEntity ue = new UniteEntity(list); int i = 109; //调用实体类中方法名为setEnno的方法(赋值方法),并给一个参数i ue.setValue(ue.setFunction("setEnno"), i); //调用实体类中方法名为getEnno的方法(取值方法),并打印返回值 System.out.println(ue.getValue(ue.getFunction("getEnno")));
说明:
用法很简单,创建联合实体对象的时候必须传入需要融合的实体对象集合。
如果想调用的方法是取值方法,则先调用联合实体对象的getFunction方法,参数是方法的名称,一定要写对!!最好是复制!!这个步骤会查找到指定的方法,并且确定该方法的返回值类型,然后把getFunction方法的返回值作为参数,调用联合实体对象的getValue方法,即可取得属性值。
如果想调用的方法是赋值方法,则先调用联合实体对象的setFunction方法,同理,该方法会确定参数的类型,把setFunction方法的返回值作为参数,调用联合实体对象的setValue方法,再加上需要赋给的值,即可给属性赋值。
由于使用了泛型技术,所以本类比较安全、稳定。调用赋值方法时,如果传入的值和方法的参数类型不同,直接赋值失败,不会抛出异常;调用取值方法时,直接对取出来的值进行强制类型转换即可,无需验证数据类型(例如:int[] items = (int[])ue.getValue(ue.getFunction("getEmp"));)。
注意事项:
使用本类肯定会降低程序效率,慎重使用。
本类只支持带有一个参数的属性赋值方法。
如果多个实体类中有重复的方法名称,则默认使用的是在集合中靠前的那个实体类的方法。
写在后面的话:
本文只是提供一种思路,肯定不是最好的解决方案,也不一定能满足读者的需求,高手勿喷。。。
附:完整演示代码
点我下载
相关文章推荐
- 解决实体类噩梦:联合实体类(Java反射+泛型实际应用)
- 解决实体类噩梦:联合实体类(Java反射+泛型实际应用)
- JAVA的泛型与反射的联合应用
- java 通过反射获得泛型的实际类型参数
- Java反射TypeToken解决泛型运行时类型擦除问题
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
- java 高新技术【9.2】 泛型类以及反射在泛型中的应用
- java基础-反射 --通过反射 获取泛型实际类型参数
- Java 反射在实际开发中的应用
- Java 泛型学习(三)通过反射获得泛型的实际类型参数
- java 浅谈反射在实际场景中应用
- java动态与反射的基本原理及实际应用
- Java反射泛型应用
- Java通过反射获取泛型实际类型总结(什么可获取,什么不可获取)
- Java 反射在实际开发中的应用
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
- Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合
- 基于java反射筛选List对于不同实体泛型的公共方法
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
- java入门笔记一:浅谈反射(reflect)&泛型(genericity)在通用数据访问库中的应用