一、引子:

项目中使用Gson的反序列化将json转化成具体的对象,具体方法是:

package com.google.gson;下的反序列化方法

  1. public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException{
  2. ......
  3. }

参数<T> :the type of the desired object

参数json:要被反序列化的json数据;

参数typeOfT:指定的通用类型的src。可以通过 Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();获得;

边对象:使用了泛型类

  1. public class CtiEdgeT<T,V> {
  2. private String id;
  3. //顶点
  4. private T inVertex;
  5. //对应点
  6. private V outVertex;
  7. ......
  8. }

最开始考虑使用具体的model作为参数,例如CtiEdgeT<DomainVertex,IpVertex> 具体类型(DomainVertex,IpVertex)做为参数,通过gson反序列化获得具体类型的CtiEdgeT<SampleVertex,IpVertex>对象,例如:

  1. private boolean saveEdgeToGraph(String msg, String inType, String outType) {
  2. boolean flag = false;
  3. switch (inType){
  4. case Constant.SAMPLE_LABEL:{
  5. switch (outType){
  6. case Constant.IP_LABEL:{
  7. Type type = new TypeToken<CtiEdgeT<SampleVertex,IpVertex>>() {
  8. }.getType();
  9. CtiEdgeT<SampleVertex,IpVertex> edge = JsonUtil.getJson().fromJson(msg, type);
  10. flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
  11. break;
  12. }
  13. case Constant.DOMAIN_LABEL:{
  14. Type type = new TypeToken<CtiEdgeT<SampleVertex,DomainVertex>>() {
  15. }.getType();
  16. CtiEdgeT<SampleVertex,DomainVertex> edge = JsonUtil.getJson().fromJson(msg, type);
  17. flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
  18. break;
  19. }
  20. 。。。。。。
  21. }
  22. }
  23. }
  24. }

本项目中就有20+种数据,即20+个model,这样做导致的结果就是如果有很多不同的边CtiEdgeT<T,V>,将会写大量的冗余代码。

二、解决方案:

可以通过 ParameterizedType 这个接口实现泛型类,参数化类型,参考这篇文章: https://www.jianshu.com/p/b1ad2f1d3e3e

具体实现如下:

  1. EdgeParameterTypeImpl
  1. import java.lang.reflect.ParameterizedType;
  2. import java.lang.reflect.Type;
  3.  
  4. public class EdgeParameterTypeImpl implements ParameterizedType {
  5.  
  6. //边
  7. private Class ctiEdgeT ;
  8. //顶点
  9. private Class inVertex ;
  10. //对应点
  11. private Class outVertex ;
  12.  
  13. public EdgeParameterTypeImpl(Class ctiEdgeT,Class inVertex,Class outVertex) {
  14. this.ctiEdgeT = ctiEdgeT ;
  15. this.inVertex = inVertex ;
  16. this.outVertex = outVertex ;
  17. }
  18.  
  19. @Override
  20. public Type[] getActualTypeArguments() {
  21. return new Type[]{inVertex,outVertex};
  22. }
  23.  
  24. @Override
  25. public Type getRawType() {
  26. return ctiEdgeT;
  27. }
  28.  
  29. @Override
  30. public Type getOwnerType() {
  31. return null;
  32. }
  33.  
  34. }
  1. CtiEdgeT<T,V>:
  1. public class CtiEdgeT<T,V> {
  2. private String id;
  3. //顶点
  4. private T inVertex;
  5. //对应点
  6. private V outVertex;
  7.  
  8. public String getId() {
  9. return id;
  10. }
  11.  
  12. public void setId(String id) {
  13. this.id = id;
  14. }
  15.  
  16. public T getInVertex() {
  17. return inVertex;
  18. }
  19.  
  20. public void setInVertex(T inVertex) {
  21. this.inVertex = inVertex;
  22. }
  23.  
  24. public V getOutVertex() {
  25. return outVertex;
  26. }
  27.  
  28. public void setOutVertex(V outVertex) {
  29. this.outVertex = outVertex;
  30. }
  31. }

