背景
之前我们知道泛型在Java中意味着什么特性,但貌似在项目中很少应用到它,如果应用恰当,能够减少许多冗余的代码,也能让你的代码变得更加安全。下面会通过解析服务端返回来的json格式数据来讲解它的作用。
再次科普
泛型可以解决数据类型的安全问题,它的主要原理是:在类声明的时候通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。就像下面这个类:
class Person<K,V>{
private K key ;
private V value ;
//省略set和get ...
};
好处是在声明对象时,可以指定K和V的类型,表现得更为灵活:
Person<String,Integer> t = null ;
t = new Person<String,Integer>() ;
t.setKey("刘德华") ;
t.setValue(40) ;
如果在声明类对象的时候,没有指定类型,系统会会自动将类中的“T”都换成“Object”,编译程序的时候会发出警告。
没有使用泛型时
Android开发中服务端传来一个json格式的列表数据,比如商品列表,我们可以使用Gson/FastJson进行解析,下面使用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,我们完成了解析,但是这样写实体类并不够通用,因为如果此时传来的不是商品列表,而是客户列表或订单列表,那么我们又要重复写一次:
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 ...
}
}
}
那会让代码显得很冗余,这个时候就需要用到泛型的知识。
使用泛型后
定义一个网络返回基础类BaseEntity,里面的data我们不知道会传回来什么类型的数据,有可能只包含一个token,或是一个array,所以我们将其定义为T,让使用它的人去定义data的类型,代码如下:
/**
* 网络返回基础类
* @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 ...
有些数据是列表结构,因此我们还需要定义一个ListEntity:
/**
* 网络返回列表基础类
* @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代码集合了起来,后面要解析订单列表、客户列表,我们只需要定义一个OrderItem和CustomerItem的实体类,这极大地减少了冗余的代码:
/**
* 商品列表项
*/
public class GoodsItem {
private String productName;
//省略set和get ...
}
使用了泛型后,原来Gson的解析已经不适用,为什么?我们回到最初的解析看看:
GoodsListEntity entity = gson.fromJson(response, GoodsListEntity.class);
fromJson的第二个参数应该为GoodsListEntity的类型,那么我们现在的代码如果这么写:
BaseEntity<ListEntity<GoodsItem>> entity=gson.fromJson(response,GoodsItem.class)
这样很显然第二个参数是错误的,我们希望传入以下这类的类型
BaseEntity<ListEntity<GoodsItem>>
请听下回分解
该怎么传入该泛型的类型呢?请参考下一篇文章:《Java基础–Android中泛型的应用(二)》