zoukankan      html  css  js  c++  java
  • 泛型(4)-泛型通配符的上限


      当直接使用List<?>这种形式时,即表明这个List集合可以是任何泛型List的父类,但还有一种特殊的情况,程序不希望这个List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,考虑到一个简单的绘图程序.
    示例代码.
    package com.j1803.Type_wildcards;

    public abstract class Shape {
    public abstract void showInfo();
    public abstract void draw(Canvas canvas);
    }

    class Circle extends Shape{
    @Override
    public void draw(Canvas canvas) {
    System.out.println("..............正在画圆形................");

    }

    @Override
    public void showInfo() {
    System.out.println("..............正在画圆形");
    }
    }
    class Rectangle extends Shape{
    @Override
    public void draw(Canvas canvas) {
    System.out.println("...............正在画矩形........................");

    }

    @Override
    public void showInfo() {
    System.out.println("...............正在画矩形");
    }
    }
    class Triangle extends Shape{
    @Override
    public void draw(Canvas canvas) {
    System.out.println("...............正在画三角形..........................");


    }

    @Override
    public void showInfo() {
    System.out.println("...............正在画三角形");
    }
    }


    package com.j1803.Type_wildcards;

    import java.util.ArrayList;
    import java.util.List;

    public class Canvas {
    //遍历集合中的所有元素
    public void shoInfo(List<?> list){
    System.out.println("===");
    for(int i=0;i<list.size();i++){
    System.out.println(list.get(i));
    if(list.get(i).getClass().equals(new Circle().getClass())){
    System.out.println(list.get(i).getClass());
    Circle circle=(Circle)list.get(i);
    circle.showInfo();
    }
    }
    }

    //同时在画布上绘制多个形状
    public void drawAll(List<Shape>list){
    System.out.println("List<Shape>list");
    for(Shape shape:list){
    shape.draw(this);
    }
    }

    //同时在画布上绘制多个形状1
    public void drawAll1(List<? extends Shape> list){
    System.out.println("List<? extends Shape>");
    for(Shape shape:list){
    shape.draw(this);
    }

    }
    public static void main(String[] args) {
    Canvas canvas=new Canvas();
    List<Shape>list=new ArrayList<>();
    list.add(new Circle());
    list.add(new Rectangle());
    list.add(new Triangle());
    canvas.shoInfo(list);

    System.out.println("********************************************************");
    List<Circle>circles=new ArrayList<>();
    circles.add(new Circle());
    //circles.add(new Triangle());//编译错误
    canvas.shoInfo(circles);

    System.out.println("********************************************************");
    canvas.drawAll(list);

    System.out.println("********************************************************");
    canvas.drawAll1(circles);



    }
    }
    关键在于List<Cirlce>并不是List<Shape>的子类,所以不能把List<Circle>对象当成List<Shape>使用,为了表示List<Circle>的父类,可以考虑使用List<?>,但同时从List<?>集合取出的元素只能被编译器当成Object处理,
    为了表示List集合的所有元素是Shape的子类,Java泛型提供了被限制的泛型通配符,被限制的泛型通配符表示如下:
    List<? extends Shape>//它表示泛型形参必须是Shape子类的List.
    List<Circle>对象当成List<? extends Shape>使用.即List<? extends Shape>可以表示List<Circle>,List<Rectangle>的父类,只要List后尖括号里面的类型是Shape的子类就可以了.
    List<? extends Shape>是受到限制的通配符的例子,此处的问号(?)代表一个未知的类型,就像前面看到的通配符一样,但是此处的这个未知类型一定是Shape的子类型(也可以是Shape本身),因此可以把Shape称为这个通配符的上限.
    类似的,由于程序无法确定这个受限的通配符的具体类型,所以不能把Shape对象或者其子类的对象加入这个泛型集合中,
    public class Demo2 {

    public void add(list<? extends Shape> shape){
    shape.add(0,new Rectangle());
    }

    与使用普通方法相似的是,shape.add()的第二个参数类型是? extends Shape,它表示Shape未知的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中.
    简而言之,这种指定通配符上限的集合,只能从集合中取出元素(取出的元素总是上限的类型),不能向集合中添加元素(因为编译器无法确定集合元素实际是哪一种子类型).
    对于更广泛的泛型类来说,指定通配符上限,局势为了支持类型新编,比如Foo是Bar类型的子类,这样A<Bar>就相当于A<? extends Foo>的子类,可以把A<Bar>赋值给A<? extends Foo>类型的变量,这种型变方式称为协变
    对于协变的泛型类来说,它只能调用泛型类型作为返回值类型的方法(编辑器会将该方法返回值当成通配符上限的类型);而不能调用泛型类型作为参数的方法,口诀是:协变只进不出.
    对于指定了通配符上限的泛型类,相当于通配符上限是Object




  • 相关阅读:
    elk工作原理
    nginx 引入外部文件
    3.1.2 视图实例演示-登录页面
    通信架构
    JAX-WS HandlerChain使用详解
    改变规则可以,前提是得有本事——北漂18年(64)
    An internal error occurred during:"Update Installed JREs".java.lang.NullPointerException
    jquery.mobile-1.4.5.min.js:3 Uncaught TypeError: Cannot set property 'mobile' of undefined
    大数据时代,百货行业信息化将如何变革?
    17.2?Replication Implementation 复制实施:
  • 原文地址:https://www.cnblogs.com/shadow-shine/p/9656536.html
Copyright © 2011-2022 走看看