87.Java泛型通配符

泛型通配符

需求:

定义一个方法,接收一个集合对象(该集合有泛型),并打印出集合中的所有元素。

例如集合对象如下格式:

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

 

posted @ 2020-09-06 21:52  nohert  阅读(194)  评论(0编辑  收藏  举报