Java進階(四)Java反射TypeToken解決泛型運行時類型擦除的問題解決

來源:互聯網
上載者:User

標籤:gson   class   java   泛型   json   

在開發時,遇到了下面這條語句,不懂,然習之。

 

private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhuiHaoDetailModel>();

 

Gson gson=new Gson();

JSONObject object=new JSONObject(callbackValue);

 

listLottery =  gson.fromJson(object.getString("lists"),

new TypeToken<List<MyZhuiHaoDetailModel>>() {

}.getType());

 

GSON提供了 TypeToken 這個類來協助我們捕獲(capture)像List<MyZhuiHaoDetailModel>這樣的泛型資訊。上文建立了一個匿名內部類,這樣,Java編譯器就會把泛型資訊編譯到這個匿名內部類裡,然後在運行時就可以被 getType()方法用反射API提取到。

 

下面來看看gson的還原序列化,Gson提供了fromJson()方法來實現從Json相關對象到java實體的方法。

 

在日常應用中,我們一般都會碰到兩種情況,轉成單一實體物件和轉換成對象列表或者其他結構。

 

先來看第一種:

 

比如json字串為:{"name":"name0","age":0}

 

代碼:

 

Person person = gson.fromJson(str, Person.class);

提供兩個參數,分別是json字串以及需要轉換對象的類型。

 

第二種,轉換成清單類型:

 

代碼:

 

List<Person> ps = gson.fromJson(str, new TypeToken<List<Person>>(){}.getType());

for(int i = 0; i < ps.size() ; i++)

{

     Person p = ps.get(i);

     System.out.println(p.toString());

}

可以看到上面的代碼使用了TypeToken,它是gson提供的資料類型轉換器,可以支援各種資料集合類型轉換。

 

經過比較,gson和其他現有java json類庫最大的不同是gson需要序列化的實體類不需要使用annotation來標識需要序列化得欄位,同時gson又可以通過使用annotation來靈活配置需要序列化的欄位。

 

另外,java反射包中的TypeToken類是用來解決java運行時泛型型別被擦除的問題的,有點不好理解,我們通過一個例子來認識什麼是泛型的運行時類型擦除。

        ArrayList<String> stringList = Lists.newArrayList();  

       ArrayList<Integer> intList = Lists.newArrayList();        

       System.out.println("intList type is " + intList.getClass());    

      System.out.println("stringList type is " + stringList.getClass());  

      System.out.println(stringList.getClass().isAssignableFrom(intList.getClass()));

上面的代碼我們聲明了兩個泛型的ArrayList類型,一個泛型的型別參數是String,另外一個是Integer;然後我們輸出了兩個泛型的Class,並輸出兩個list的類型是否是同一個list。我們看下輸出的結果:

intList type is class java.util.ArrayListstringList type is class java.util.ArrayListtrue

前兩個輸出都是java.util.ArrayList,而第三個輸出竟然是true,也就是認為stringList和intList的類型是一樣的。這就是所謂的泛型型別擦除。運行時我們不知道泛型型別的型別參數是什麼了。

TypeToken可以解決這個問題,請看下面代碼:

        TypeToken<ArrayList<String>> typeToken = new TypeToken<ArrayList<String>>() {};        TypeToken<?> genericTypeToken = typeToken.resolveType(ArrayList.class.getTypeParameters()[0]);        System.out.println(genericTypeToken.getType());

注意上面第一行代碼使用了一個空的匿名類。第二行使用了resolveType方法解析出泛型型別,第三行代碼列印出泛型型別,輸出是:

class java.lang.String

可以看出TypeToken解析出了泛型參數的具體類型。

TypeToken的方法列表如下:

方法

描述

getType()

獲得封裝的java.lang.reflect.Type.

getRawType()

返回大家熟知的運行時類

getSubtype(Class<?>)

返回那些有特定原始類的子類型。舉個例子,如果這有一個Iterable並且參數是List.class,那麼返回將是List。

getSupertype(Class<?>)

產生這個類型的超類,這個超類是指定的原始類型。舉個例子,如果這是一個Set並且參數是Iterable.class,結果將會是Iterable。

isAssignableFrom(type)

如果這個類型是 assignable from 指定的類型,並且考慮泛型參數,返回true。List<? extends Number>是assignable from List,但List沒有.

getTypes()

返回一個Set,包含了這個所有介面,子類和類是這個類型的類。返回的Set同樣提供了classes()和interfaces()方法允許你只瀏覽超類和介面類。

isArray()

檢查某個類型是不是數組,甚至是<? extends A[]>。

getComponentType()

返回組件類型數組。

 

 

Gson的基本使用就是這麼多,至於annotation方面可以參考gson的官方文檔,希望能對初學java和gson的同學有所協助。

Java進階(四)Java反射TypeToken解決泛型運行時類型擦除的問題解決

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.