美文网首页
泛型,TypeToken(Guava)

泛型,TypeToken(Guava)

作者: byamao1 | 来源:发表于2018-10-29 17:27 被阅读0次

    众所周知,Java的泛型在运行时会有类型擦除。Guava的TypeToken却很好解决了这个问题。原因在匿名类+反射,其方法getSuperclassTypeParameter获取了Type。其中关键代码是调用了反射方法:

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        // 获取泛型超类
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
          throw new RuntimeException("Missing type parameter.");
        }
        // 类型参数,这个就是被擦除的泛型类型
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
     }
    
    

    其原理就是用一个继承TypeToken的匿名类,从而获取该匿名类的泛型超类,然后将其强制转换为ParameterizedTypeParameterizedType包含了其原始类型ParameterizedType.getRawType()及其泛型类型ParameterizedType.getActualTypeArguments()。举例:
    对于List<String>这个类,

    List list = new ArrayList<String>(){};
    Type superclass = list.getClass().getGenericSuperclass();
    ParameterizedType parameterized = (ParameterizedType) superclass;
    Type raw = parameterized.getRawType();  // ArrayList类
    Type[] types = parameterized.getActualTypeArguments();  // String类
    

    如果是List<List<String>>这种嵌套的泛型,那么还可以对上面Type[] types内的Type继续强制类型转换为ParameterizedType,嵌套获取其内嵌套的泛型。
    注意

    List list = new ArrayList<String>(){};  //这是匿名类
    不要写成
    List<String> list = new ArrayList(){}; 
    或
    List list = new ArrayList<String>();  //这样不是继承,无法获取泛型
    
    

    TypeLiteral可以通过TypeLiteral.getType()转换为Type,以便gson反序列化。也可以用比较原始的方式:

        // 改造自 TypeToken.getSuperclassTypeParameter()
        static Type getSuperclassTypeParameter(Class<?> subclass) {
            Type superclass = subclass.getGenericSuperclass();
            if (superclass instanceof Class) {
                throw new RuntimeException("Missing type parameter.");
            }
            ParameterizedType parameterized = (ParameterizedType) superclass;
            return parameterized.getActualTypeArguments()[0];
        }
    
    TypeLiteral typeLiteral = new TypeLiteral<List<String>>() {};
    Type type = getSuperclassTypeParameter(typeLiteral.getClass());
    // gson反序列化
    List<String> list = gson.fromJson(json, type);  
    

    相关文章

      网友评论

          本文标题:泛型,TypeToken(Guava)

          本文链接:https://www.haomeiwen.com/subject/iuybtqtx.html