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查看对应的源码和进行 ...
随机推荐
- 20135202闫佳歆--week3 构造一个简单的Linux系统MenuOs--学习笔记
此为个人学习笔记存档 week 3 构造一个简单的Linux系统MenuOs 复习: 计算机有三个法宝:存储程序计算机,函数调用堆栈,中断 操作系统有两把剑: 1.中断上下文的切换,保存现场和恢复现场 ...
- PowerDesigner16工具学习笔记-建立CDM
1.基本术语 1.1.实体和属性 实体(entity):指现实世界中客观存在,并可相互区别的事物或者事件. 属性(attribute):一组用来描述实体特征的属性. 实体集(entity set):具 ...
- 第一个spring,第一天。
陈志棚:界面跳转与框架 李天麟:游戏界面ui 徐侃:算法代码的设计 经过热烈的讨论后,我们各自在完成自己的任务.
- VS2013新建web项目时出错,系统找不到指定文件
好不容易找了一个VS2013_RTM_ULT_CHS来安装好,Key:BWG7X-J98B3-W34RT-33B3R-JVYW9 兴高采烈的打开vs2013,新建web项目,结果弹出一个错误: 傻眼了 ...
- Android TextView中图文混排设置行间距导致高度不一致问题解决
最近项目中需要实现一个评论带表情的功能,刚开始一切顺利,非常easy,突然有一天发现文字跟表情混排的时候,TextView中图文高度不一致,excuse...什么鬼,之前明明测试过图文混排,不存在这个 ...
- MarkDown to PDF
前面随便说说 之前在 windows 上一直习惯用 cmdmarkdown 把要写的东西写下来,再通过 typora 转成 pdf:现在很多时候在用 Ubuntu,需要把写完的作业转成 pdf 交上去 ...
- BZOJ3434 WC2014时空穿梭(莫比乌斯反演)
考虑枚举相邻点距离差的比例.显然应使比例值gcd为1以保证不重复统计.确定比例之后,各维坐标的方案数就可以分开考虑.设比例之和为k,则若坐标上限为m,该维坐标取值方案数即为Σm-ki (i=1~⌊m/ ...
- windows10中远程登录ubuntu16.04的桌面
1. 安装xrdp sudo apt-get install xrdp 2. 安装vnc4server sudo apt-get install vnc4server tightvncserver ...
- MySQL 主从复制详解
读写分离的意思是,写入的时候向 a 服务器写入,而读出的时候从 b c d 甚至更多的服务器读出:这样的架构适合于读多写少的应用,最典型的就是火车购票系统,一般我们买票的时候要先查询好多次,包括车次啊 ...
- 修改MyEclipse取消默认工作空间
使用MyEclipse,在最开始Workspace Launcher中选择工作空间时,勾选了默认选择,以后启动程序的时候,就不会弹出这个选择工作空间的对话框了.如下图: 但后来又新增一个工作空间,需要 ...