Gson TypeToken 是如何工作的?
How does Gson TypeToken work?
我知道在 Java 中相反,例如,C# 泛型是编译时特性,并通过类型擦除被删除。那么,Gson 的 TypeToken
到底是如何工作的呢?它是如何获取对象的通用类型的?
Java 的类型擦除适用于单个对象,不适用于 classes 或字段或方法。 TypeToken 使用匿名 class 来确保它保留通用类型信息,而不是仅仅创建一个对象。
From §4.6 of the JLS(强调我的):
Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T| for the erasure of type T. The erasure mapping is defined as follows:
The erasure of a parameterized type (§4.5) G is |G|.
The erasure of a nested type T.C is |T|.C.
The erasure of an array type T[] is |T|[].
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
The erasure of every other type is the type itself.
因此,如果您使用自身的匿名子 class 声明一个 class,它会保持其参数化类型;它没有被删除。因此,请考虑以下代码:
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>]
请注意,如果您没有匿名声明 class,您会得到一个 ClassCastException
,因为擦除; superclass 不会是参数化类型,它会是 Object
.
Gson TypeToken 使用 Neal Gafter 的 super type tokens pattern. this pattern is based on the Class#getGenericSuperclass()
方法,来自文档
Returns the Type
representing the direct superclass of the entity
(class, interface, primitive type or void) represented by this Class.
If the superclass is a parameterized type, the Type
object returned
must accurately reflect the actual type parameters used in the source
code.
这实质上意味着如果你有一个 class 扩展一个参数化的 class,那么你可以获得实际类型参数到 super class as
((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)。
我知道在 Java 中相反,例如,C# 泛型是编译时特性,并通过类型擦除被删除。那么,Gson 的 TypeToken
到底是如何工作的呢?它是如何获取对象的通用类型的?
Java 的类型擦除适用于单个对象,不适用于 classes 或字段或方法。 TypeToken 使用匿名 class 来确保它保留通用类型信息,而不是仅仅创建一个对象。
From §4.6 of the JLS(强调我的):
Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T| for the erasure of type T. The erasure mapping is defined as follows:
The erasure of a parameterized type (§4.5) G is |G|.
The erasure of a nested type T.C is |T|.C.
The erasure of an array type T[] is |T|[].
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
The erasure of every other type is the type itself.
因此,如果您使用自身的匿名子 class 声明一个 class,它会保持其参数化类型;它没有被删除。因此,请考虑以下代码:
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>]
请注意,如果您没有匿名声明 class,您会得到一个 ClassCastException
,因为擦除; superclass 不会是参数化类型,它会是 Object
.
Gson TypeToken 使用 Neal Gafter 的 super type tokens pattern. this pattern is based on the Class#getGenericSuperclass()
方法,来自文档
Returns the
Type
representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class. If the superclass is a parameterized type, theType
object returned must accurately reflect the actual type parameters used in the source code.
这实质上意味着如果你有一个 class 扩展一个参数化的 class,那么你可以获得实际类型参数到 super class as
((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)。