例如,我理解在Java中,C#泛型是编译时特性,是通过类型擦除删除的。那么,Gson的TypeToken到底是如何工作的呢?它如何获得对象的泛型类型?
发布于 2015-05-02 20:17:50

从“司法文书”第4.6条起 (重点地雷):
类型擦除是从类型(可能包括参数化类型和类型变量)到类型(从来不是参数化类型或类型变量)的映射。对于类型T的擦除,我们编写了_~_ 参数化类型(§4.5) G的擦除值是{x}。 嵌套类型T.C的擦除值是{##**$$}}。 数组类型T[]的擦除值是{##**$$}}。 类型变量(§4.4)的擦除是其最左界的擦除。 其他类型的擦除是类型本身。
因此,如果您声明一个类本身具有一个匿名子类,它将保持它的参数化类型;它不会被擦除。因此,请考虑以下代码:
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.HashMap;
public class Erasure<T>
{
public static void main(String...strings) {
Class<?> foo = new Erasure<HashMap<Integer, String>>() {}.getClass();
ParameterizedType t = (ParameterizedType) foo.getGenericSuperclass();
System.out.println(t.getOwnerType());
System.out.println(t.getRawType());
System.out.println(Arrays.toString(t.getActualTypeArguments()));
}
}这一产出如下:
null
class Erasure
[java.util.HashMap<java.lang.Integer, java.lang.String>]注意,如果您不匿名声明类,由于擦除,您将得到一个ClassCastException;超类不是参数化类型,它将是一个Object。
发布于 2015-05-02 20:09:02
Java的类型擦除适用于单个对象,而不是类、字段或方法。TypeToken使用匿名类来确保保存泛型类型信息,而不仅仅是创建对象。
发布于 2021-08-06 05:55:56
Gson TypeToken利用Neal的超型令牌模式。此模式基于来自docs的Class#getGenericSuperclass()方法。
返回表示该类表示的实体的直接超类(类、接口、原始类型或空)的
Type。如果超类是参数化类型,则返回的Type对象必须准确地反映源代码中使用的实际类型参数.。
这在本质上意味着,如果有一个类扩展了一个参数化类,那么您可以将实际的类型参数作为
((ParameterizedType)myClassObj.getGenericSuperClass()).getActualTypeArguments()因此,当您在Gson中创建类型令牌时,
Type someTypeToken = new TypeToken<Collection<Integer>>(){};
// This essentially is same as defining
class AnonClass extends TypeToken<Collection<Integer>>{}现在,您可以很容易地将Type参数获得到上面指定的超级类型(TypeToken)。
https://stackoverflow.com/questions/30005110
复制相似问题