文档介绍:通配符
1 通配符的作用
Object[] objs = new String[10];
objs[0] = new Integer(100);
上面代码编译是可以通过的,但在运行时会出现ArrayStoreException。因为objs数组真实的身份是String[],向String[]数组中存放Integer对象当然是不行的。
ArrayList<Object> list = new ArrayList<String>();
(new Integer(100);
上面代码在第一行位置编译失败,因为泛型根本就不让把ArrayList<String>赋值给ArrayList<Object>,对于ArrayList<Object>而言,只能赋值ArrayList<Object>,其他的什么都不能赋值。
这也说明一个问题:
public static void printList(List<Object> list) {…}
调用printList()方法只能传递给它List<Object>类型的参数,而不能传递List<String>,或者List<Integer>,这说明我们的printList()方法有很多的限制,不够通用!!!你可能会想我再重载几次printList()方法吧,但这是行不通的!
public static void printList(List<Object> list) {…}
public static void printList(List<String> list) {…}
因为JVM不知道什么是泛型,这两个方法在到了JVM那里时都是会把泛型参数擦除,这两个方法就是相同的方法了,擦除之后即:
public static void printList(List list) {…}
public static void printList(List list) {…}
当然JVM不可能看到这样的代码,因为编译器不能让你编译通过!
处理这个问题需要使用通配符!
2 子类型通配符
public static void printList(List<? extends Person> list) {…}
这回可以传递给printList()方法List<Student>,以及List<Teacher>参数了。只要类型参数为Person,或者是Person子类型就都可以。
你可以这样来理解通配符,通配符表示“不知道”的意思。即一个问号!但子类型通配符还是知道一些信息的,它只知道用户转递的类型参数一定是Person的子类型。虽然使用了通配符之后printList()方法更加通用了,但是这也是要付出一些代价的。因为不知道List中类型参数的真实类型,所以就不能调用list的add()方法了。你可能会想add(new Student())应该是可以的,但如果List是List<Teacher>呢,你怎么向这样的List添加Student呢?再想一想,add()方法已经作废了,什么都传递不了。
3 父类型通配符
public static void printList(List<? super Student> list) {…}
可以传递给printList()方