通配符的继承关系

来源:互联网 发布:淘宝云客服工资怎么算 编辑:程序博客网 时间:2024/06/03 14:58

通配符

  在类表达式中<? 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.FatherChild Spack class Generic.ChildGrandson Spack class Generic.Grandson

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

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

原创粉丝点击