在java開發中,泛型通常可以用來做兩件事兒:
1、檢驗限制
檢驗限制添加的或者要處理的數據只能是泛型指定的類型。
比如List<String> list,這個list集合只能添加String類型的數據。
再比如,有一個抽象類Father:
public abstract class Father {
public abstract void execute();
}
有一個類Handler2,只處理繼承了Father類的對象:
public class Handler2<T extends Father> {
public void execute(T t){
t.execute();
}
public static void main(String[] args) {
Handler2<Son> handler = new Handler2<Son>();
Son sun = new Son();
handler.execute(sun);
}
}
在Handler2中只是調用了Father子類的execute方法,假如一個類沒有繼承Father類,則在編譯時就會報錯:
Handler2<User> handler = new Handler2<User>();
這行代碼會報錯:
Bound mismatch: The type User is not a valid substitute for the bounded parameter <T extends Father> of the type Handler2<T>
2、根據泛型指定的類型,進行參數的轉化
這里所說的參數轉換包括兩種:一種是類型的強制轉換,一種是數據的反序列化。
第一種就不說了(T)obj,這里重點說一下根據泛型進行數據的反序列化:
假設有這么一個需求,你需要設計一個RPC通信框架,RPC通信過程是這樣的,在A端,將一個T類型的對象序列化成一個json串,通過socket傳給B端,B端接收到這個消息后,將這個Json串反序列化成T類型的對象,進行處理。
先不說消息生產者A端,這里看一下消費者B端,B端不可能為所有類型都單獨寫一遍基于某個類型的數據接收和數轉換的實現方法,而是基于泛型,參數轉換類根據指定的泛型。
看下面例子,首先是一個父類Father:
public abstract class Father<T> {
//當泛型是List、Set集合或者是Map時,clazz就是集合的類型,否則就是普通類的類型
public Class clazz;
//當泛型是List、Set類型時,valueClazz就是集合值的類型,Map時就是鍵值對中值的類型。當泛型為普通類型時,valueClazz為空
public Class valueClazz;
//當泛型是MAP時,keyClazz是鍵值對中key的類型,當泛型為普通類型時,keyClazz為空
public Class keyClazz;
public ParameterType parameterType;
@SuppressWarnings("unchecked")
public Father(){
//獲得當前對象父類的類型,對于Son子類來說,就是Father類。Father類是一個帶有泛型的類型
//所以getGenericSuperclass()返回的Type是一個ParameterizedType類型的實例
ParameterizedType paramterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
//getActualTypeArguments用于獲得泛型類中<>中的實際類,返回值是一個數組,比如<T,Z>,則數組為{T.class,Z.class}
Type type = paramterizedType.getActualTypeArguments()[0];
//如果泛型中的T也是一個泛型的類型,比如List<User>, collection,Map等泛型
if(ParameterizedType.class.isAssignableFrom(type.getClass())){
ParameterizedType parameterizedType = (ParameterizedType)type;
clazz = (Class<T>) parameterizedType.getRawType();
//如果是map類型,設置key和value的類型
//如果當前類實現了map接口
if(Map.class.isAssignableFrom(clazz)){
keyClazz = (Class) parameterizedType.getActualTypeArguments()[0];
valueClazz = (Class) parameterizedType.getActualTypeArguments()[1];
parameterType = ParameterType.MAP;
//如果是collection集合,則設置集合value的類型
}else{
valueClazz = (Class) parameterizedType.getActualTypeArguments()[0];
parameterType = ParameterType.COLLECTION;
}
}else{
this.clazz = (Class<T>) paramterizedType.getActualTypeArguments()[0];
parameterType = ParameterType.SIMPLE;
}
}
/**
* @Title: receiveAndExecuteMsg
* @Description: 接收并處理消息
* @param @param message
* @param @throws Exception 設定文件
* @return void 返回類型
* @throws
*/
public void receiveAndExecuteMsg(String message)throws Exception{
Object obj = null;
//如果泛型是普通的引用類型
if(parameterType==ParameterType.SIMPLE){
obj = JsonConvertUtil.getObjFromJson(message, clazz);
//如果是List<T>,Set<T>這種泛型
}else if(parameterType==ParameterType.COLLECTION){
obj = JsonConvertUtil.getListFromJosn(message, clazz, valueClazz);
//如果是Map<E,T>這種泛型
}else{
obj = JsonConvertUtil.getMapFromJson(message, clazz, keyClazz, valueClazz);
}
execute((T)obj);
}
/**
* 處理消息
* @Title: execute
* @Description: TODO(這里用一句話描述這個方法的作用)
* @param @param t 設定文件
* @return void 返回類型
* @throws
*/
public abstract void execute(T t);
}
然后是兩個子類,兩個子類都指定了不同的泛型:
public class Son extends Father<List<User>> {
@Override
public void execute(List<User> list) {
System.out.println(list.size()+",name="+list.get(0));
}
}
public class Son2 extends Father<User> {
@Override
public void execute(User user) {
System.out.println("name="+user.getName());
}
}
下面是User實體類和枚舉類型ParameterType:
public class User {
private int id;
private String name;
//省略了get/set
}
//標明泛型是什么類型
public enum ParameterType {
SIMPLE("simple", "普通java類"),
COLLECTION("collection", "List,Set等集合"),
MAP("map", "map類型");
private String value;
private String desc;
private ParameterType(String value,String desc){
this.value = value;
this.desc = desc;
}
//.....
}
最后,做一個測試:
public class TestMain {
public static void main(String[] args) {
List<User> userList = new ArrayList<User>();
User user = new User();
user.setId(1);
user.setName("測試1");
userList.add(user);
//模擬一個json消息
String message = JsonConvertUtil.getJsonFromObj(userList);
Son son = new Son();
try {
//接收并處理消息
son.receiveAndExecuteMsg(message);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//測試2
User user2 = new User();
user2.setName("測試2");
//模擬一個json消息
String message2 = JsonConvertUtil.getJsonFromObj(user2);
Son2 son2 = new Son2();
try {
son2.receiveAndExecuteMsg(message2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}