为泛型超类型的类型参数创建TypeToken

时间:2016-08-25 09:53:11

标签: java android generics gson typetoken

我正在为两个依赖的泛型模型实现Gson TypeAdapter

interface ModelA<T> {}
interface ModelB<T> extends ModelA<List<T>> {}

为此,我需要获得TypeTokenTypeAdapter。通过做

Type type = ((ParameterizedType) type).getActualTypeArguments()[0];
TypeToken<?> token = TypeToken.get(type);
TypeAdapter<?> adapter = gson.getAdapter(token);

我为任何给定类型AnyType的模型和相关适配器获取了一个类型标记。这是我ModelA所需要的,但对于ModelB,我需要List<AnyType>的适配器,这是直接使用ModelA<List<AnyType>>的结果。

使用传递原始类型标记的原始类型的接口

token.getRawType().getGenericInterfaces()[0]

我似乎只获得了List类型的删除类型。

如何组合这两个信息以获取通用List<AnyType>类型或直接创建?作为输入,它只有ModelB<AnyType>的类型标记。

实施例

对于给定的行为,我实施了一个显示差异的简单测试。我使用Gson内部非API类expected hahn 的答案中取了$Gson$Types部分。

public class TypeTokenValidate {

    public interface ModelA<T> {}
    public interface ModelB<T> extends ModelA<List<T>> {}

    @Test
    public void genericToken() throws Exception {
        TypeToken<ModelB<String>> token = new TypeToken<ModelB<String>>() {};
        ModelB<String> m = new ModelB<String>() {};
        Type expected = $Gson$Types.resolve(ModelB.class, m.getClass(),
                ModelA.class.getTypeParameters()[0]);
        assertEquals(expected, getActual(token));
    }

    private static Type getActual(TypeToken<?> token) {
        Type type = token.getType();
        //type = token.getRawType().getGenericInterfaces()[0];
        type = ((ParameterizedType) type).getActualTypeArguments()[0];
        return TypeToken.get(type).getType();
    }
}

2 个答案:

答案 0 :(得分:3)

您可以使用$Gson$Types来检索已键入Type的{​​{1}}。例如:

List

会返回ModelB<String> m = new ModelB<String>() {}; Type resolve = $Gson$Types.resolve(m.getClass(), m.getClass(), ModelA.class.getTypeParameters()[0]); Type设置为rawTypeList设置为typeArguments。因此,您可以根据需要保留类型。

然后执行此块

[String]

会导致TypeToken<?> token = TypeToken.get(resolve); TypeAdapter<?> adapter = gson.getAdapter(token); 的适配器设置为CollectionTypeAdaptorFactory elementTypeAdapter.type

答案 1 :(得分:1)

如果您使用.getType()而不是.getRawType(),那么您要查找的信息似乎会被保留:

import java.util.List;
import java.lang.reflect.ParameterizedType;
import com.google.gson.reflect.TypeToken;

public class Test  {

   public interface ModelA<T> {};

   public interface ModelB<T> extends ModelA<List<T>> {}

   public static void main(String[] args) {

        // Using java.lang.reflect.*:

        System.out.println(ModelB.class.getGenericInterfaces()[0]);
        // out: Test.Test$ModelA<java.util.List<T>>
        System.out.println(((ParameterizedType)ModelB.class.getGenericInterfaces()[0]).getActualTypeArguments()[0]);
        // out: java.util.List<T>
        System.out.println(((ParameterizedType)((ParameterizedType)ModelB.class.getGenericInterfaces()[0]).getActualTypeArguments()[0]).getActualTypeArguments()[0]);
        // out: T

        // Recovery from a TokenType instance...

        // ... using .getRawType()
        System.out.println(TypeToken.get(ModelB.class.getGenericInterfaces()[0]).getRawType());
        // out: interface Test$ModelA
        System.out.println(TypeToken.get(((ParameterizedType)((ParameterizedType)ModelB.class.getGenericInterfaces()[0]).getActualTypeArguments()[0])).getRawType());
        // out: interface java.util.List

        // ... using .getType()
        System.out.println(TypeToken.get(ModelB.class.getGenericInterfaces()[0]).getType());
        // out: Test$ModelA<java.util.List<T>>
        System.out.println(TypeToken.get(((ParameterizedType)((ParameterizedType)ModelB.class.getGenericInterfaces()[0]).getActualTypeArguments()[0])).getType());
        // out: java.util.List<T>
   }
}

希望您能从中找出如何创建TokenAdaptors