问题
public class ArrayList {
public Object get(int i) { ... }
public void add(Object o) { ... }
...
private Object[] elementData;
}
泛型类
Pair<String, Integer> pair = new Pair<String, Integer>();
泛型方法
static <T> void fromArrayToCollection(T[] a, Collection<T> c){
for (T o : a) {
c.add(o); // correct
}
}
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src){...}
}
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src){...}
}
<T> T writeAll(Collection<T> coll, Sink<? super T> snk) { … }
String str = writeAll(cs, s); // YES!!!
推断出来的T是String。
通配符
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
因为我们不知道c的元素类型,我们不能向其中添加对象。另一方面,我们可以调用get()方法并使用其返回值。
返回值是一个未知的类型,但是我们知道,它总是一个Object,因此把get的返回值赋值给一个Object类型的对象。
通配符的上限(upper bound)
public void addRectangle(List<? extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
你应该能够指出为什么上面的代码是不允许的。因为shapes.add的第二个参数类型是? extends Shape ——一个Shape未知的子类。因此我们不知道这个类型是什么,所以这里传递一个Rectangle不安全。
可以使用&将多个通配符链接
新老代码兼容(java5为分界线)
本质(编译和擦除)
public String loophole(Integer x) {
List<String> ys = new LinkedList<String>();
List xs = ys;
xs.add(x); // compile-time unchecked warning
return ys.iterator().next();
}
上面的代码与下面的代码的行为一样:
public String loophole(Integer x) {
List ys = new LinkedList();
List xs = ys;
xs.add(x);
return (String) ys.iterator().next(); // run time error
}
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());//true
Collection cs = new ArrayList<String>();
if (cs instanceof Collection<String>) { ...} // 非法
类似的,如下的类型转换
Collection<String> cstr = (Collection<String>) cs;
得到一个unchecked warning,因为运行时环境不会为你作这样的检查。
对类型变量也是一样:
<T> T badCast(T t, Object o) {
return (T) o; // unchecked warning
}
public static <T extends Comparable> T min(T[] a)
编译后经过类型擦除会变成下面这样:
public static Comparable min(Comparable[] a)