Java 泛型多重边界错误:无法继承具有不同类型参数的内容

huangapple go评论82阅读模式
英文:

Java generic multiple bounds error:cannot be inherited with different type arguments

问题

当我编写代码时,我考虑使用通用的多重边界来解决一个问题,但在我完成编写后,它不断报错:无法使用不同的类型参数继承。我有以下的类:

public class Animal implements Comparable<Animal> {}
public class Dog extends Animal {}

我还定义了一个静态方法:

public static <T extends Animal & Comparable<? extends T>> T getMin(List<T> value) { return null; }

我的想法是定义一个通用类型,这个通用类型必须是Animal的子类,并且这个通用类型必须实现Comparable接口,接口的实际参数是Animal及其子类。

后来我尝试了另一种方式,定义了另一个静态方法:

public static <T extends Animal & Comparable<? super T>> T getMin(List<T> value) { return null; }

我的想法是定义一个通用类型,这个通用类型必须是Animal的子类,并且这个通用类型必须实现Comparable接口,接口的实际参数是Animal及其父类。

令人沮丧的是,这两种方法都报错:无法继承具有不同类型参数的java.lang.Comparable':'Animal'和'capture<? super T>'

最后,我发现Animal和Dog类需要修改如下,就像Number及其子类一样:

public class Animal {}
public class Dog extends Animal implements Comparable<Dog> {}

但我不明白为什么需要这样修改,以及为什么一开始会报错。

英文:

When I wrote the code, I thought about using generic multiple bounds to achieve a problem,but when I finished writing, it kept reporting errors:cannot be inherited with different type arguments

I have the following classes:

public class Animal implements Comparable&lt;Animal&gt; {}
public class Dog extends Animal   {}

I also defined a static method:

public static &lt;T extends Animal &amp; Comparable&lt;? extends T&gt;&gt; T getMin(List&lt;T&gt; value) { return null;}

My idea is to define a generic type, this generic type must be a subclass of Animal, and this generic type must implement the Comparable interface, and the actual parameters of the interface are Annimal and its subclass class.

Later I made another attempt,defined another static method:

public static &lt;T extends Animal &amp; Comparable&lt;? super T&gt;&gt; T getMin(List&lt;T&gt; value) { return null;}

My idea is to define a generic type, this generic type must be a subclass of Animal, and this generic type must implement the Comparable interface, and the actual parameters of the interface are Annimal and its parent class.

It is frustrating that both methods report errors:java.lang.Comparable' cannot be inherited with different type arguments: 'Animal' and 'capture<? super T>

Finally, I found that the Animal and dog classes need to be modified as follows,just like number and its subclasses:

public class Animal  {}
public class Dog extends Animal implements Comparable&lt;Dog&gt;  {}

But I do n’t understand why it needs to be modified like this, and why the error was reported at the beginning.

答案1

得分: 2

Java的泛型只有Java编译器知道,而不被Java虚拟机(JVM)所了解。这被称为类型擦除Comparable<Animal>Comparable<Dog>在JVM看来是相同的类型。JVM只将它们都视为Comparable

这是无效的:

<T extends Animal & Comparable<? extends T>>

因为你在说T应该同时实现两个接口:Comparable<Animal>(因为Animal实现了Comparable<Animal>)和Comparable<U>,其中UT的子类。T不能同时实现这两个接口,因为尽管它们在编译器中看起来不同,但在运行时,它们被认为是相同的Comparable接口。

这也是为什么不能让Animal实现Comparable<Animal>,同时让Dog实现Comparable<Dog>的原因。在运行时,Dog将会实现两个看起来相同的接口!

你可以这样写:

<T extends Animal & Comparable<Animal>>

但这有点多余…

通过只让Dog实现Comparable<Dog>T extends Animal不再意味着T implements Comparable<Animal>,因此你不再在说T应该实现两个不同的接口。

英文:

Java's generics are only known by the Java compiler, but not the JVM. This is known as type erasure. Comparable&lt;Animal&gt; and Comparable&lt;Dog&gt; are the same type, as far as the JVM is concerned. The JVM just thinks of both of them as Comparable.

This is invalid:

&lt;T extends Animal &amp; Comparable&lt;? extends T&gt;&gt;

Because you are saying that T should implement two interfaces at the same time: Comparable&lt;Animal&gt; (since Animal implements Comparable&lt;Animal&gt;) and Comparable&lt;U&gt; where U is a subclass of T. T can't implement these two interfaces at the same time, because although they look different to the compiler, the runtime thinks they are the same Comparable.

This is the same reason why you can't have Animal implement Comparable&lt;Animal&gt; and Dog implement Comparable&lt;Dog&gt;. Dog would be implementing two interfaces that look the same to the runtime!

You could say:

&lt;T extends Animal &amp; Comparable&lt;Animal&gt;&gt;

but that's kind of redundant...

By making only Dog implement Comparable&lt;Dog&gt;, T extends Animal no longer implies T implements Comparable&lt;Animal&gt;, so you are no longer saying that T should implement 2 different interfaces.

huangapple
  • 本文由 发表于 2020年4月7日 20:25:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/61079988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定