JSON 序列化與反序列化(二)使用TypeReference 構建型別安全的異構容器
阿新 • • 發佈:2018-11-19
原文連結:https://www.cnblogs.com/yuyutianxia/p/6051682.html
1. 泛型通常用於集合,如Set和Map等。這樣的用法也就限制了每個容器只能有固定數目的型別引數,一般來說,這也確實是我們想要的。
然而有的時候我們需要更多的靈活性,如資料庫可以用任意多的Column,如果能以型別安全的方式訪問所有Columns就好了,幸運的是
有一種方法可以很容易的做到這一點,就是將key進行引數化,見以下程式碼
public class Favorites { private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>(); public <T> void setFavorite(Class<T> klass, T thing) { favorites.put(klass, thing); } public <T> T getFavorite(Class<T> klass) { return klass.cast(favorites.get(klass)); } public static void main(String[] args) { Favorites f = new Favorites(); f.setFavorite(String.class, "Java"); f.setFavorite(Integer.class, 0xcafebabe); String s = f.getFavorite(String.class); int i = f.getFavorite(Integer.class); } }
2.不足之處
There is a limitation to this pattern.
//You can't add your favorite List<String> to a Favorites because you simply can't make a type token for a generic type.
f.setFavorite(List<String>.class, Collections.emptyList());
3.改進
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; /** * References a generic type. * * @author
[email protected] (Bob Lee) */ public abstract class TypeReference<T> { private final Type type; private volatile Constructor<?> constructor; protected TypeReference() { Type superclass = getClass().getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; } /** * Instantiates a new instance of {@code T} using the default, no-arg * constructor. */ @SuppressWarnings("unchecked") public T newInstance() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (constructor == null) { Class<?> rawType = type instanceof Class<?> ? (Class<?>) type : (Class<?>) ((ParameterizedType) type).getRawType(); constructor = rawType.getConstructor(); } return (T) constructor.newInstance(); } /** * Gets the referenced type. */ public Type getType() { return this.type; } public static void main(String[] args) throws Exception { List<String> l1 = new TypeReference<ArrayList<String>>() {}.newInstance(); List l2 = new TypeReference<ArrayList>() {}.newInstance(); } }
參考:
- com.google.common.reflect.TypeToken<T>
- com.fasterxml.jackson.core.type.TypeReference