2019独角兽企业重金招聘Python工程师标准>>>

场景描述:

我需要开发四个页面,每个页面都是只涉及增删改查的基本逻辑。

最简单的写法:

创建四个接口A,B,C,D,每个接口中都声明了增删改查四个方法,完全一致

public Map<String,Object> delete(HttpServletRequest request, User user);public Map<String,Object> query(HttpServletRequest request, User user, Map<String, Object> params);public Map<String,Object> insert(HttpServletRequest request, User user);public Map<String,Object> update(HttpServletRequest request, User user);

为上面四个接口分别创建四个实现类,复写接口中的增删改查方法

接口A的实现类

@Override
public Map<String, Object> delete(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "delete");return commandExecutor.execute(new DaoAImpl(request, params, user));
}
@Override
public Map<String, Object> query(HttpServletRequest request, User user,   Map<String, Object> params) {params = null == params ? new HashMap<String,Object>() : params;params.put("operation", "query");return commandExecutor.execute(new DaoAImpl(request, params, user));
}
@Override
public Map<String, Object> insert(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "insert");return commandExecutor.execute(new DaoAImpl(request, params, user));
}
@Override
public Map<String, Object> update(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "update");return commandExecutor.execute(new DaoAImpl(request, params, user));
}

接口B的实现类

@Override
public Map<String, Object> delete(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "delete");return commandExecutor.execute(new DaoBImpl(request, params, user));
}
@Override
public Map<String, Object> query(HttpServletRequest request, User user,   Map<String, Object> params) {params = null == params ? new HashMap<String,Object>() : params;params.put("operation", "query");return commandExecutor.execute(new DaoBImpl(request, params, user));
}
@Override
public Map<String, Object> insert(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "insert");return commandExecutor.execute(new DaoBImpl(request, params, user));
}
@Override
public Map<String, Object> update(HttpServletRequest request, User user) {Map<String,Object> params = new HashMap<String,Object>();params.put("operation", "update");return commandExecutor.execute(new DaoBImpl(request, params, user));
}

接口C,D 的实现类就不在展示了。其中主要区别就是:

ServiceAImpl调用DaoAImpl的对象

ServiceBImpl调用DaoBImpl的对象

ServiceCImpl调用DaoCImpl的对象

ServiceDImpl调用DaoDImpl的对象

看完上面的代码,你可以发现,重复的代码太多了,需要整理下

解决方案:

接口:可以将增删改查的方法声明放到一个基础接口中,然后继承这个基础接口就行。

基础service接口

package com.engine.odoc.service;import java.util.Map;import javax.servlet.http.HttpServletRequest;import weaver.hrm.User;public interface BaseService {public Map<String,Object> delete(HttpServletRequest request, User user);public Map<String,Object> query(HttpServletRequest request, User user, Map<String, Object> params);public Map<String,Object> insert(HttpServletRequest request, User user);public Map<String,Object> update(HttpServletRequest request, User user);
}

继承基础service接口的接口

package com.engine.odoc.service;public interface ServiceA extends BaseService {}
package com.engine.odoc.service;public interface ServiceB extends BaseService {}
package com.engine.odoc.service;public interface ServiceC extends BaseService {}
package com.engine.odoc.service;public interface ServiceD extends BaseService {}

接口的实现:同样是增删改查四个复写的方法,唯一不同的就是不同的实现类调用不同的持久层(DAO)对象。期初的想法与处理接口的想法一样,把复写的增删改查方法写到一个基础service实现类中,然后继承这个基础service实现类即可。

为了能实现这个功能,我们需要用到Java中的泛型和反射知识

新建一个基础service实现类

package com.engine.odoc.service.impl;public class BaseServiceImpl<T> implements BaseService {@Overridepublic Map<String, Object> delete(HttpServletRequest request, User user) {}@Overridepublic Map<String, Object> query(HttpServletRequest request, User user, Map<String, Object> params) {}@Overridepublic Map<String, Object> insert(HttpServletRequest request, User user) {}@Overridepublic Map<String, Object> update(HttpServletRequest request, User user) {}}

