Java泛型:通配符

来源:互联网 发布:p2p网管软件 编辑:程序博客网 时间:2024/04/28 19:41

通配符是Java泛型里的一部分,但是在普通业务代码上应用不会很多,其提供一系列关于编译器上的检查,以保证代码的稳定。这里记录一些这两天学习到的关于通配符的知识。

package com.qpm.learn.base;import java.util.*;/**    * @ClassName: UnboundedWildcards1     * @Description: TODO    Java泛型学习 * @author kangqiang.w 945766863@qq.com     * @date 2017年3月5日 上午9:34:55     *   */class Fruit{}class Apple extends Fruit{}class Orange extends Fruit{}public class UnboundedWildcards1 {    static List list1;  //编译器报未确定类型的warn    static List<?> list2;    static List<? extends Fruit> list3; //list3 只接受具有Fruit特征的元素    static List<? super Fruit> list4;   //列表的处理下界是Fruit    static void assign1(List list) {        list1 = list;        list2 = list;        list3 = list;   //类型安全warning    }    static void assign2(List<?> list){        list1 = list;        list2 = list;//      list3 = list;   //可能List是符合要求的,但因为编译器始终无法知道其是否正确,所以直接报了编译错误    }    static void assign3(List<? extends Fruit> list) {        list1 = list;        list2 = list;        list3 = list;   // 参数类型的限制保证了参数 的正确//      list.add(new Apple());    }    static void assign4(List<Fruit> list){        list1 = list;        list2 = list;        list3 = list;   // 参数类型的限制保证了参数 的正确    }    static void assign5(List<? super Apple> list){        list.add(new Apple());    }    public static void main(String[] args) {        assign1(new ArrayList());        assign2(new ArrayList());        assign3(new ArrayList());        assign1(new ArrayList<String>());        assign2(new ArrayList<String>());//      assign3(new ArrayList<String>());        List<?> wildList = new ArrayList();        wildList = new ArrayList<String>();        assign1(wildList);        assign2(wildList);//      assign3(wildList);        /*         * static List<? extends Fruit> list3; //list3 只接受具有Fruit特征的元素         * 这里报编译错误?         * 这是一个与常识有所违背的:list3存储的是具有Fruit特征的元素,但是我们不能向List写入继承与Fruit类的Apple对象         * 解:List<? extends Fruit> 意味着:具有任何从Fruit继承的类型的列表。当一个List<Fruit>列表向上转型为List<? extends Fruit>,它将失去向列表传递对象的能力。         *          * 应用,一个List<? extends Fruit>的列表居然不能让我们传递具体对象,有什么用呢?         * 1、作为一种方法的参数来处理。以List<? extends Fruit>为参数,方法可以接受ArrayList<Apple>或ArrayList<Orange>。         *  假如方法参数是List<Fruit>,那么其只能接受ArrayList<Fruit>的参数类型         *          *          *          */        list3 = new ArrayList<Apple>();//      list3.add(new Apple());        List<Fruit> list4 = new ArrayList<Fruit>();        list4.add(new Apple());        list4.add(new Orange());        List<Apple> list5 = new ArrayList<Apple>();        assign3(list5);//      assign4(list5);        /*         * 超类型通配符         * List<? super Fruit>编译器会反应到这个集合处理的必需是一个Fruit,         * 如:Apple继承于Fruit,这个变量是不会接受ArrayList<Apple>。因为List<? super Fruit>表示,?的类类型在继承体系中必需高于Fruit。Apple是继承于Fruit,明显是低于Fruit         *///      list4 = new ArrayList<Apple>();        assign5(new ArrayList<Apple>());        assign5(new ArrayList<Fruit>());        /*         * 同上分析:         * List<? extend Fruit>具有任何从Fruit继承的类型的列表。         * 相对于List<? super Fruit>而言,extend关键字表达的意思是:?的类类型在继承体系中必需低于Fruit。所以List<? extend Fruit> l  = new ArrayList<Apple>()是合法的。         * 为什么List<? extend Fruit>不能够传递任何Apple、Fruit的对象进去呢?         * 这与泛型的安全有关,因为编译器至此都无法知道List拥有的是什么类型,所以往这样的list放置对象编译器是不允许的(尽管感觉上没有任何问题),但是相反,从这样的集合获取一个Fruit是允许的,         * 因为编译器知道集合里面的对象起码是一个Fruit。         */        System.out.println("finish");    }}

参考资料:《Java编程思想》p389-p396

0 0