你可以指定一个继承另一个泛型类型和一个具体接口的通用类型吗?

15

我有一组领域模型,每个模型都有一个子类来扩展它并实现特定的接口,就像这样(Cloneable不是问题中的接口,只是举例):

class A{}
class B extends A implements Cloneable{}

class C{}
class D extends C implements Cloneable{}

我希望创建一个通用的类型签名,以强制执行这种配对,我尝试了这个,但失败了

<T1,T2 extends T1 & Cloneable> void f ( T1 t1, T2 t2 ){}

但是在我的IntelliJ IDE中,我收到了一条消息:"类型参数后不能跟其他边界";如果我改变顺序为:

"其他边界不能跟随类型参数"它仍然失败
<T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}

我收到了消息"这里需要接口."

令人困惑的是,这两个签名都可以使用

<T extends A & Cloneable> void f( A a, T t ){}
<T1,T2 extends T1> void f ( T1 t1, T2 t2 ){}

这只是Java泛型类型系统的奇怪限制吗?我不能有一个泛型类(即T2)既扩展另一个泛型类(即T1),又扩展一个具体接口(例如Cloneable)吗?

简而言之:为什么<T1,T2 extends Cloneable& T1> void f(T1 t1,T2 t2){} 无法编译:这是Java泛型语法的限制还是我使用了错误的语法?


是的,Java类型的另一个奇怪且不幸的限制是,如果涉及类型变量,则无法执行交集类型约束。给出的原因显然是为了避免“某些问题情况”。 - Judge Mental
@PaulBellora 虽然答案可能相同,但我的问题与两个接口的问题不同。 - Sled
@JudgeMental 看起来可以在编译时检查,所以我真的很想知道实际涉及的具体细节。 - Sled
1
@ArtB 请查看那个问题的编辑(它有一个赏金)和我的回答。我知道这有点令人困惑。第二个链接的帖子更明显是重复的。 - Paul Bellora
2个回答

6
答案在JLS 4.4中:JLS 4.4
TypeParameter:
    TypeVariable TypeBoundopt

TypeBound:
    extends TypeVariable
    extends ClassOrInterfaceType AdditionalBoundListopt

AdditionalBoundList:
    AdditionalBound AdditionalBoundList
    AdditionalBound

AdditionalBound:
    & InterfaceType
& Cloneable是一个AdditionalBound,只能用于AdditionalBoundList中。 AdditionalBoundList只能在ClassOrInterfaceType之后使用。而T1是一个TypeVariable,不是ClassOrInterfaceType。

因此,这确实是Java泛型语法的限制。


0

<T1,T2 extends Cloneable & T1> void f(T1 t1,T2 t2){}

我收到了“此处应该是接口”的消息。

来自jls 4.4. 类型变量:

Every type variable declared as a type parameter has a bound. If no bound is declared for a type variable, Object is assumed. If a bound is declared, it consists of either:

- a single type variable T, or

- a class or interface type T possibly followed by interface types `I1 & ... & In`.

It is a compile-time error if any of the types I1 ... In is a class type or type variable.

因此,对于表达式<T extends C & I> void test(T t)I应该是一个接口。


我在原问题中指的是Cloneable接口。问题出在C上,它必须是一个类或接口(但不是类型变量)。 - yshavit
@yshavit,请看一下我的回答开头,我引用了他的一个问题。实际上他有两个问题。我使用了 > 代码来粘贴问题,但是使用 < 时,它将 <T1,T2 extends Cloneable & T1> 这部分隐藏在了帖子中。 :) - Sage
不要紧,是我没能正确粘贴的错 :) - Sage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接