当前位置: 首页 > 知识库问答 >
问题:

将实现接口的泛型列表分配给相同接口的列表

袁宜
2023-03-14

这个问题是关于接口与实现该接口的类之间的关系。我看不出这个或这个如何回答这个问题。

我创建了一个接口boxed和一个抽象泛型类box,它实现了该接口。然后创建两个具体的类IntegerBoxStringBox。然后创建了一个元素列表,这些元素使用一个IntegerBox值和一个StringBox值扩展了Box。到目前为止还不错。

现在我要分配list<?将box>扩展为列表 。我的期望是,这应该是有效的,因为无论什么扩展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
  }
}

共有1个答案

秦鸿羽
2023-03-14

请考虑以下问题:

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 。那就糟了。

这就是编译器正在防止的。

绕过这个问题很简单

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 是List 的子类吗?为什么Java泛型不是隐式多态的?涵盖了这一点,只是不是 的直接情况?extends。)

 类似资料:
  • 问题内容: 假设我有一个域类: 其中Animal是具有不同实现(Cat,Dog)的接口。假设我希望能够保存Zoo对象: 我想发送一个json-类似: 我如何告诉Spring MVC在type ==’Cat’时将动物映射到Cat类型,在type ==’Dog’时将其映射到Dog类? 问题答案: 您应该使用Jackson注释并实现多态json。注释在基类上。

  • 假设我有一个域类: 其中动物是具有不同实现的接口(猫、狗)。假设我希望能够保存一个动物园对象:

  • 问题内容: 好的,这是我的问题: 我有一个包含interfaces的列表-和扩展该接口的接口的列表:。我要设置。我不希望使用任何东西或会花费更多内存的东西,因为我正在做的事情已经非常耗费成本。我确实需要能够说。我已经尝试过,但是后来我无法将接口添加到列表中,只能将SubInterfaces 添加到列表中。有什么建议? 我希望能够做这样的事情: RecordKeeper类是包含接口列表的类(NOT

  • 问题内容: 假设我有一个域类: 其中Animal是具有不同实现(Cat,Dog)的接口。假设我希望能够保存Zoo对象: 我想发送一个json-类似: 我如何告诉Spring MVC在type ==’Cat’时将动物映射到Cat类型,并在type ==’Dog’时将其映射到Dog类? 问题答案: 你应该使用Jackson注释并实现多态json。注释在基类上。

  • 问题内容: 我有以下接口,我想在类中多次实现: 现在,我希望能够通过以下方式实现此接口: 但是,这给了我错误:在行上: 是否可以使用不同的泛型两次实现接口?如果不是,那么我在这里可以做的下一步工作是什么? 问题答案: 您需要使用内部或匿名类。例如:

  • 问题内容: 我有一个关于将子类列表分配给超类列表的基本问题。 所以我有以下内容: 为什么最后一次分配失败?对不起,新手问题 问题答案: 为了解释这一点,让我用整数代替“ B”,用数字代替“ A”。这只是为了使其更容易解释。 失败的原因是因为nList可以采用任何Number;可以采用Integer;可以采用Double;或者就此而言,可以是Number的任何子类。但是,对于iList并非如此。您不