Java泛型:通配符

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

package com.qpm.learn.base;

import java.util.*;

/**   
 * @ClassName: UnboundedWildcards1    
 * @Description: TODO    Java泛型学习
 * @author kangqiang.w [email protected]    
 * @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 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());
        assign2(new ArrayList());
//      assign3(new ArrayList());

        List> wildList = new ArrayList();
        wildList = new ArrayList();

        assign1(wildList);
        assign2(wildList);
//      assign3(wildList);

        /*
         * static List extends Fruit> list3; //list3 只接受具有Fruit特征的元素
         * 这里报编译错误?
         * 这是一个与常识有所违背的:list3存储的是具有Fruit特征的元素,但是我们不能向List写入继承与Fruit类的Apple对象
         * 解:List extends Fruit> 意味着:具有任何从Fruit继承的类型的列表。当一个List列表向上转型为List extends Fruit>,它将失去向列表传递对象的能力。
         * 
         * 应用,一个List extends Fruit>的列表居然不能让我们传递具体对象,有什么用呢?
         * 1、作为一种方法的参数来处理。以List extends Fruit>为参数,方法可以接受ArrayList或ArrayList。
         *  假如方法参数是List,那么其只能接受ArrayList的参数类型
         * 
         * 
         * 
         */
        list3 = new ArrayList();
//      list3.add(new Apple());

        List list4 = new ArrayList();
        list4.add(new Apple());
        list4.add(new Orange());

        List list5 = new ArrayList();
        assign3(list5);
//      assign4(list5);


        /*
         * 超类型通配符
         * List super Fruit>编译器会反应到这个集合处理的必需是一个Fruit,
         * 如:Apple继承于Fruit,这个变量是不会接受ArrayList。因为List super Fruit>表示,?的类类型在继承体系中必需高于Fruit。Apple是继承于Fruit,明显是低于Fruit
         */
//      list4 = new ArrayList();
        assign5(new ArrayList());
        assign5(new ArrayList());


        /*
         * 同上分析:
         * List extend Fruit>具有任何从Fruit继承的类型的列表。
         * 相对于List super Fruit>而言,extend关键字表达的意思是:?的类类型在继承体系中必需低于Fruit。所以List extend Fruit> l  = new ArrayList()是合法的。
         * 为什么List extend Fruit>不能够传递任何Apple、Fruit的对象进去呢?
         * 这与泛型的安全有关,因为编译器至此都无法知道List拥有的是什么类型,所以往这样的list放置对象编译器是不允许的(尽管感觉上没有任何问题),但是相反,从这样的集合获取一个Fruit是允许的,
         * 因为编译器知道集合里面的对象起码是一个Fruit。
         */
        System.out.println("finish");
    }

}

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

你可能感兴趣的:(Java,java,泛型)