【IT168 文档】本来jdk5之前有java.util.List这个Interface是这么用的:
myIntList.add(new Integer(0));
Integer x = (Integer)myIntList.iterator().next();
这里myIntList其实可以myIntList.add(new Object());因为声明语句就没有写出该List到底支持什么。所以myIntList.iterator().next()返回的只能是Object,它并不知道这里面装的到底是什么具体的类。
因为这个List里既可能有Integer对象,也可能有Double对象,为了不要(Integer)这个强制转换,我们有了这个:
这个时候,Integer x = (Integer)myIntList.iterator().next();就可以去掉强制转换写成
因为编译器确实知道了myIntList里放的就是Integer,不会是其他。这个地方要注意:List
List<Integer> myIntList = new LinkedList(); //警告,不出错 myIntList只能add(Integer)
List<Integer> myIntList = new LinkedList<Double>(); // 出错
事情到这里,看似所有问题都解决了,但是不尽然。慢慢道来:
public void say();
};
class Circle extends {
public void say() {
System.out.println("i am a circle");
}
};
通过上面,我们可以
shape.say(); // i am a circle.
这里表明,父类可以代表子类。但是,List
for(Shape s : list) {
s.say();
}
}
那么这个函数不能被这样调用:
sayAll(circleList);
只能被这样调用:
sayAll(shapeList);
##这里详细解释为什么List
List<Shape> shapeList = circleList;
shapeList.add(new Shape());
circleList.iterator().next(); //出错。
那么怎么解决这个问题?可以这样解决:
for(Object s : list) {
}
}
具体我们刚才讨论的Shape和Circle的问题可以这样写:
for(Shape s : list) {
s.say();
}
}
其中public void sayAll(List list) 就是public void sayAll(List list) 的意思,这个例子说明,List才是List
class Student extends Person{}
public class Census {
public static void addRegistry(Map<String, ? extends Person> registry) { ... }
};
Map<String,Driver> allDrivers = ...
Census.add(allDrivers);
我们下一个话题,先由这个引起:我们说过,如果List
List<Shape> shapeList = circleList; //错误
shapeList.add(new Shape());
circleList.iterator().next(); //出错。
那么List确实是List
List<?> list= circleList; //正确
list.add(new Shape()); //错误
为什么list不能加新元素?因为list里的元素类型已经定义好了,是?,不是任何类型,所以不能加入任何类型的元素。
所以如下方法是不能使用的:
for (Object o : a) {
c.add(o); // compile time error 因为c不能加入元素
}
}
但是我们想要在List里加入元素如何弄呢?一个例子概括如下:
for (T o : a) {
c.add(o); // correct
}
}
那么这样,c这个Collection就能加入东西了,加入的东西必须是T类,看例子:
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T inferred to be Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, co);// T inferred to be Object
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error
到现在为止,上面一共讲了两个jdk1.5中新的事物
static <T> void fromArrayToCollection(T[] a, Collection<T> c)
那么看下面两个例子,他们做的事情都是一样的,但是分别用了这两个方法:
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E) c);
}
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
}
他们都做两件事:判断任意类的容器是不是在本身这容器里。加入E子类的容器到本身的容器里。
也可以同时都用上两个新东西:
public static <T> void copy(List<T> dest, List<? extends T> src){}
}
或者写成
public static <T,S extends T> void copy(List<T> dest, List<S> src){}
}
作为总结这两个新的java特性,举出一个复杂例子:
public void drawAll(List<? extends Shape> shapes) {
history.addLast(shapes);
for(Shape s : shape) {
s.draw(this);
}
}