1

跟进这个问题,但我会尽量让它自成一体。

假设我有一个名为 的接口Animal,由于各种原因,它有一个表示实现类的泛型类型参数:

public interface Animal<A extends Animal<A>>

我还有一个子接口 ,Dinosaur它的行为方式相同:

public interface Dinosaur<D extends Dinosaur<D>> extends Animal<D>

现在我有一个Lizard实现的类Animal

public class Lizard implements Animal<Lizard>

和一个子类Trex,它实现Dinosaur

public class Trex extends Lizard implements Dinosaur<Trex>

这四个声明现在产生错误。这是因为该类Trex实现了接口Animal两次,但使用了不同的类型参数:因为它 extends Lizard,它实现了 interface Animal<Lizard>,并且因为它 implements Dinosaur<Trex>,它实现了Animal<Trex>

Animal<Trex>不是 的子接口Animal<Lizard>,即使Trex是 的子类Lizard,所以我们得到编译器错误。

我确信使用通配符可以解决这个问题,但我无法弄清楚它是什么。

您可以编译以下内容以获得相同的错误:

public class InterfaceTest
{
  private interface Animal<A extends Animal<A>> {}

  private interface Dinosaur<D extends Dinosaur<D>> extends Animal<D> {}

  private class Lizard implements Animal<Lizard> {}

  private class Trex extends Lizard implements Dinosaur<Trex> {}
}
4

1 回答 1

2

这是因为 Trex 类两次实现了 Animal 接口,但是使用了不同的类型参数

是的,情况就是这样,而且没有办法直接解决这个问题——这是一个技术限制,因为泛型是使用擦除实现的。您永远不能在具有不同泛型参数的多个类上实现相同的接口。当泛型类型被擦除时,您最终会以相同的方式扩展两个接口,无法区分使用这些不同泛型类型的方法,因此运行时无法确定执行哪个方法。

对于您的特定用例,可能有一种解决方法,这意味着您不必使用不同的类型参数实现相同的接口,但是如果没有更多细节,就不可能说出那可能是什么。

编辑:查看链接的问题,您似乎可以通过使用以这种方式指定返回值而不是在类上声明它的另一个答案(您尚未接受的答案)来解决此问题:

public <T extends JNumber> T add(T addend);

这应该意味着你不需要在你的类和接口上声明泛型类型参数,因此不应该有这个问题。

于 2014-03-24T12:57:57.270 回答