Java反射--基于ParameterizedType实现泛型类,参数化类型
一、引子:
项目中使用Gson的反序列化将json转化成具体的对象,具体方法是:
package com.google.gson;下的反序列化方法
- public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException{
- ......
- }
参数<T> :the type of the desired object
参数json:要被反序列化的json数据;
参数typeOfT:指定的通用类型的src。可以通过 Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();获得;
边对象:使用了泛型类
- public class CtiEdgeT<T,V> {
- private String id;
- //顶点
- private T inVertex;
- //对应点
- private V outVertex;
- ......
- }
最开始考虑使用具体的model作为参数,例如CtiEdgeT<DomainVertex,IpVertex> 具体类型(DomainVertex,IpVertex)做为参数,通过gson反序列化获得具体类型的CtiEdgeT<SampleVertex,IpVertex>对象,例如:
- private boolean saveEdgeToGraph(String msg, String inType, String outType) {
- boolean flag = false;
- switch (inType){
- case Constant.SAMPLE_LABEL:{
- switch (outType){
- case Constant.IP_LABEL:{
- Type type = new TypeToken<CtiEdgeT<SampleVertex,IpVertex>>() {
- }.getType();
- CtiEdgeT<SampleVertex,IpVertex> edge = JsonUtil.getJson().fromJson(msg, type);
- flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
- break;
- }
- case Constant.DOMAIN_LABEL:{
- Type type = new TypeToken<CtiEdgeT<SampleVertex,DomainVertex>>() {
- }.getType();
- CtiEdgeT<SampleVertex,DomainVertex> edge = JsonUtil.getJson().fromJson(msg, type);
- flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
- break;
- }
- 。。。。。。
- }
- }
- }
- }
本项目中就有20+种数据,即20+个model,这样做导致的结果就是如果有很多不同的边CtiEdgeT<T,V>,将会写大量的冗余代码。
二、解决方案:
可以通过 ParameterizedType 这个接口实现泛型类,参数化类型,参考这篇文章: https://www.jianshu.com/p/b1ad2f1d3e3e
具体实现如下:
- EdgeParameterTypeImpl:
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- public class EdgeParameterTypeImpl implements ParameterizedType {
- //边
- private Class ctiEdgeT ;
- //顶点
- private Class inVertex ;
- //对应点
- private Class outVertex ;
- public EdgeParameterTypeImpl(Class ctiEdgeT,Class inVertex,Class outVertex) {
- this.ctiEdgeT = ctiEdgeT ;
- this.inVertex = inVertex ;
- this.outVertex = outVertex ;
- }
- @Override
- public Type[] getActualTypeArguments() {
- return new Type[]{inVertex,outVertex};
- }
- @Override
- public Type getRawType() {
- return ctiEdgeT;
- }
- @Override
- public Type getOwnerType() {
- return null;
- }
- }
- 边 CtiEdgeT<T,V>:
- public class CtiEdgeT<T,V> {
- private String id;
- //顶点
- private T inVertex;
- //对应点
- private V outVertex;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public T getInVertex() {
- return inVertex;
- }
- public void setInVertex(T inVertex) {
- this.inVertex = inVertex;
- }
- public V getOutVertex() {
- return outVertex;
- }
- public void setOutVertex(V outVertex) {
- this.outVertex = outVertex;
- }
- }
通过参数化泛型解决,传入的具体model类作为参数,反序列化得到具体的边
- private boolean saveEdgeToGraph(String msg, String inType, String outType) {
- boolean flag = false;
- Class<?> inVertex = Constant.vertexClassMap.get(inType); //inType : SAMPLE_LABEL
- Class<?> outVertex = Constant.vertexClassMap.get(outType); //outType : IP_LABEL
- EdgeParameterTypeImpl type = new EdgeParameterTypeImpl(CtiEdgeT.class, inVertex, outVertex);
- @SuppressWarnings("rawtypes")
- CtiEdgeT edge = JsonUtil.getJson().fromJson(msg,type);
- flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
- return flag;
- }
- 从vertexClassMap中取对应的具体model
- public class Constant {
- @SuppressWarnings("rawtypes")
- public static Map<String,Class> vertexClassMap = new HashMap<String,Class>();
- static{
- try {
- vertexClassMap.put(SAMPLE_LABEL,SampleVertex.class);
- vertexClassMap.put(IP_LABEL,IpVertex.class);
- vertexClassMap.put(DOMAIN_LABEL,DomainVertex.class);
- 。。。。。。
- }
- }
- }
通过追踪代码:CtiEdgeT edge = JsonUtil.getJson().fromJson(msg,type);可以发现type的源码
- TypeToken(Type type) {
- this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
- this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
- this.hashCode = this.type.hashCode();
- }
- public static Type canonicalize(Type type) {
- if (type instanceof Class) {
- Class<?> c = (Class<?>) type;
- return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
- } else if (type instanceof ParameterizedType) {
- ParameterizedType p = (ParameterizedType) type;
- return new ParameterizedTypeImpl(p.getOwnerType(),
- p.getRawType(), p.getActualTypeArguments());
- }
- ......
- }
上面标红的代码会执行具体model的实现类的方法,得到具体的类型。
三、拓展点:
关于ParameterizedType 的解析可以 参考这篇文章: https://blog.csdn.net/a327369238/article/details/52622331
- public class ParameterTest {
- public static void main(String[] args) {
- Method method = null;
- try {
- //这里的第二个参数,和getRawType()意义类似
- method = new ParameterTest().getClass().getMethod("test", HashMap.class);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- }
- Type[] types = method.getGenericParameterTypes();
- ParameterizedType ptype = (ParameterizedType) types[0];
- Type rawType = ptype.getRawType();
- System.out.println("最外层<>前面那个类型 rawType:"+rawType);
- Type type = ptype.getActualTypeArguments()[0];
- Type type1 = ptype.getActualTypeArguments()[1];
- System.out.println("泛型 type:"+type);
- System.out.println("泛型 type1:"+type1);
- Type ownerType = ptype.getOwnerType();
- System.out.println("ownerType:"+ownerType);
- //type是Type类型,但直接输出的不是具体Type的五种子类型,
- //而是这五种子类型以及WildcardType具体表现形式
- System.out.println("泛型 type name:"+type.getClass().getName());
- }
- public void test(HashMap<String,Integer> a){
- }
- }
结果:
- 最外层<>前面那个类型 rawType:class java.util.HashMap
- 泛型 type:class java.lang.String
- 泛型 type1:class java.lang.Integer
- ownerType:null
- 泛型 type name:java.lang.Class
因此 EdgeParameterTypeImpl 中的
public Type getRawType() { return ctiEdgeT;} 得到 边ctiEdgeT,而边 CtiEdgeT<T,V> 是参数是泛型,
public Type[] getActualTypeArguments() { return new Type[]{inVertex,outVertex};} 得到 参数 inVertex,outVertex
----------------------------------------------多做多解决多总结-----------------------------------
Java反射--基于ParameterizedType实现泛型类,参数化类型的更多相关文章
- Java 反射 ParameterizedType 参数化类型
/***************************************************************************************** * Java 反射 ...
- 基于NACOS和JAVA反射机制动态更新JAVA静态常量非@Value注解
1.前言 项目中都会使用常量类文件, 这些值如果需要变动需要重新提交代码,或者基于@Value注解实现动态刷新, 如果常量太多也是很麻烦; 那么 能不能有更加简便的实现方式呢? 本文讲述的方式是, 一 ...
- 基于Java反射的map自动装配JavaBean工具类设计
我们平时在用Myabtis时不是常常需要用map来传递参数,大体是如下的步骤: public List<Role> findRoles(Map<String,Object> p ...
- Java反射机制的学习
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- Java反射机制(转载)
原文链接:http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Jav ...
- 详解Java反射各种应用
Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息.通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容: Class对象 构造器 变量 方法 ...
- (转载)Java反射机制
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- java反射基础知识(五)反射应用实践
详解Java反射各种应用 Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息.通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容: Cl ...
- 深入分析Java反射(三)-泛型
前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...
随机推荐
- Linux内核分析第四周总结
用户态,内核态和中断处理过程 库函数将系统调用封装起来 用户态和内核态的差别: 在内核态时,cs和eip的值可以是任意地址,但在用户态时只能访问0x00000000 - 0xbfffffff,0x00 ...
- 第一次spring,第三天。
陈志棚:界面跳转与框架 李天麟:游戏界面ui 徐侃:算法代码的设计 由于队员要回家,我们讨论后,在校的队员先完成自己的任务,待回来的队员完成后在开会讨论,我们的最终结果.
- nodejs的事件驱动理解
// 引入 events 模块 var events = require('events'); // 创建 eventEmitter 对象 var eventEmitter = new events. ...
- Ubuntu忘记MySQL密码重设方法
====================忘了mysql密码,从网上找到的解决方案记录在这里==================== 结束当前正在运行的mysql进程 # /etc/init.d/mys ...
- USACO 2012 December ZQUOJ 24128 Wifi Setup(动态dp)
题意:给出在同一条直线上的n个点和两个数A,B,现在要在这条直线上放置若干个信号塔,每个信号塔有一个r值,假设它的位置是x,则它能覆盖的范围是x-r~x+r,放置一个信号塔的花费是A+B*r,问要覆盖 ...
- Cheerleaders UVA - 11806(容斥+二进制技巧)
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- 【转】vi 写完文件保存时才发现是 readonly
在MAC上编辑apache配置文件,老是忘记sudo…… readonly的文件保存时提示 add ! to override, 但这仅是对root来说的啊! 百毒了一下竟然还有解决方案!! :w ! ...
- [学习笔记]Cayley-Hilmiton
Cayley–Hamilton theorem - Wikipedia 其实不是理解很透彻,,,先写上 简而言之: 是一个知道递推式,快速求第n项的方法 k比较小的时候可以用矩阵乘法 k是2000,n ...
- Centos7搭建SS以及加速配置的操作记录
部署 Shadowsocks之前,对它做了一个简单的了解,下面先介绍下.一道隐形的墙众所周知,天朝局域网通过 GFW (中国防火墙长城:英文名称Great Firewall of China,简写为G ...
- linux开启swap(磁盘缓存)操作
转载 2014年04月26日 14:41:15 4470 由于工作需要,要帮助同事查看linux服务器的缓存开启情况,经过查找资料,可确定通过以下方法确定Linux磁盘缓存是否已开启. 1.命令行下执 ...