Gson TypeToken如何运作?

Hei*_*erg 21 java generics gson erasure

据我所知,在Java中,例如,C#泛型是编译时功能,并通过类型擦除删除.那么,Gson TypeToken的确如何运作?它是如何获得对象的泛型类型的?

dur*_*597 29

这是一招!

从JLS的§4.6(强调我的):

类型擦除是从类型(可能包括参数化类型和类型变量)到类型(从不参数化类型或类型变量)的映射.我们写| T | 用于擦除类型T.擦除映射定义如下:

参数化类型(第4.5节)G的擦除是| G |.

嵌套类型TC的擦除是| T | .C.

数组类型T []的擦除是| 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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

这输出:

null
class Erasure
[java.util.HashMap<java.lang.Integer, java.lang.String>]
Run Code Online (Sandbox Code Playgroud)

请注意,ClassCastException如果您因为删除而没有匿名声明该类,那么您将得到一个; 超类不是参数化类型,它将是一个Object.


Lou*_*man 8

Java的类型擦除适用于单个对象,而不是类或字段或方法.TypeToken使用匿名类来确保它保留泛型类型信息,而不是仅创建对象.