通配符的继承关系

通配符

  在类表达式中<? extends ClassName > ?就表示通配符,Object表示通配符的上界。所谓上界就表示?只能代表ClassNamet的子类或者它自己,不能是父类。

通配符的继承关系

  我们先看一个简单的继承层次

class Father{
    private int first;
    public Father(){}
    public  void spack(String s){
        System.out.println("Father Spack "+ s);
    }
}
class Child extends Father{
    public void spack(String s){
        System.out.println("Child Spack "+ s);
    }
}
class Grandson extends Child{
    public void spack(String s){
        System.out.println("Grandson Spack " +s);
    }
}


  我们知道<? extends ClassName >可以代表ClassName和它的子类。现在初始化List数组list:

List<? extends Father> list = new ArrayList<>();

  理论上list代表的Father类和它的子类Child,list可以是List<Father>,也可以是List<Child>。所以list可以添加Father对象也可以添加Child对象是吧?但是呢,你用list.add()添加元素时却会发现编译错误。为什么呢?我们分析一下 :
  现在假设可以在list中添加元素,那么下面这个方法也一定也执行。

public void testAdd(List<? extends Father> list){
        list.add(new Father());
        list.add(new Child()));
    }

  当你将类型为List<Child>的参数传入,理论是是可以编译的,因为Child对象实际类型也可以是Father,当然可以添加到list啦。然后当你将类型为List<Child>的传进去时就会发现在第一行lList<Child>ist.add(new Father());理论上会报错的,因为List<Child>肯定只能添加Child对象而不能添加Father对象啊。子类可以指向父类,但父类不能指向子类呀,你的iphone X一定是手机,但是你不能说你的手机一定是iphone X吧。那有人说了,那我把第一行 list.add(new Father());删了不久成立了吗?但你你的参数类型为List<? extends Facher既可以代表List<Child>也可以代表List<Father>,既然只想将Child的对象添加进去那为什么还要在写个List<? extends Father>呢?多此一举。直接改成List<Child>好了,就与“list代表的Father类和它的子类Child”这句话相违背。
  总结一下。编译器不允许List<? extends Father>类型的List变量add()添加任何非null元素,但是允许添加null。为什么呢?因为List<? extends Father>中元素的不确定性,为了保护其类型的一致性不允许add()添加非null元素。
  既然List<? extends Father> list不能添加元素,那么怎么才能解决这个问题呢?通配符除了上界,还有下界的表达式<? super FatherClass>表示可以代表子类还能代表子类的父类。于上面的相反。

 public void tset(){
         List<? super Father> list = new ArrayList<>();
         list.add(new Father());
         list.add(new Child());
         list.add(new Grandson());

         for(int i=0;i<list.size();i++){
             Facher f = (Father)list.get(i);
             f.spack(f.getClass().toString());
         }

    }

  输出结果:

Father Spack class Generic.Father
Child Spack class Generic.Child
Grandson Spack class Generic.Grandson

  变量list是可以添加Facher对象和它的子类的。? super Father 为超类型限制。它代表的是它和它的超类。现在list只能存Father对象和它的超类对吧,所以Father的所有子类都可以添加,因为子类指向父类,子类的类型也可以是父类。

  总结:通配符的上界我们可以发现:当规定上界,在继承层次中它的最高为Father,但不知道下界,所以可能出线父类指向子类的情况。当规定下界时他在继承层次中最低也是Father了。不能可能存在父类指向子类的情况了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值