通过参数化泛型解决,传入的具体model类作为参数,反序列化得到具体的边

  1. private boolean saveEdgeToGraph(String msg, String inType, String outType) {
  2. boolean flag = false;
  3. Class<?> inVertex = Constant.vertexClassMap.get(inType); //inType : SAMPLE_LABEL
  4. Class<?> outVertex = Constant.vertexClassMap.get(outType); //outType : IP_LABEL
  5. EdgeParameterTypeImpl type = new EdgeParameterTypeImpl(CtiEdgeT.class, inVertex, outVertex);
  6. @SuppressWarnings("rawtypes")
  7. CtiEdgeT edge = JsonUtil.getJson().fromJson(msg,type);
  8. flag = this.doSaveEdgeToGraph(inType,outType,edge.getInVertex(),edge.getOutVertex(),edge);
  9. return flag;
  10. }
  1. vertexClassMap中取对应的具体model
  1. public class Constant {
  2. @SuppressWarnings("rawtypes")
  3. public static Map<String,Class> vertexClassMap = new HashMap<String,Class>();
  4.  
  5. static{
  6. try {
  7. vertexClassMap.put(SAMPLE_LABEL,SampleVertex.class);
  8. vertexClassMap.put(IP_LABEL,IpVertex.class);
  9. vertexClassMap.put(DOMAIN_LABEL,DomainVertex.class);
  10. 。。。。。。
  11. }
  12. }
  13. }

通过追踪代码:CtiEdgeT edge = JsonUtil.getJson().fromJson(msg,type);可以发现type的源码

  1. TypeToken(Type type) {
  2. this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
  3. this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
  4. this.hashCode = this.type.hashCode();
  5. }
  1. public static Type canonicalize(Type type) {
  2. if (type instanceof Class) {
  3. Class<?> c = (Class<?>) type;
  4. return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
  5.  
  6. } else if (type instanceof ParameterizedType) {
  7. ParameterizedType p = (ParameterizedType) type;
  8. return new ParameterizedTypeImpl(p.getOwnerType(),
  9. p.getRawType(), p.getActualTypeArguments());
  10.  
  11. }
  12. ......
  13. }

上面标红的代码会执行具体model的实现类的方法,得到具体的类型。

三、拓展点:

关于ParameterizedType 的解析可以 参考这篇文章: https://blog.csdn.net/a327369238/article/details/52622331

  1. public class ParameterTest {
  2. public static void main(String[] args) {
  3. Method method = null;
  4. try {
  5. //这里的第二个参数,和getRawType()意义类似
  6. method = new ParameterTest().getClass().getMethod("test", HashMap.class);
  7. } catch (NoSuchMethodException e) {
  8. e.printStackTrace();
  9. }
  10. Type[] types = method.getGenericParameterTypes();
  11. ParameterizedType ptype = (ParameterizedType) types[0];
  12. Type rawType = ptype.getRawType();
  13. System.out.println("最外层<>前面那个类型 rawType:"+rawType);
  14. Type type = ptype.getActualTypeArguments()[0];
  15. Type type1 = ptype.getActualTypeArguments()[1];
  16. System.out.println("泛型 type:"+type);
  17. System.out.println("泛型 type1:"+type1);
  18. Type ownerType = ptype.getOwnerType();
  19. System.out.println("ownerType:"+ownerType);
  20. //type是Type类型,但直接输出的不是具体Type的五种子类型,
  21. //而是这五种子类型以及WildcardType具体表现形式
  22. System.out.println("泛型 type name:"+type.getClass().getName());
  23. }
  24. public void test(HashMap<String,Integer> a){
  25. }
  26. }

结果:

  1. 最外层<>前面那个类型 rawTypeclass java.util.HashMap
  2. 泛型 typeclass java.lang.String
  3. 泛型 type1class java.lang.Integer
  4. ownerTypenull
  5. 泛型 type namejava.lang.Class

因此 EdgeParameterTypeImpl 中的

public Type getRawType() {   return ctiEdgeT;} 得到 边ctiEdgeT,而边 CtiEdgeT<T,V> 是参数是泛型,