可以看到这个基础service实现类接受了一个类型参数T

那些继承了这个基础实现类的类,就可以通过这个类型参数,把需要调用的Dao层对象的类型传递到父类当中

package com.engine.odoc.service.impl;public class ServiceAImpl extends BaseServiceImpl<DaoAImpl> implements ServiceA {}
package com.engine.odoc.service.impl;public class ServiceBImpl extends BaseServiceImpl<DaoBImpl> implements ServiceB {}
package com.engine.odoc.service.impl;public class ServiceCImpl extends BaseServiceImpl<DaoCImpl> implements ServiceC {}
package com.engine.odoc.service.impl;public class ServiceDImpl extends BaseServiceImpl<DaoDImpl> implements ServiceD {}

接下来,我们需要思考的是,如何通过这个类型参数T,来得到T的一个实例。

我们先上菜

package com.engine.odoc.service.impl;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import com.engine.odoc.service.BaseService;public class BaseServiceImpl<T> implements BaseService {public Class cusClass;public BaseServiceImpl() {// 获取T.classType genericSuperclass = this.getClass().getGenericSuperclass();if(genericSuperclass instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;Type[] typeArray = parameterizedType.getActualTypeArguments();if(null != typeArray && typeArray.length>0) {cusClass = (Class) typeArray[0];}}}/*** 获取T类的实例* @param request* @param params* @param user* @return*/private T getTInstance(HttpServletRequest request, Map<String,Object> params, User user) {try {return (T) cusClass.getConstructor(new Class[]{HttpServletRequest.class, Map.class, User.class}).newInstance(request, params, user);} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic Map<String, Object> delete(HttpServletRequest request, User user) {}@Overridepublic Map<String, Object> query(HttpServletRequest request, User user,    Map<String, Object> params) {}@Overridepublic Map<String, Object> insert(HttpServletRequest request, User user) {}@Overridepublic Map<String, Object> update(HttpServletRequest request, User user) {}}

我们可以看到,我们在这个基础service实现类的默认构造函数中确认了类型参数T的类型,得到T.class。之后在getTInstance() 方法中通过反射的方式获取了T的实例。

Type genericSuperclass = this.getClass().getGenericSuperclass();

这行代码我们是写在父类(BaseServiceImpl)的默认构造函数中的。继承这个类的子类们,在执行默认构造函数的时候,会先执行super();调用父类的默认构造函数,这时候,以上这行代码中的this就代表了子类,调用getGenericSuperclass()来获得父类(BaseServiceImpl),而得到的父类(BaseServiceImpl)可能是BaseServiceImpl<DaoAImpl>,BaseServiceImpl<DaoBImpl>... ,也可能BaseServiceImpl<T>。

我们可以使用接口ParameterizedType,用来检验类型参数是否被参数化

Type genericSuperclass = this.getClass().getGenericSuperclass();
if(genericSuperclass instanceof ParameterizedType) {// 该泛型类的类型参数已经被参数化
}

如果类型参数已经被参数化,我们就可以通过调用下面的方法

package java.lang.reflect;public interface ParameterizedType extends Type {Type[] getActualTypeArguments();
}

返回的数组中就存储了类型参数T的具体类型,即T.class

获取到T.class之后,我们就可以通过反射来进一步获得T的实例

try {return (T) cusClass.getConstructor(new Class[]{HttpServletRequest.class, Map.class, User.class}).newInstance(request, params, user);
} catch (Exception e) {e.printStackTrace();
}

转载于:https://my.oschina.net/u/3229807/blog/1821207

Java:反射+泛型:获取类型参数的实例相关推荐

  1. java反射无法获取_Java反射'无法设置'错误

    我正在尝试使用Java反射来获取通用Field属性的实例,以便执行此Field的方法. 例如,如果我使用getValue()方法创建类型为MyType的类,并且我有另一个具有MyType类属性的MyC ...

  2. Java反射机制——获取成员变量构造函数

    2019独角兽企业重金招聘Python工程师标准>>> Java反射机制--获取成员变量&构造函数 一.成员变量是java.lang.reflect.Field的对象 1.F ...

  3. ParameterizedType应用,java反射,获取参数化类型的class实例

    ParameterizedType是一个接口,这个类可以用来检验泛型是否被参数化 比如: class Dao<T> {public Dao(){} } 上面的这个类,也就是泛型类,当有子类 ...

  4. Java反射Method和Field简单实例

    目录 定义 使用方法 1.Field 2.Method 3.简单实例 定义 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方 ...

  5. java反射之获取class对象,Java之反射机制(获取Class对象的三种方式)

    Java之反射机制(获取Class对象的三种方式) 开发工具与关键技术:MyEclipse 10,java 作者:刘东标 撰写时间:2019-06-14 如何得到各个字节码对应的实例对象? 每个类被加 ...

  6. java反射怎么获取结构体_java反射-使用反射获取类的所有信息

    在OOP(面向对象)语言中,最重要的一个概念就是:万事万物皆对象. 在java中,类也是一个对象,是java.lang.Class的实例对象,官网称该对象为类的类类型. Class 类的实例表示正在运 ...

  7. java 反射 泛型 构造函数_Java复习——反射和泛型的复习

    反射 Class类 一个类被类加载器加载到内存之中,占有一片区域,这个空间里的内容就是类的字节码,不同的类的字节码是不一样的,这一个个空间页可以使用类来表示,这就是Class类. 根据这个概念可知:不 ...

  8. Java反射03 : 获取Class的注解、修饰符、父类、接口、字段、构造器和方法

    [超级通道 : Java反射学习系列-绪论] java.lang.Class类提供了获取类的各种信息对象的静态方法. 1.通过Class类可以做什么 获取类的包(Package)信息 获取类的注解(A ...

  9. Java反射机制和动态代理实例

    反射机制是Java语言的一个重要特性,允许用户动态获取类的信息和动态调用对象的方法. 通过给定类的名字,通过反射机制就可以获取类的所有信息. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道 ...

  10. java 反射获取对象_使用Java反射机制获取对象

    本文由广州疯狂软件教育java培训分享: 构造接口Person,所有Person都会问好,但具体讲什么语言就不知道了! package interf; public interface Person ...

最新文章

  1. mysql 排序取前4_MySQL时间段分组排序后取前10的问题?
  2. java string()函数_从Java中的String函数返回String构建器?
  3. 单一nginx负载均衡+LNMP分布式架构
  4. [一个经典的多线程同步问题]解决方案一:关键段CS
  5. java comparator_【面试题】Java必考面试题全集(15)
  6. mybatis进行CRUD操作时返回值不为影响的条数,为null
  7. DBA必知的mysql备份与还原的几大方法
  8. pip安装requirement.txt
  9. (转)Hibernate框架基础——多对多关联关系映射
  10. Money Pro for Mac如何导入账单?
  11. 字符串匹配---KMP
  12. winqsb替代软件linux,winqsb软件64位-运筹学软件winqsb下载 v3.0免费版 附使用教程-下载啦...
  13. 计算机硬件基础 试题,计算机硬件基础试题(库)
  14. H265解码流程理解
  15. Vim简介以及常用命令
  16. 数学建模学习(41):单因素方差分析
  17. MMORPG游戏优化报告
  18. Linux常用文件目录指令(实操)
  19. 分而治之 (25 分)
  20. 学习英语02——词汇——01

热门文章

  1. 数字图像处理同态滤波(matlab)
  2. Vue提供操作DOM的方法
  3. 阅读笔记一之《软件需求与分析》
  4. 关于爬虫的一些工具。
  5. 在github中使用pages上传自己的网页
  6. mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
  7. Android版CCLabelTTF在setstring时出现黑块
  8. 一个网站自动化测试程序的设计与实现
  9. C++第10周项目2扩展之2参考——迭代求和
  10. document.body.scrollTop以及一些备忘