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查看对应的源码和进行 ...
随机推荐
- Inside the Social Network’s (Datacenter) Network
摘要: 大量服务提供商投资越来越多的更大数据中心来保证基础计算需求以支持他们的服务.因此,研究人员和行业从业者都集中了大量的努力设计网络结构有效互连和管理流量以保证这些数据中心的性能.不幸的是,数据中 ...
- VS2013 单元测试
1.打开VS2013 --> 新建一个项目.这里创建一个c#控制台项目.取名为ccj_test1 2.进入控制台项目ccj_test1的Program类,创建一个add静态方法,并将progra ...
- 从零开始学Kotlin-类和对象(5)
定义一个类 定义一个类,使用关键字class声明,后面跟类名(不使用new) class demo5 {//定义一个类,使用关键字class声明,后面跟类名 fun test() {//类中定义方法 ...
- qemu-img.exe 工具 简介
1. 下载地址 https://cloudbase.it/qemu-img-windows/ 2. 解压缩 然后扔到 system32目录下 或者是 修改环境变量-- 我很懒,我决定扔到system3 ...
- delphi xe 的替代者 Lazarus
Lazarus的设计目标是应用Free Pascal,所以所有凡是Free Pascal能运行的平台,Lazarus都可以运行.最新版本能运行于Linux,Win32和Mac OS.整个界面的外观和操 ...
- Struts2 分割字符串标签s:generator
有些时候会从后台返回一个字符串,可以通过Strut2的标签s:generator进行分割. generator标签,该标签可以将指定字符串按指定分隔符分割成多个字串.生成的多个字串可以用iterato ...
- BZOJ4078 WF2014Metal Processing Plant(二分答案+2-SAT)
题面甚至没给范围,由数据可得n<=200.容易想到二分答案,暴力枚举某集合的价值,2-SATcheck一下即可.这样是O(n4logn)的. 2-SAT复杂度已经是下界,考虑如何优化枚举.稍微改 ...
- POJ 1182 食物链 (带权并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 78551 Accepted: 23406 Description ...
- 用call/cc合成所有的控制流结构
用call/cc合成所有的控制流结构 来源 https://www.jianshu.com/p/e860f95cad51 call/cc 是非常.非常特殊的,因为它根本无法用 Lambda 演算定义. ...
- 【BZOJ1297】[SCOI2009]迷路(矩阵快速幂)
[BZOJ1297][SCOI2009]迷路(矩阵快速幂) 题面 BZOJ 洛谷 题解 因为边权最大为\(9\),所以记录往前记录\(9\)个单位时间前的.到达每个点的方案数就好了,那么矩阵大小就是\ ...