• JSON 序列化与反序列化(二)使用TypeReference 构建类型安全的异构容器


    1. 泛型通常用于集合,如Set和Map等。这样的用法也就限制了每个容器只能有固定数目的类型参数,一般来说,这也确实是我们想要的。

    然而有的时候我们需要更多的灵活性,如数据库可以用任意多的Column,如果能以类型安全的方式访问所有Columns就好了,幸运的是

    有一种方法可以很容易的做到这一点,就是将key进行参数化,见以下代码

     1 public class Favorites {
     2     private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
     3     public <T> void setFavorite(Class<T> klass, T thing) {
     4         favorites.put(klass, thing);
     5     }
     6     public <T> T getFavorite(Class<T> klass) {
     7         return klass.cast(favorites.get(klass));
     8     }
     9     public static void main(String[] args) {
    10         Favorites f = new Favorites();
    11         f.setFavorite(String.class, "Java");
    12         f.setFavorite(Integer.class, 0xcafebabe);
    13         String s = f.getFavorite(String.class);
    14         int i = f.getFavorite(Integer.class);
    15     }
    16 }

    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 crazybob@google.com (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

  • 相关阅读:
    HTML5 postMessage 和 onmessage API 详细应用
    layerX
    HTML5中createPattern()
    HTML5中lineCap端点样式遇到closePath()
    [转]Modernizr的介绍和使用
    HTML5学习之路
    javascript选取文档元素
    ie不支持getElementsByClassName的解决办法
    document.images、document.forms、doucument.links——>HTMLCollection
    JavaScript 参考手册——javascript本地和内置对象、BOM、DOM
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/6051682.html
Copyright © 2020-2023  润新知