泛型通配符
需求:
定义一个方法,接收一个集合对象(该集合有泛型),并打印出集合中的所有元素。
例如集合对象如下格式:
Collection<Person> coll = new ArrayList<Person>(); coll.add(new Person("jack", 20)); coll.add(new Person("rose", 18)); Collection<Object> coll2 = new ArrayList<Object>(); coll2.add(new Object()); coll2.add(new Object()); coll2.add(new Object()); Collection<String> coll3 = new ArrayList<String>(); coll3.add("abc"); coll3.add("ddd"); coll3.add("eee");
分析,集合对象中的元素的类型是变化的,方法的形参的那么泛型类型就只能定义为Object类型.
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Demo9 { public static void main(String[] args) { ArrayList<Object> arr = new ArrayList<Object>(); arr.add(new Object()); arr.add("String"); print(arr); //将集合的泛型设置类String类型,是Object子类 HashSet<String> hs = new HashSet<String>(); hs.add("hello"); hs.add("jack"); //由于print方法接收的集合进行了元素限定,只接受限定为Object类型的集合,编译不通过 //print(hs); } public static void print(Collection<Object> coll) { Iterator<Object> it = coll.iterator(); while (it.hasNext()) { Object next = it.next(); System.out.println(next); } } }
但是,由于print方法接收的集合进行了元素限定,只接受限定为Object类型的集合,编译不通过该问题如何解决?
可以把方法的形参的泛型去掉,那么方法中就把集合中的元素当做Object类型处理.
也可以使用使用泛型通配符
public class Demo9 { public static void main(String[] args) { ArrayList<Object> arr = new ArrayList<Object>(); arr.add(new Object()); arr.add("String"); print(arr); // 将集合的泛型设置类String类型,是Object子类 HashSet<String> hs = new HashSet<String>(); hs.add("hello"); hs.add("jack"); // 使用泛型通配符,编译通过。 print(hs); } public static void print(Collection<?> coll) { Iterator<?> it = coll.iterator(); while (it.hasNext()) { Object next = it.next(); System.out.println(next); } } }
上述就使用了泛型通配符
通配符:? public void show(List<?> list) { } 可以对类型进行限定范围。 ?extends E: 接收E类型或者E的子类型。 ? super E: 接收E类型或者E的父类型。
限定泛型通配符的边界
限定通配符的上边界:
extends
接收Number 类型或者Number的子类型
正确:Vector<? extends Number> x = new Vector<Integer>(); 错误:Vector<? extends Number> x = new Vector<String>();
限定通配符的下边界
super
接收Integer 或者Integer的父类型
正确:Vector<? super Integer> x = new Vector<Number>(); 错误:Vector<? super Integer> x = new Vector<Byte>();
总结:
JDK5中的泛型允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定
注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。
泛型的基本术语,以ArrayList<E>为例:<>念着typeof
ArrayList<E>中的E称为类型参数变量
ArrayList<Integer>中的Integer称为实际类型参数
整个称为ArrayList<E>泛型类型
整个ArrayList<Integer>称为参数化的类型ParameterizedType