List<? extends Number> arr = Arrays.asList(1,2,3.1f,4.1d);
问题在于,list 变量并没有准确的类型,初始化的参数的类型也是不确定的,这样的不明确的代码为什么可以通过编译。
![]() | 1 sbdx 2021-03-25 15:40:30 +08:00 ![]() 编译器猜的 |
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 Dockerfile 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 zm8m93Q1e5otOC69 2021-03-25 22:54:24 +08:00 1 不是包装类的子类吧,默认是 int 类型 @szuwl |
29 zm8m93Q1e5otOC69 2021-03-25 22:56:50 +08:00 @beichenhpy 我理解错了,应该是 super 。。 |
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)); 我试了一下编译通过了,也没有错误啊。。 |
![]() | 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 |