List<? extends Number> arr = Arrays.asList(1,2,3.1f,4.1d);
问题在于,list 变量并没有准确的类型,初始化的参数的类型也是不确定的,这样的不明确的代码为什么可以通过编译。
1
sbdx 2021-03-25 15:40:30 +08:00 2
编译器猜的
|
2
Jooooooooo 2021-03-25 15:51:13 +08:00
不都是 Number 吗?
List 可以装 Number. |
3
faust24601 2021-03-25 15:54:48 +08:00 via iPhone
范型协变
|
4
xx6412223 2021-03-25 15:59:15 +08:00
泛型检查,泛型擦除
|
5
xuanbg 2021-03-25 16:00:05 +08:00
extends Number,就是当作 Number 类型处理啊
|
6
CodeCodeStudy 2021-03-25 16:00:45 +08:00
List 里面装的是 Number,1,2,3.1f,4.1d 这些都是 Number
|
7
szuwl OP @CodeCodeStudy @xuanbg @Jooooooooo 这个 `list` 既然装的都是 `Number` 那为什么不允许再插入一个 `Number` 进去, `list.add(Integer.valueOf(1))` 将无法通过编译
|
9
Chengx 2021-03-25 16:09:52 +08:00
|
10
hello2060 2021-03-25 16:11:07 +08:00 via iPhone
实际类型就是 Number 啊,所以这语句没问题。
|
11
X26U68jE5Q6D0ih0 2021-03-25 16:16:44 +08:00
返回的是 Arrays 的内部类 ArrayList, 所以不能 add,remove,clear
|
12
szuwl OP @Chengx 首先产生的是编译期错误 `Required type: capture of ? extends Number,Provided: Integer`,而非运行时错误,你说的是运行时错误,再另说。
|
13
szuwl OP @Chengx @wunaidouzi
```java List<Number> arr = Arrays.asList(1,2,3.1f,4.1d); arr.add(Integer.valueOf(1)); ``` 不会有编译器错误,只是在运行时候才会出现 `UnsupportedOperationException` 异常 |
14
xuanbg 2021-03-25 16:25:17 +08:00
@szuwl 运行时不是 List<Number>,而是 Arrays.asList(1,2,3.1f,4.1d)。这个对象不允许增减操作。
|
15
llej 2021-03-25 16:27:05 +08:00
@szuwl 允许修改的话类型不安全 你可以参见我这个 ts 的例子。父子类所构成的数组并不是父子关系 https://www.typescriptlang.org/zh/play?#code/MYGwhgzhAECC0G8BQ1XTNAvNAjEgvkqJDAELQCmAHgC4UB2AJjPMmtAEZbQBMBR4KNADClWg2ZxEKNMG59CRAPb0INTgC5opANoBdbvuWr1YLbH3cuAemvRAFzaB4Q0Cb8YBnE9NEAhboDztQKJpgHgVAejNtIyQwHQAGA2x6CgB3EQAKAEokJA5IvQA6Gzs3QA1tQAp1QDvUwAyMzkzoP2DRQEKbQEhzTiQgA
|
16
szuwl OP @xuanbg 那我换个表达:
```java List<? extends Number> arr = new ArrayList<Number>(){{ add(1); }}; arr.add(1); //Required type: capture of ? extends Number,Provided: int ``` 这个 ArrayList 可以增减吧,但是第二句依然无法通过编译。 |
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)); 不会编译错误 |
20
Jwyt 2021-03-25 16:36:46 +08:00
|
21
misdake 2021-03-25 16:36:55 +08:00
学一下“协变”
|
22
kuko126 2021-03-25 17:01:32 +08:00
|
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)'
|
24
richardxxx 2021-03-25 18:22:34 +08:00 via Android
extends 能取不能存
super 能存不能取 |
25
CodeCodeStudy 2021-03-25 19:07:53 +08:00
改成 ArrayList<? super Number> arr 就可以了
|
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)); 理解一下这两个的区别, |
27
AoEiuV020 2021-03-25 19:24:00 +08:00
搞错,是 extends 和 super 的区别,看来我也不熟,
|
28
uselessVisitor 2021-03-25 22:54:24 +08:00
1 不是包装类的子类吧,默认是 int 类型
@szuwl |
29
uselessVisitor 2021-03-25 22:56:50 +08:00
@beichenhpy 我理解错了,应该是 super 。。
|
30
uselessVisitor 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)); 我试了一下编译通过了,也没有错误啊。。 |
31
Chengx 2021-03-26 09:17:37 +08:00
@richardxxx 点睛之笔
|
32
geminius2333 2021-03-26 10:16:47 +08:00
Array.asList 方法返回的是 Arrays 的内部类。你要 add 可以 new ArrayList(Arrays.asList(...));
|
33
no1xsyzy 2021-03-26 10:26:32 +08:00
@beichenhpy 你不能 Integer x = listSuper.get(0)
println 允许的范围大得多罢了,super 仍然潜在蕴含了 extends Object |
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 同理。 |
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 。 |
36
w4ngzhen 2021-03-26 14:46:27 +08:00
|