• 请不要在回答技术问题时复制粘贴 AI 生成的内容
szuwl
V2EX  ›  程序员

怎样理解下面这段代码

  •  
  •   szuwl · Mar 25, 2021 · 5452 views
    This topic created in 2052 days ago, the information mentioned may be changed or developed.
    List<? extends Number> arr = Arrays.asList(1,2,3.1f,4.1d);
    

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

    Supplement 1  ·  Mar 25, 2021
    让我困惑的就是 java 不允许 List<? extends Number> arr 中添加元素,但是却允许使用元素初始化 arr 。
    ```java
    List<? extends Number> arr = new ArrayList<Number>(){{ add(1); }};
    ```
    36 replies  •  2021-03-26 14:46:27 +08:00
    sbdx
    sbdx
    Mar 25, 2021❤️2
    1
    编译器猜的
    Jooooooooo
    Jooooooooo
    Mar 25, 2021
    2
    不都是 Number 吗?

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

    1. List<? extends/ super T> 而不是 List<T>,目的就是限定只能 add/get
    2. ? extends T 这种形式,因为父类无法强转为子类,但子类可以强转为父类;在只有明确上界 T 的 i 情况下,无法 add,只能 get 。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2177 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 63ms · UTC 12:51 · PVG 20:51 · LAX 04:51 · JFK 07:51
    ♥ Do have faith in what you're doing.