1.针对泛型的缺陷
问题:类型转换,如何限制类型转换
解决方案:使用通配符进行限制,确保类型转换安全
错误例子(针对泛型的缺陷)
List<String> strList = new ArrayList<String>();
List<Integer> intList = new ArrayList<Integer>();
intList.add(123);
strList.add("abc");
numberPlus(intList);
// numberPlus(strList); 编译出错
//限制只传入数字类型进行计算,限制上限类型,可读不可写
static void numberPlus(List<? extends Number> list){
Number b= 123;
//list.add(0,b);编译出错
int a = (Integer) list.get(0);
a=a+a;
System.out.println("numberPlus :" + a);
}
2.引入泛型通配符
由此引入通配符
? super xxx,定义:限制下限,最小可以是xxx,调用:可写
? extends xxx, 定义:限制上限,最大只能是xxx,调用:可读
3.最佳使用案例:
1.开源框架RxJava 的map 类型转换就使用
//? super 可写 |? extends 可读
public <R> Observable<R> map(Function<? super T, ? extends R> function){
// ObservableMap map = new ObservableMap(source,function);
ObservableMap<T, R> observableMap = new ObservableMap(source, function); // source 控制权
return new Observable<R>(observableMap); // observableMap是source的实现类
//return new Observable(map) ;
}
2.Java collection copy源码
就是用 <? extends T>src,来限制src只读不能修改,保证src的安全性
再使用<? super T> dest可写,但不可读,进行把src安全拷贝到dest
同时安全确保拷贝时,dest类型包含或相同src,所以如果src时dest的子类时,编译器会检查出错误如:
collection 的copy源码
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}