背景
之前我們知道泛型在Java中意味著什么特性仙逻,但貌似在項(xiàng)目中很少應(yīng)用到它茂翔,如果應(yīng)用恰當(dāng)混蔼,能夠減少許多冗余的代碼,也能讓你的代碼變得更加安全珊燎。下面會通過解析服務(wù)端返回來的json格式數(shù)據(jù)來講解它的作用惭嚣。
再次科普
泛型可以解決數(shù)據(jù)類型的安全問題遵湖,它的主要原理是:在類聲明的時(shí)候通過一個(gè)標(biāo)識表示類中某個(gè)屬性的類型或者是某個(gè)方法的返回值及參數(shù)類型。就像下面這個(gè)類:
class Person<K,V>{
private K key ;
private V value ;
//省略set和get ...
};
好處是在聲明對象時(shí)料按,可以指定K和V的類型,表現(xiàn)得更為靈活:
Person<String,Integer> t = null ;
t = new Person<String,Integer>() ;
t.setKey("劉德華") ;
t.setValue(40) ;
如果在聲明類對象的時(shí)候卓箫,沒有指定類型载矿,系統(tǒng)會會自動將類中的“T”都換成“Object”,編譯程序的時(shí)候會發(fā)出警告烹卒。
沒有使用泛型時(shí)
Android開發(fā)中服務(wù)端傳來一個(gè)json格式的列表數(shù)據(jù)闷盔,比如商品列表,我們可以使用Gson/FastJson進(jìn)行解析旅急,下面使用Gson解析:
Gson gson=new GsonBuilder().serializeNulls().create();
GoodsListEntity entity = gson.fromJson(response, GoodsListEntity.class);
List<GoodsItem> list=entity.getData().getList();
對于上面的GoodsListEntity我們是這么定義的:
public class BaseEntity {
private int errcode;
private String errmsg;
//省略set和get ...
}
public class GoodsListEntity extends BaseEntity {
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public class Data {
private String total;
private String hasnext;
private String count;
private String page;
private String totalPages;
private List<GoodsItem> list;
//省略set和get ...
private class GoodsItem {
private String productName;
//省略set和get ...
}
}
}
就是這樣定義GoodsListEntity逢勾,我們完成了解析,但是這樣寫實(shí)體類并不夠通用藐吮,因?yàn)槿绻藭r(shí)傳來的不是商品列表溺拱,而是客戶列表或訂單列表,那么我們又要重復(fù)寫一次:
public class GoodsListEntity extends BaseEntity {
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public class Data {
private String total;
private String hasnext;
private String count;
private String page;
private String totalPages;
private List<OrderItem> list;
//省略set和get ...
private class OrderItem {
private String orderId;
//省略set和get ...
}
}
}
那會讓代碼顯得很冗余谣辞,這個(gè)時(shí)候就需要用到泛型的知識迫摔。
使用泛型后
定義一個(gè)網(wǎng)絡(luò)返回基礎(chǔ)類BaseEntity,里面的data我們不知道會傳回來什么類型的數(shù)據(jù)泥从,有可能只包含一個(gè)token句占,或是一個(gè)array,所以我們將其定義為T躯嫉,讓使用它的人去定義data的類型纱烘,代碼如下:
/**
* 網(wǎng)絡(luò)返回基礎(chǔ)類
* @param <T>
*/
public class BaseEntity<T> {
private int errcode;
private String errmsg;
private T data;
//省略set和get ...
}
public class GoodsItem {
private String productName;
//省略set和get ...
有些數(shù)據(jù)是列表結(jié)構(gòu),因此我們還需要定義一個(gè)ListEntity:
/**
* 網(wǎng)絡(luò)返回列表基礎(chǔ)類
* @param <T>
*/
public class ListEntity<T> {
private String total;
private String hasnext;
private String count;
private String page;
private String totalPages;
private List<T> list;
//省略set和get ...
}
這樣祈餐,我們就把一些通用的Entity代碼集合了起來擂啥,后面要解析訂單列表、客戶列表帆阳,我們只需要定義一個(gè)OrderItem和CustomerItem的實(shí)體類啤它,這極大地減少了冗余的代碼:
/**
* 商品列表項(xiàng)
*/
public class GoodsItem {
private String productName;
//省略set和get ...
}
使用了泛型后,原來Gson的解析已經(jīng)不適用舱痘,為什么变骡?我們回到最初的解析看看:
GoodsListEntity entity = gson.fromJson(response, GoodsListEntity.class);
fromJson的第二個(gè)參數(shù)應(yīng)該為GoodsListEntity的類型,那么我們現(xiàn)在的代碼如果這么寫:
BaseEntity<ListEntity<GoodsItem>> entity=gson.fromJson(response,GoodsItem.class)
這樣很顯然第二個(gè)參數(shù)是錯(cuò)誤的芭逝,我們希望傳入以下這類的類型
BaseEntity<ListEntity<GoodsItem>>
請聽下回分解
該怎么傳入該泛型的類型呢塌碌?請參考下一篇文章:《Java基礎(chǔ)--Android中泛型的應(yīng)用(二)》