为什么这个泛型返回方法没有正确使用泛型类型?

时间:2017-05-24 19:22:38

标签: java generics

我有一些代码,我需要多次使用,所以我想把它放在一个方法中。代码是:

try
{
    //Create a list descriptor for GSON to use
    Type listType = new TypeToken<ArrayList<MyClass>>(){}.getType();

    //Get it out as a list
    List<MyClass> myClass = gson.fromJson( jsonString, listType );
}
catch (Exception e)
{
    e.printStackTrace();
}

我把它放在一个方法中:

public static <T> List<T> getTypeAsList(String jsonString)
{
    try
    {
        Gson gson = new Gson();

        //Create a list descriptor for GSON to use
        Type listType = new TypeToken<ArrayList<T>>(){}.getType();

        //Get it out as a list
        return gson.fromJson( jsonString, listType );
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return null;
    }
}

我将这种方法称为:

util.<MyClass>getTypeAsList( jsonString );

但是当我这样做时,我得到了错误:

com.google.gson.internal.StringMap cannot be cast to MyClass

为什么没有得到合适的类型?它适用于第一个代码,而不是通用方法。

2 个答案:

答案 0 :(得分:3)

类型T已被删除。这意味着通用方法没有T的类型信息。

通常情况下,TypeToken用于捕获该类型信息,但是实例化一个信息很简单,在您的情况下,您已经知道了一些信息,即您拥有{{1} 某些类型。

因此,您可以创建一个实用程序方法,以List作为原始类型创建ParameterizedType,并将任意ArrayList作为类型参数:

Type

然后你可以像这样使用它:

public static ParameterizedType listTypeWith(Type t) {
    Type[] actual = { t };
    return new ParameterizedType() {

        @Override
        public Type getRawType() {
            return ArrayList.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return actual;
        }
    };
}

答案 1 :(得分:0)

这是由于编译时的类型擦除造成的。

进一步解释 - 在第一种情况下

new TypeToken<ArrayList<MyClass>>(){}

在编译时,将使用实际类型ArrayList<MyClass>生成匿名类。另一方面,通用调用

  new TypeToken<ArrayList<T>>(){}

实际编译的匿名类将接收ArrayList<Object>作为实际类型。因此,gson使用默认实现(即StringMap)来反序列化数组元素