一、引子:
項目中使用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<Collection<Foo>>(){}.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
具體實現如下:
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 }
邊 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 }
從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 最外層<>前面那個類型 rawType:class java.util.HashMap 2 泛型 type:class java.lang.String 3 泛型 type1:class java.lang.Integer 4 ownerType:null 5 泛型 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
----------------------------------------------多做多解決多總結-----------------------------------