当前位置: 首页 > news >正文

解决实体类噩梦:联合实体类(Java反射+泛型实际应用)

       小菜提到的实体类,即项目中业务或者数据库表的映射,貌似也可以称为模型,不同的语言中叫法不同吧!!

       举个例子,比如在某个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的反射和泛型写了一个“联合实体类”。

       通过这个联合实体类,可以把任意多个实体类融合成一个实体类。

联合实体类代码:

  1 import java.lang.reflect.Method;
  2 import java.util.List;
  3 
  4 /**
  5  * 联合实体类
  6  * @author 杨元
  7  *
  8  */
  9 public class UniteEntity {
 10     
 11     //联合实体对象集合
 12     List<Object> entitys = null;
 13     //方法名称
 14     String fnName = "";
 15     //方法对象
 16     Method method = null;
 17     
 18     /**
 19      * 构造方法
 20      * @param entitys 需要联合的实体对象集合
 21      */
 22     public UniteEntity(List<Object> entitys){
 23         this.entitys = entitys;
 24     }
 25     
 26     /**
 27      * 获取某个取值方法
 28      * @param fnName 方法名称
 29      * @return 该取值方法返回值类型
 30      */
 31     public Class getFunction(String fnName){
 32         //保存方法名称
 33         this.fnName = fnName;
 34         //查找方法
 35         Method m = findMethod();
 36         //判断方法是否存在
 37         if(m != null){
 38             //获取目标方法的返回值类型
 39             Class type = m.getReturnType();
 40             //保存取值方法对象
 41             method = m;
 42             //返回该取值方法返回值类型
 43             return type;
 44         }else{
 45             return null;
 46         }
 47     }
 48     
 49     /**
 50      * 获取某个赋值方法
 51      * @param fnName 方法名称
 52      * @return 该赋值方法参数类型
 53      */
 54     public Class setFunction(String fnName){
 55         //保存方法名称
 56         this.fnName = fnName;
 57         //查找方法
 58         Method m = findMethod();
 59         //判断方法是否存在
 60         if(m != null){
 61             //获取目标方法的参数类型
 62             Class type = m.getParameterTypes()[0];
 63             //保存赋值方法对象
 64             method = m;
 65             //返回该赋值方法参数类型
 66             return type;
 67         }else{
 68             return null;
 69         }
 70     }
 71     
 72     /**
 73      * 调用某个方法,为属性赋值
 74      * @param <T> 赋值方法的参数类型
 75      * @param c
 76      * @param value 值内容
 77      */
 78     public <T> void setValue(Class<T> c,T value){
 79         //遍历实体类集合
 80         for(Object o : entitys){
 81             //出错继续执行
 82             try{
 83                 method.invoke(o, value);
            break;
84 }catch(Exception ex){} 85 } 86 } 87 88 /** 89 * 调用某个方法,取得属性的值 90 * @param <T> 取值方法的返回值类型 91 * @param c 92 * @return 取得值的内容 93 */ 94 public <T> T getValue(Class<T> c){ 95 //遍历实体类集合 96 for(Object o : entitys){ 97 //出错继续运行 98 try{ 99 //由于invoke返回的是Object类型,因此要强制转换成T类型 100 return (T)method.invoke(o); 101 }catch(Exception ex){} 102 } 103 return null; 104 } 105 106 /** 107 * 从实体对象集合中查找某个方法 108 * @return 方法对象 109 */ 110 private Method findMethod(){ 111 //遍历集合,寻找方法 112 for(Object o : entitys){ 113 //保证出错能继续运行 114 try{ 115 //获取对象所有公有方法 116 Method[] methods = o.getClass().getMethods(); 117 118 //遍历方法 119 for(Method m : methods){ 120 //匹配是否有目标方法 121 if(fnName.equals(m.getName())){ 122 //返回方法对象 123 return m; 124 } 125 } 126 }catch(Exception ex){} 127 } 128 return null; 129 } 130 }

 

调用方法:

 

 1 //创建一个对象集合
 2 List<Object> list = new ArrayList<Object>();
 3 
 4 //将需要融合的实体类填入集合
 5 list.add(new User());
 6 list.add(new Enterprise());
 7 
 8 //创建联合实体类对象
 9 UniteEntity ue = new UniteEntity(list);
10 
11 int i = 109;
12 
13 //调用实体类中方法名为setEnno的方法(赋值方法),并给一个参数i
14 ue.setValue(ue.setFunction("setEnno"), i);
15 //调用实体类中方法名为getEnno的方法(取值方法),并打印返回值
16 System.out.println(ue.getValue(ue.getFunction("getEnno")));

 

说明:

 

       用法很简单,创建联合实体对象的时候必须传入需要融合的实体对象集合。

       如果想调用的方法是取值方法,则先调用联合实体对象的getFunction方法,参数是方法的名称,一定要写对!!最好是复制!!这个步骤会查找到指定的方法,并且确定该方法的返回值类型,然后把getFunction方法的返回值作为参数,调用联合实体对象的getValue方法,即可取得属性值。

       如果想调用的方法是赋值方法,则先调用联合实体对象的setFunction方法,同理,该方法会确定参数的类型,把setFunction方法的返回值作为参数,调用联合实体对象的setValue方法,再加上需要赋给的值,即可给属性赋值。

       由于使用了泛型技术,所以本类比较安全、稳定。调用赋值方法时,如果传入的值和方法的参数类型不同,直接赋值失败,不会抛出异常;调用取值方法时,直接对取出来的值进行强制类型转换即可,无需验证数据类型(例如:int[] items = (int[])ue.getValue(ue.getFunction("getEmp"));)。

注意事项:

 

       使用本类肯定会降低程序效率,慎重使用。

       本类只支持带有一个参数的属性赋值方法。

       如果多个实体类中有重复的方法名称,则默认使用的是在集合中靠前的那个实体类的方法。

写在后面的话:

 

       本文只是提供一种思路,肯定不是最好的解决方案,也不一定能满足读者的需求,高手勿喷。。。

附:完整演示代码

 

       点我下载

 

 

相关文章:

  • proxool数据连接池
  • pdns和powreadmin的安装
  • Jira:必选项设置(创建缺陷、修复缺陷)
  • 如何解读数码相机的直方图
  • CSS3实现的3D按钮精美效果
  • 【零基础学习iOS开发】【01-前言】03-前景和难易度分析
  • OBJEct-c中NSDictionary的用法
  • 数据库设计-主键的设计
  • 移动开发者如何获取免费流量(转载)
  • Aspose.Pdf for Java 4.0 发布
  • 【parser】stanford-parser demo使用
  • 程序环境基于 IO密集 CPU密集考量 SAN NAS 选择的一点建议
  • SQL Server修改标识列方法
  • Uva 10085 - The most distant state
  • java数据类型与Sql server数据类型对应关系
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • bootstrap创建登录注册页面
  • canvas 五子棋游戏
  • CSS3 变换
  • Cumulo 的 ClojureScript 模块已经成型
  •  D - 粉碎叛乱F - 其他起义
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Magento 1.x 中文订单打印乱码
  • React系列之 Redux 架构模式
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 设计模式 开闭原则
  • 赢得Docker挑战最佳实践
  • 正则与JS中的正则
  • No resource identifier found for attribute,RxJava之zip操作符
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (C语言)逆序输出字符串
  • (zhuan) 一些RL的文献(及笔记)
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (七)c52学习之旅-中断
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (四) 虚拟摄像头vivi体验
  • (四)汇编语言——简单程序
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • .NET 8.0 发布到 IIS
  • .Net CF下精确的计时器
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .net和php怎么连接,php和apache之间如何连接
  • ::前边啥也没有
  • @ModelAttribute 注解
  • [ C++ ] STL_list 使用及其模拟实现