全国咨询/投诉热线:400-618-4000

Java培训之通配符

更新时间:2016年06月28日14时13分 来源:传智播客Java培训学院 浏览次数:

1 通配符的作用
Object[] objs = new String[10];
objs[0] = new Integer(100);
上面代码编译是可以通过的,但在运行时会出现ArrayStoreException。因为objs数组真实的身份是String[],向String[]数组中存放Integer对象当然是不行的。
ArrayList<Object> list = new ArrayList<String>();
list.add(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()方法List<Student>,以及List<Person>,甚至List<Object>也是可以的。只要传递给printList()方法的List类型参数为Student,或者Student的父类型就是可以的。
你现在可以向list中添加Student类型的参数,例如:list.add(new Student())。因为用户提供的参数List<Student>、List<Person>、List<Object>,无论哪一种类型,对于list.add(new Student())都是合法的。
但是,现在我们不知道list的get()方法返回的是什么了!因为用户传递的可能是List<Student>、List<Person>、List<Object>,如果我们用Student s = list.get(0),那么如果list其实是一个List<Person>岂不是出错了!没错,只能使用Object来接收list.get(0)的返回值了。
 

4 无界通配符
所谓无界通配符,即List<?>,对通配符没有限定。你可以给List<?>赋任意的值,但是,你能使用这样的list干什么呢?也不能add(),也只能使用Object来接收get()方法返回值。
所以,通常List<?>只能表示你在使用泛型而已!编译器会认为List<?>比List更加优雅一些!你可能也看出来了,泛型还真是很垃圾!!!这也是没有办法中的办法,现在的泛型是迁移性兼容的一种版本而已!Java设计者不敢让JVM知道泛型的存在,原因是为了兼容1.4之前的版本。当所有人都在使用1.5以上版本的JDK后,Java的泛型可能就不会再是编译期状态了。
 

本文版权归传智播客Java培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:传智播客Java培训学院
首发:http://www.itcast.cn/javaee