1. 程式人生 > >JSON 序列化與反序列化(二)使用TypeReference 構建型別安全的異構容器

JSON 序列化與反序列化(二)使用TypeReference 構建型別安全的異構容器

原文連結: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

原文:Super Type Tokens