zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    关于JS动态切换样式表
    关于header()函数重定向的问题
    微信团队讲课笔记 Android 开发(二)UI设计
    Effective C++ 笔记:4设计与声明
    某面试算法题_最短时间找出十包粉末中的两蓝粉末。
    VS2015 配置opengl的一些库
    URAL 1225 Flags 简单DP,一重循环
    POJ 1384 Piggy-Bank 完全背包分析
    POJ 1651 Multiplication Puzzle DP 类似矩阵链
    URAL 1183 Brackets Sequence DP 路径输出
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/6051682.html
Copyright © 2011-2022 走看看