在 Java 反射中,對(duì)于一般的類翁都,我們可以通過對(duì)象.getClass
來獲得類對(duì)象
碍论,然后通過類對(duì)象.getFields()
可以獲得類下的字段對(duì)象數(shù)組
,以及字段對(duì)象.getType()
來獲得字段的具體類型柄慰,如下面源碼中carClass.getFields()[0].getType():int
鳍悠;
但如果是泛型類(參見源碼中的Foo<T>
類),因?yàn)槠渚唧w類型是外部傳入的先煎,引起 Java反射是無法獲取到傳入泛型的具體類型的贼涩,如字段對(duì)象.getType
輸出 Object(參見源碼中輸出fooClass.getFields()[0].getType():class java.lang.Object
)
Gson的TypeToken解決了 Java 泛型反射問題,通過定義一個(gè)匿名內(nèi)部類new TypeToken<Foo<Integer>>(){}
薯蝎,然后可以獲取具體的泛型類型遥倦。
源碼如下:
package test.onjava;
import com.google.gson.reflect.TypeToken;
class TestGeneric {
class Car {
public int wheel;
protected int color; // carClass.getFields().length 不包含這個(gè)
}
class Foo<T> {
public T value;
public String key;
}
void testGeneric(){
// 一般類
System.out.println("-----------------------Normal class--------");
Car car = new Car();
Class carClass = car.getClass();
System.out.println(" car.getClass():" + carClass);
System.out.println(" carClass.getFields().length:" + carClass.getFields().length);
System.out.println(" carClass.getFields()[0].getType():" + carClass.getFields()[0].getType());
// 泛型類
System.out.println("-----------------------Generic class--------");
Foo foo = new Foo<Integer>();
Class fooClass = foo.getClass();
System.out.println(" foo.getClass():" + fooClass);
System.out.println(" fooClass.getFields().length:" + fooClass.getFields().length);
System.out.println(" fooClass.getFields()[0].getType():" + fooClass.getFields()[0].getType());
// Gson
System.out.println("----------------------Gson TypeToken---------");
TypeToken typeToken= new TypeToken<Foo<Integer>>(){};
System.out.println(" typeToken.getRawType:" + typeToken.getRawType());
System.out.println(" typeToken.getType:" + typeToken.getType());
}
}
輸出
-----------------------Normal class--------
car.getClass():class test.onjava.TestGeneric$Car
carClass.getFields().length:1
carClass.getFields()[0].getType():int
-----------------------Generic class--------
foo.getClass():class test.onjava.TestGeneric$Foo
fooClass.getFields().length:2
fooClass.getFields()[0].getType():class java.lang.Object
----------------------Gson TypeToken---------
typeToken.getRawType:class test.onjava.TestGeneric$Foo
typeToken.getType:test.onjava.TestGeneric$Foo<java.lang.Integer>