java - 将实现接口的泛型列表分配给相同接口的列表
问题描述
这个问题是关于接口与实现接口的类的关系。我看不出这个或这个如何回答这个问题。
我创建了一个接口Boxed
和一个实现该接口的抽象泛型类Box
。然后我创建了两个具体的类IntegerBox
和StringBox
. 然后我创建了一个元素列表,其中Box
包含一个IntegerBox
值和一个StringBox
值。到目前为止,一切都很好。
现在我想分配List<? extends Box>
给List<Boxed>
. 我的期望是,这应该是有效的,因为任何扩展都可以Box
实现Boxed
。但是编译器不允许我。这是错误:
main.java:29: error: incompatible types: List<CAP#1> cannot be converted to List<Boxed>
List<Boxed> lb2 = laeb; // does not compile, although every value which extends Box implements Boxed
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Box from capture of ? extends Box
1 error
我可以复制列表:
List<? extends Box> laeb = List.of (new IntegerBox(42), new StringBox("answer"));
List<Boxed> lb1 = new ArrayList<> (laeb);
如果类型为,则类型的每个元素? extends Box
都用于创建一个值Boxed
。但是分配报告了不兼容的类型。为什么?
import java.util.List;
import java.util.ArrayList;
public class main
{
static interface Boxed { }
static abstract class Box<T> implements Boxed
{
T content;
Box (T content) { this.content = content; }
}
static class IntegerBox extends Box<Integer> { IntegerBox (Integer content) { super (content); } }
static class StringBox extends Box<String> { StringBox (String content) { super (content); } }
public static void main (String ...arguments) throws Exception
{
IntegerBox i = new IntegerBox(42);
StringBox s = new StringBox("answer");
List<? extends Box> laeb = List.of (i, s);
Boxed b0 = i; // => IntegerBox is compatible with Boxed
Boxed b1 = s; // => StringBox is compatible with Boxed
List<Boxed> lb1 = new ArrayList<> (laeb); // List<Boxed> can be created by values of "? extends Box"
List<Boxed> lb2 = laeb; // does not compile, although every value which extends Box implements Boxed
}
}
解决方案
考虑一下:
List<StringBox> stringBoxList = new ArrayList<StringBox>();
List<? extends Box> boxList = stringBoxList; // works, StringBox extends Box
List<Boxed> boxedList = boxList; // suppose this *did* work
boxedList.add(new IntegerBox(42)); // this line definitely compiles, what does it do?
在最后一行之后,stringBoxList
将包含一个IntegerBox
,尽管最初是一个ArrayList<StringBox>
. 那很糟。
这就是编译器正在阻止的。
要解决这个问题很简单
List<? extends Boxed> boxedList = boxList;
boxedList.add(new IntegerBox(42));
// forbidden by the compiler, because IntegerBox is not necessarily the _same_ subclass
// of Boxed as boxedList's elements
或者,或者,你可以写
List<Boxed> boxedList = Collections.unmodifiableList(boxList);
...因为如果您无法修改列表,问题就会消失。
(但是,坦率地说,List<Dog> 是 List<Animal> 的子类吗?为什么 Java 泛型不是隐式多态的?涵盖了这一点,而不是 . 的直接情况? extends
。)
推荐阅读
- jquery - Auto Complete TextBox Using ASP.NET jQuery AJAX call paste not working 如果不使用自动完成,则必须键入每个字母
- math - 如何在 <=25 的机会中找到列表(列表 50 的长度)中随机数的索引?
- java - 为什么jpa manyToOnelazy fetch不可用,还是导致无用的关联查询
- c# - 如何像在纸 io 中一样填写选择?
- r - Shiny:没有数据时如何禁用下载按钮?
- kotlin - Android Jetpack Compose NumberPicker 小部件等效
- couchbase - 如何使用 RAW MAX 制作 CouchBase 子查询,执行速度更快
- java - 在特定包中生成 AVRO 类
- laravel - Laravel Nginx 全栈的 CORS 策略阻止
- vue.js - SCSS:用@use替换作用域@import