3

我对 java 还很陌生,没有太多使用接口,这是我想象的一个非常基本的问题。

我定义了一个接口,一个扩展它的第二个接口,然后是一个实现第二个接口的类:

public interface I1 {
  public void doStuff();
}

public interface I2 extends I1 {
  public void doMoreStuff();
}

public class C2 implements I2 {
  public void doStuff(){
    // implements I1 as required
  }
  public void doMoreStuff(){
    // implements I1 as required
  }
}

然后我想调用一个方法,该方法具有一个实现接口 I1 的对象集合作为参数:

public class C3 {
   public static void doI1Stuff(List<I1> implementorsOfI1){
      // code here
   }
}

但是当我尝试类似的东西时出现上述错误

C2 aC2 = new C2();
List c2L = new List<I2>();
c2L.add(aC2);
C3.doI1Stuff(c2L);

作为一个java新手,我所做的对我来说似乎是合理的。为什么它不起作用,更有经验的程序员会怎么做?我希望我在某个地方犯了一个非常简单的错误,这实际上是可能的......

(修改后的问题:如果我正在处理单个 C2 对象,但不是它们的集合,它可以工作(如回复所述)......)

4

1 回答 1

2

更新

哎呀,你的 c2L 是一个List,而不是一个 List`。这应该可以编译——它对其他评论的人也是如此——尽管出于我在下面描述的相同原因它是危险的。我暂时将这个答案留在这里,但如果我发现它没有用,我可以将其删除


 public static void doI1Stuff(List<I1> implementorsOfI1)
 ...
 C3.doI1Stuff(c2L);

doI1Stuff期望 aList<I1>但您传递的 aList<I2>是不允许的。听起来很奇怪,“一袋苹果不是一袋水果”。原因是您可以将任何水果放入一袋水果中,例如香蕉,但您不能用一袋苹果这样做。

为了把它联系起来,你的例子考虑还有一个class C1 extends I1. doI1Stuff可以添加一个C3参数,打破合同。意识到您的参数命名错误可能会澄清,它应该是listOfImplementorsOfT1.

解决问题的一种方法是将声明更改为

 public static void doI1Stuff(List<? extends I1> implementorsOfI1)

这表示参数是一些未知类型的列表extends I1List<I2>, List<C2>,List<C1>都满足满足约束。使用此声明,该方法无法向该列表添加任何内容,因为它不知道该类型是什么。

于 2013-07-31T23:11:16.813 回答