日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

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

發(fā)布時間:2023/12/9 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java:反射+泛型:获取类型参数的实例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

場景描述:

我需要開發(fā)四個頁面,每個頁面都是只涉及增刪改查的基本邏輯。

最簡單的寫法:

創(chuàng)建四個接口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);

為上面四個接口分別創(chuàng)建四個實(shí)現(xiàn)類,復(fù)寫接口中的增刪改查方法

接口A的實(shí)現(xiàn)類

@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的實(shí)現(xiàn)類

@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 的實(shí)現(xiàn)類就不在展示了。其中主要區(qū)別就是:

ServiceAImpl調(diào)用DaoAImpl的對象

ServiceBImpl調(diào)用DaoBImpl的對象

ServiceCImpl調(diào)用DaoCImpl的對象

ServiceDImpl調(diào)用DaoDImpl的對象

看完上面的代碼,你可以發(fā)現(xiàn),重復(fù)的代碼太多了,需要整理下

解決方案:

接口:可以將增刪改查的方法聲明放到一個基礎(chǔ)接口中,然后繼承這個基礎(chǔ)接口就行。

基礎(chǔ)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); }

繼承基礎(chǔ)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 {}

接口的實(shí)現(xiàn):同樣是增刪改查四個復(fù)寫的方法,唯一不同的就是不同的實(shí)現(xiàn)類調(diào)用不同的持久層(DAO)對象。期初的想法與處理接口的想法一樣,把復(fù)寫的增刪改查方法寫到一個基礎(chǔ)service實(shí)現(xiàn)類中,然后繼承這個基礎(chǔ)service實(shí)現(xiàn)類即可。

為了能實(shí)現(xiàn)這個功能,我們需要用到Java中的泛型和反射知識

新建一個基礎(chǔ)service實(shí)現(xiàn)類

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) {}}

可以看到這個基礎(chǔ)service實(shí)現(xiàn)類接受了一個類型參數(shù)T

那些繼承了這個基礎(chǔ)實(shí)現(xiàn)類的類,就可以通過這個類型參數(shù),把需要調(diào)用的Dao層對象的類型傳遞到父類當(dāng)中
?

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 {}

?

接下來,我們需要思考的是,如何通過這個類型參數(shù)T,來得到T的一個實(shí)例。

我們先上菜

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類的實(shí)例* @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) {}}

?

????????我們可以看到,我們在這個基礎(chǔ)service實(shí)現(xiàn)類的默認(rèn)構(gòu)造函數(shù)中確認(rèn)了類型參數(shù)T的類型,得到T.class。之后在getTInstance() 方法中通過反射的方式獲取了T的實(shí)例。

?

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

????????這行代碼我們是寫在父類(BaseServiceImpl)的默認(rèn)構(gòu)造函數(shù)中的。繼承這個類的子類們,在執(zhí)行默認(rèn)構(gòu)造函數(shù)的時候,會先執(zhí)行super();調(diào)用父類的默認(rèn)構(gòu)造函數(shù),這時候,以上這行代碼中的this就代表了子類,調(diào)用getGenericSuperclass()來獲得父類(BaseServiceImpl),而得到的父類(BaseServiceImpl)可能是BaseServiceImpl<DaoAImpl>,BaseServiceImpl<DaoBImpl>... ,也可能BaseServiceImpl<T>。

我們可以使用接口ParameterizedType,用來檢驗(yàn)類型參數(shù)是否被參數(shù)化

Type genericSuperclass = this.getClass().getGenericSuperclass(); if(genericSuperclass instanceof ParameterizedType) {// 該泛型類的類型參數(shù)已經(jīng)被參數(shù)化 }

如果類型參數(shù)已經(jīng)被參數(shù)化,我們就可以通過調(diào)用下面的方法

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

返回的數(shù)組中就存儲了類型參數(shù)T的具體類型,即T.class

?

獲取到T.class之后,我們就可以通過反射來進(jìn)一步獲得T的實(shí)例

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

?

?

?

?

轉(zhuǎn)載于:https://my.oschina.net/u/3229807/blog/1821207

總結(jié)

以上是生活随笔為你收集整理的Java:反射+泛型:获取类型参数的实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。