• java泛型-PECS


     1 package com.example.base;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import com.example.spring.MyLog;
     7 /**
     8  * Producer extends Consumer super  生产者使用extends,consumer使用super
     9  * 这里的生产者和消费者是相对容器而言的,
    10  *   生产者只能对外提供数据,不可以写入数据,数据来源于赋值操作(将参数化类型为子类的容器赋值过来)
    11  *   消费者表示只能向容器中写入数据,不能读取(只能以Object来接收)
    12  * 这里的extends和super指的是声明类型和参数化类型的关系,
    13  *    如下所示:等号左侧类型为声明类型,右侧为参数化类型
    14  *    List<? extends Number> intList = new ArrayList<Integer>();
    15  *    private List<? super Number> intList2 = new ArrayList<Number>();
    16  * @DESC 
    17  * @author guchuang
    18  *
    19  */
    20 public class PECS {
    21 
    22     int int1 = 1;
    23     long long1 = 11;
    24     Number number1 = 10;
    25     
    26     private List<Integer> intList = new ArrayList<Integer>();
    27     private List<Long> longList = new ArrayList<Long>();
    28     private List<Number> numberList = new ArrayList<Number>();
    29     
    30     public static void main(String[] args) {
    31         PECS pecs = new PECS();
    32         pecs.pe();
    33         pecs.cs();
    34     }
    35     
    36     /**
    37      * <? extends Number>  这种方式声明的泛型容器,不能写入任何类型的数据,只能读取数据
    38      * 其指定了上确界为Number,参数化类型(如:实际新建的容器类型T new ArrayList<T>())必须是Number的子类,所以读出的数据都可以上转型为Number
    39      * 理论含义是容器内包含的数据可能是Number的任何一种子类,所以无法添加数据。
    40      * 写数据的方式:
    41      *    声明一个具体类型(Number的子类型)的容器,向其中添加数据,将这个容器赋值给numbers容器
    42      * 优势:
    43      *    避免调用者向此容器内写入数据,只能读取里面的数据
    44      */
    45     public void pe() {
    46         //<? extends Number>  这种方式声明的泛型容器,不能写入任何类型的数据
    47         List<? extends Number> numbers = new ArrayList<Number>();
    48         //下面三种添加数据都会导致编译报错
    49         //foo.add(int1);
    50         //foo.add(long1);
    51         //foo.add(number1);
    52         
    53         //Number number = numbers.get(0);
    54         
    55         intList.add(123);
    56         intList.add(456);
    57         //将新创建的具有确定类型的容器(必须是Number的子类型)赋值给numbers,起到生产数据的目的
    58         numbers = intList;      //新容器的参数化类型是Integer,是Number的子类,所以可以赋值
    59         MyLog.info(numbers);
    60         Number number = numbers.get(0);    //读出来的类型依然是Number
    61         MyLog.info("read from ? extends Number: " + number);
    62         numbers = longList;
    63         numbers = numberList;
    64     }
    65     
    66     /**
    67      * Consumer super
    68      * ? super Number 表示容器中所有的数据类型都是Number或者Number的超类型,
    69      *  所以Number及其子类型(可以上转型为Number)可以写入,读取的时候由于不能确定类型,只能使用Object接收
    70      */
    71     public void cs() {
    72         List<? super Number> numbers = new ArrayList<Number>();
    73         numbers.add(int1);
    74         numbers.add(long1);
    75         numbers.add(number1);
    76         //numbers.add(new Object());    编译报错
    77         MyLog.info(numbers);
    78         
    79         //Number n = numbers.get(0);    编译报错
    80         Object n = numbers.get(0);      //只能以Object来接收数据
    81         //numbers = intList;    编译报错
    82         numbers = numberList;
    83         numbers = new ArrayList<Object>();
    84     }
    85 }
  • 相关阅读:
    【LOJ#10027】魔板
    【LOJ#2653】山峰和山谷
    【POJ2449】第k短路
    【HAOI2008】移动玩具
    【洛谷P1379】八数码难题
    【NOIP2002】字串变换
    【CH2501】矩阵距离
    【CH2601】电路维修
    【NOIP2009】靶形数独
    树的子结构
  • 原文地址:https://www.cnblogs.com/gc65/p/11183659.html
Copyright © 2020-2023  润新知