public Type[] getActualTypeArguments() { return new Type[]{inVertex,outVertex};} 得到 参数 inVertex,outVertex

----------------------------------------------多做多解决多总结-----------------------------------

Java反射--基于ParameterizedType实现泛型类,参数化类型的更多相关文章

  1. Java 反射 ParameterizedType 参数化类型

    /***************************************************************************************** * Java 反射 ...

  2. 基于NACOS和JAVA反射机制动态更新JAVA静态常量非@Value注解

    1.前言 项目中都会使用常量类文件, 这些值如果需要变动需要重新提交代码,或者基于@Value注解实现动态刷新, 如果常量太多也是很麻烦; 那么 能不能有更加简便的实现方式呢? 本文讲述的方式是, 一 ...

  3. 基于Java反射的map自动装配JavaBean工具类设计

    我们平时在用Myabtis时不是常常需要用map来传递参数,大体是如下的步骤: public List<Role> findRoles(Map<String,Object> p ...

  4. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  5. Java反射机制(转载)

    原文链接:http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Jav ...

  6. 详解Java反射各种应用

    Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息.通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容: Class对象 构造器 变量 方法 ...

  7. (转载)Java反射机制

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  8. java反射基础知识(五)反射应用实践

    详解Java反射各种应用   Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息.通过反射获取类的信息,得到类的信息之后,就可以获取以下相关内容: Cl ...

  9. 深入分析Java反射(三)-泛型

    前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...

随机推荐

  1. Linux内核分析第四周总结

    用户态,内核态和中断处理过程 库函数将系统调用封装起来 用户态和内核态的差别: 在内核态时,cs和eip的值可以是任意地址,但在用户态时只能访问0x00000000 - 0xbfffffff,0x00 ...

  2. 第一次spring,第三天。

    陈志棚:界面跳转与框架 李天麟:游戏界面ui 徐侃:算法代码的设计 由于队员要回家,我们讨论后,在校的队员先完成自己的任务,待回来的队员完成后在开会讨论,我们的最终结果.

  3. nodejs的事件驱动理解

    // 引入 events 模块 var events = require('events'); // 创建 eventEmitter 对象 var eventEmitter = new events. ...

  4. Ubuntu忘记MySQL密码重设方法

    ====================忘了mysql密码,从网上找到的解决方案记录在这里==================== 结束当前正在运行的mysql进程 # /etc/init.d/mys ...

  5. USACO 2012 December ZQUOJ 24128 Wifi Setup(动态dp)

    题意:给出在同一条直线上的n个点和两个数A,B,现在要在这条直线上放置若干个信号塔,每个信号塔有一个r值,假设它的位置是x,则它能覆盖的范围是x-r~x+r,放置一个信号塔的花费是A+B*r,问要覆盖 ...

  6. Cheerleaders UVA - 11806(容斥+二进制技巧)

    #include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...

  7. 【转】vi 写完文件保存时才发现是 readonly

    在MAC上编辑apache配置文件,老是忘记sudo…… readonly的文件保存时提示 add ! to override, 但这仅是对root来说的啊! 百毒了一下竟然还有解决方案!! :w ! ...

  8. [学习笔记]Cayley-Hilmiton

    Cayley–Hamilton theorem - Wikipedia 其实不是理解很透彻,,,先写上 简而言之: 是一个知道递推式,快速求第n项的方法 k比较小的时候可以用矩阵乘法 k是2000,n ...

  9. Centos7搭建SS以及加速配置的操作记录

    部署 Shadowsocks之前,对它做了一个简单的了解,下面先介绍下.一道隐形的墙众所周知,天朝局域网通过 GFW (中国防火墙长城:英文名称Great Firewall of China,简写为G ...

  10. linux开启swap(磁盘缓存)操作

    转载 2014年04月26日 14:41:15 4470 由于工作需要,要帮助同事查看linux服务器的缓存开启情况,经过查找资料,可确定通过以下方法确定Linux磁盘缓存是否已开启. 1.命令行下执 ...