Java:反射+泛型:获取类型参数的实例

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

场景描述:

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

最简单的写法:

创建四个接口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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/277909.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

servlet(1)

servlet类分级&#xff1a; 1.ServletConfig接口类&#xff1a;理解为读取servlet配置的类&#xff0c;里面有四个抽象方法如下&#xff1a; ①getServletName:获取servlet在web.xml中的名字 ②getServletContext&#xff1a;获取Servlet上下文&#xff0c;相当于web项目管理所…

如何在 Apple Silicon (M1) 上开发 Teams App

apple 在几个月前发布了自家的芯片 M1&#xff0c;由于将多核cpu&#xff0c;多核gpu&#xff0c;神经网络运算&#xff0c;内存和其他一切处理部件高度整合在一起&#xff0c;大大提高数据传输速度。发布后好评如潮&#xff0c;我也没有忍住&#xff0c;入手了一台最低配的mac…

BZOJ5289 洛谷4437:[HNOI/AHOI2018]排列——题解

https://www.lydsy.com/JudgeOnline/problem.php?id5289 https://www.luogu.org/problemnew/show/P4437 考虑对于a[i]m,a[m]n&#xff0c;我们令p[j]i,p[k]m&#xff08;一定会有一对(j,k)满足这个条件的&#xff09;&#xff0c;则我们会有p[k]a[p[j]]&#xff0c;此时我们要…

集成学习-Adaboost

Adaboost 中文名叫自适应提升算法&#xff0c;是一种boosting算法。 boosting算法的基本思想 对于一个复杂任务来说&#xff0c;单个专家的决策过于片面&#xff0c;需要集合多个专家的决策得到最终的决策&#xff0c;通俗讲就是三个臭皮匠顶个诸葛亮。 对于给定的数据集&#…

主动给团队或用户安装Teams App

在写这篇文章的时候&#xff0c;这个新功能还处在 Public Review&#xff0c;这意味着可能&#xff08;很小的可能性&#xff09;这里写的方法在正式发布前还会有一些改动。 之前有一些做teams app开发的朋友问过我&#xff0c;能不能主动给一个team或者一个用户安装一个指定的…

thinkphp5多级控制器是什么?怎么使用?

thinkphp5多级控制器是什么&#xff1f;怎么使用&#xff1f; 一、总结 1、多级控制器是让控制器的级数变成多级&#xff0c;也就是controller目录下可以新建其它目录。 2、使用的话注意目录下的控制的的命名空间&#xff08;加上目录名&#xff09;&#xff08;namespace app\…

给Teams消息附加图片的三种方式

Teams消息支持三种不同的方式来添加图片&#xff0c;这篇文章我们来一起看一下这三种方式。 Inline图片 var imagePath Path.Combine(Environment.CurrentDirectory, "abc.png"); var imageData Convert.ToBase64String(File.ReadAllBytes(imagePath)); var image…

4月18日 MySQL学习

正式开始了数据库的学习 昨天下好的MySQL 今天正式开始学习的&#xff0c;介绍了多种数据库软件&#xff0c;当然 学习的这个是开源的 免费的。 DBMS(数据库管理系统)这就是我们学习的数据库的软件 数据库分为关系型数据库管理系统和非关系型数据库管理系统(没有深入的了解) 今…

企业数据湖构建之旅

摘要&#xff1a;随着互联网的发展&#xff0c;数据的规模和类型都呈现一个爆炸性的增长&#xff0c;对于这么多类型的数据&#xff0c;如何进行有效的管理和存储&#xff0c;包括数据的分析&#xff0c;这是大家要面临的一个问题。在武汉云栖大会上&#xff0c;阿里云高级产品…

用AzureFunction开发最简单的Teams Bot

之前我有一篇文章讲了如何在azure function上开发最简单的outgoing webhook&#xff0c;收到一些反馈&#xff0c;建议我介绍一下如果在azure function上开发teams bot&#xff0c;那这篇文章就来讲一下如何用function来快速开发bot。 我们先创建一个azure function资源&#…

20189215 2018-2019-2 《密码与安全新技术专题》第7周作业

课程&#xff1a;《密码与安全新技术专题》 班级&#xff1a; 1892班 姓名&#xff1a; 李炀 学号&#xff1a;20189215 上课教师&#xff1a;谢四江 上课日期&#xff1a;2019年4月9日 必修/选修&#xff1a; 选修 1.本次讲座的学习总结 讲座主题&#xff1a;信息隐藏 信息隐藏…

BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序

题目描述 Plants vs. Zombies&#xff08;PVZ&#xff09;是最近十分风靡的一款小游戏。Plants&#xff08;植物&#xff09;和Zombies&#xff08;僵尸&#xff09;是游戏的主角&#xff0c;其中Plants防守&#xff0c;而Zombies进攻。该款游戏包含多种不同的挑战系列&#xf…

推送ActivityFeed到Teams

几个月前&#xff0c;Teams 团队又推出了新的 Graph API&#xff0c;让 app 可以给用户发送 Activity Feed。我们来看看如何做。 首先&#xff0c;我们的app需要使用较新的 manifest 1.7版本&#xff0c;当然如果使用最新的1.8版本就更好了。在manifest json中添加 webApplica…

RecycleView弹性滑动

还有点bug&#xff0c;建议使用 LinearSnapHelper rvPilotList.addOnScrollListener(new RecyclerView.OnScrollListener() {Overridepublic void onScrolled(NonNull RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);// …

关于深度学习,这些知识点你需要了解一下

深度学习概述 o 受限玻尔兹曼机和深度信念网络 o Dropout o 处理不平衡的技巧 o SMOTE&#xff1a;合成少数过采样技术 o 神经网络中对成本敏感的学习 深度学习概述 在2006年之前&#xff0c;训练深度监督前馈神经网络总是失败的&#xff0c;其主要原因都是导致…

发送不同类型的ActivityFeed

上一篇文章讲到了如何使用最新的Graph API来给一个用户发送一个简单的 Activity Feed。我们这篇文章来详细讲一下发送三种不同类型的消息。 发送 Chat 相关的 Activity Notification API 为 POST https://graph.microsoft.com/beta/chats/{chat-id}/sendActivityNotification…

git add * 提示warning: LF will be replaced by CRLF in 解决办法

在使用git的时候&#xff0c;每次执行 $ git add * 都会提示这样一个警告消息&#xff1a; 虽然说没有什么影响吧。 不过就是觉得太碍眼了&#xff0c; 按照这样设置就没有问题了: git config core.autocrlf false 这样设置git的配置后在执行add操作就没有问题了。 奋斗的年纪你…

git 放弃本地修改,强制拉取更新

开发时&#xff0c;对于本地的项目中修改不做保存操作&#xff08;或代码改崩&#xff09;&#xff0c;可以用到Git pull的强制覆盖&#xff0c;具体代码如下&#xff1a; git fetch --all git reset --hard origin/master git pull //可以省略 git fetch 指令是下载远程仓库最…

发送ActivityFeed的隐藏功能

前两篇文章介绍了如何发送 activity notification&#xff0c;这篇文章主要介绍两个隐藏功能&#xff0c;实际上所谓的隐藏功能是指大家在阅读官方文档是会忽略的两个点&#xff0c;但是实际上也是很实用的两个功能点。 text 类型的 topic 之前文章中提到我们的 activity not…

Dispatch Queue 之 Invoke 当前队列

&#xfffc; 转载于:https://www.cnblogs.com/huahuahu/p/dispatch-queue-zhi-invoke-dang-qian-dui-lie.html