怎样理解下面这段代码 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
szuwl
V2EX    程序员

怎样理解下面这段代码

  •  
  •   szuwl 2021-03-25 15:22:43 +08:00 4403 次点击
    这是一个创建于 1661 天前的主题,其中的信息可能已经有所发展或是发生改变。
    List<? extends Number> arr = Arrays.asList(1,2,3.1f,4.1d); 

    问题在于,list 变量并没有准确的类型,初始化的参数的类型也是不确定的,这样的不明确的代码为什么可以通过编译。

    第 1 条附言    2021-03-25 16:34:24 +08:00
    让我困惑的就是 java 不允许 List<? extends Number> arr 中添加元素,但是却允许使用元素初始化 arr 。
    ```java
    List<? extends Number> arr = new ArrayList<Number>(){{ add(1); }};
    ```
    36 条回复    2021-03-26 14:46:27 +08:00
    sbdx
        1
    sbdx  
       2021-03-25 15:40:30 +08:00   2
    编译器猜的
    Jooooooooo
        2
    Jooooooooo  
       2021-03-25 15:51:13 +08:00
    不都是 Number 吗?

    List 可以装 Number.
    faust24601
        3
    faust24601  
       2021-03-25 15:54:48 +08:00 via iPhone
    范型协变
    xx6412223
        4
    xx6412223  
       2021-03-25 15:59:15 +08:00
    泛型检查,泛型擦除
    xuanbg
        5
    xuanbg  
       2021-03-25 16:00:05 +08:00
    extends Number,就是当作 Number 类型处理啊
    CodeCodeStudy
        6
    CodeCodeStudy  
       2021-03-25 16:00:45 +08:00
    List 里面装的是 Number,1,2,3.1f,4.1d 这些都是 Number
    szuwl
        7
    szuwl  
    OP
       2021-03-25 16:08:11 +08:00
    @CodeCodeStudy @xuanbg @Jooooooooo 这个 `list` 既然装的都是 `Number` 那为什么不允许再插入一个 `Number` 进去, `list.add(Integer.valueOf(1))` 将无法通过编译
    Chengx
        8
    Chengx  
       2021-03-25 16:09:15 +08:00
    @szuwl Arrays.asList 不可修改
    Chengx
        9
    Chengx  
       2021-03-25 16:09:52 +08:00
    @Chengx
    Arrays.asList 返回长度固定的 List
    支持 set 修改元素值
    不支持 add, remove, clear
    hello2060
        10
    hello2060  
       2021-03-25 16:11:07 +08:00 via iPhone
    实际类型就是 Number 啊,所以这语句没问题。
    X26U68jE5Q6D0ih0
        11
    X26U68jE5Q6D0ih0  
       2021-03-25 16:16:44 +08:00
    返回的是 Arrays 的内部类 ArrayList, 所以不能 add,remove,clear
    szuwl
        12
    szuwl  
    OP
       2021-03-25 16:17:06 +08:00
    @Chengx 首先产生的是编译期错误 `Required type: capture of ? extends Number,Provided: Integer`,而非运行时错误,你说的是运行时错误,再另说。
    szuwl
        13
    szuwl  
    OP
       2021-03-25 16:18:51 +08:00
    @Chengx @wunaidouzi
    ```java
    List<Number> arr = Arrays.asList(1,2,3.1f,4.1d);
    arr.add(Integer.valueOf(1));
    ```
    不会有编译器错误,只是在运行时候才会出现 `UnsupportedOperationException` 异常
    xuanbg
        14
    xuanbg  
       2021-03-25 16:25:17 +08:00
    @szuwl 运行时不是 List<Number>,而是 Arrays.asList(1,2,3.1f,4.1d)。这个对象不允许增减操作。
    szuwl
        16
    szuwl  
    OP
       2021-03-25 16:30:12 +08:00
    @xuanbg 那我换个表达:
    ```java
    List<? extends Number> arr = new ArrayList<Number>(){{ add(1); }};
    arr.add(1); //Required type: capture of ? extends Number,Provided: int
    ```
    这个 ArrayList 可以增减吧,但是第二句依然无法通过编译。
    kuko126
        17
    kuko126  
       2021-03-25 16:32:57 +08:00
    List<? super Number> arr = Arrays.asList(1,2,3.1f,4.1d);
    arr.add(Integer.valueOf(1));
    不会编译错误
    ipwx
        18
    ipwx  
       2021-03-25 16:35:43 +08:00
    @szuwl int != Integer
    szuwl
        19
    szuwl  
    OP
       2021-03-25 16:35:58 +08:00
    @kuko126 问的是 extends 并非 super
    Dockerfile
        20
    Dockerfile  
       2021-03-25 16:36:46 +08:00
    misdake
        21
    misdake  
       2021-03-25 16:36:55 +08:00
    学一下“协变”
    xuanbg
        23
    xuanbg  
       2021-03-25 17:25:55 +08:00
    @szuwl 'add(capture<? extends java.lang.Number>)' in 'java.util.List' cannot be applied to '(int)'
    richardxxx
        24
    richardxxx  
       2021-03-25 18:22:34 +08:00 via Android
    extends 能取不能存
    super 能存不能取
    CodeCodeStudy
        25
    CodeCodeStudy  
       2021-03-25 19:07:53 +08:00
    改成 ArrayList<? super Number> arr 就可以了
    AoEiuV020
        26
    AoEiuV020  
       2021-03-25 19:20:30 +08:00
    List<? extends Number> arr = Arrays.asList(1,2,3.1f,4.1d);
    List<? extends Number> arr = new ArrayList(Arrays.asList(1,2,3.1f,4.1d));
    理解一下这两个的区别,
    AoEiuV020
        27
    AoEiuV020  
       2021-03-25 19:24:00 +08:00
    搞错,是 extends 和 super 的区别,看来我也不熟,
    zm8m93Q1e5otOC69
        28
    zm8m93Q1e5otOC69  
       2021-03-25 22:54:24 +08:00
    1 不是包装类的子类吧,默认是 int 类型
    @szuwl
    zm8m93Q1e5otOC69
        29
    zm8m93Q1e5otOC69  
       2021-03-25 22:56:50 +08:00
    @beichenhpy 我理解错了,应该是 super 。。
    zm8m93Q1e5otOC69
        30
    zm8m93Q1e5otOC69  
       2021-03-25 23:57:19 +08:00
    逆变不能 get 吗?
    List<? super Integer> listSuper = new ArrayList<Number>();
    listSuper.add(1);
    System.out.println(listSuper.get(0));
    我试了一下编译通过了,也没有错误啊。。
    Chengx
        31
    Chengx  
       2021-03-26 09:17:37 +08:00
    @richardxxx 点睛之笔
    geminius2333
        32
    geminius2333  
       2021-03-26 10:16:47 +08:00
    Array.asList 方法返回的是 Arrays 的内部类。你要 add 可以 new ArrayList(Arrays.asList(...));
    no1xsyzy
        33
    no1xsyzy  
       2021-03-26 10:26:32 +08:00
    @beichenhpy 你不能 Integer x = listSuper.get(0)
    println 允许的范围大得多罢了,super 仍然潜在蕴含了 extends Object
    Bronya
        34
    Bronya  
       2021-03-26 10:33:27 +08:00
    本人拙见:
    初始化的时候已经确定了值都是 Number,因此允许初始化。
    但是添加的时候,`List<? extend Number>`并不知道到引用的哪一个子类,规定上界之后`List<? extend Number> = List<Integer> 和 List<? extend Number> = List<Double>`都是成立的,如果可以添加的话会造成`List<Integer>中添加了 Double 类型`,类似这样的代码:

    ```
    List<Integer> intList = new ArrayList<>();
    List<? extends Number> numList = intList;
    numList.add(0.1);//如果允许添加
    Integer integer = intList.get(0);//会造成 intList 存储了 Double
    ```

    因此规定上界(协变?)的时候能取不能存。
    super 同理。
    acr0ss
        35
    acr0ss  
       2021-03-26 14:24:43 +08:00
    List<? extends/ super T> 这个也曾困扰我,目前我的理解是。

    1. List<? extends/ super T> 而不是 List<T>,目的就是限定只能 add/get
    2. ? extends T 这种形式,因为父类无法强转为子类,但子类可以强转为父类;在只有明确上界 T 的 i 情况下,无法 add,只能 get 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2613 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 06:18 PVG 14:18 LAX 23:18 JFK 02:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86