Java泛型:通配符

通配符是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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值