是否可以指定一个泛型类型,该泛型类型将另一个泛型类型 _and_ 作为具体接口的子类化?

2022-09-03 15:55:44

我有一系列领域模型,每个模型都有一个子类来扩展它实现一个特定的接口,就像这样(不是有问题的接口,它只是用于示例目的):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中收到消息;如果我将订单切换到:"Type parameter cannot be followed by other bounds"

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

我收到消息"Interface expected here."

令人困惑的是,这两个签名都有效

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

这是否只是Java泛型类型系统的一个奇怪的限制,我不能让一个泛型类(即)同时扩展另一个泛型类(即)一个具体的接口(例如)?T2T1Cloneable

tl;dr:那么,为什么不编译:这是Java通用语法的限制,还是我使用了错误的语法?<T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}


答案 1

答案就在JLS 4.4中:

TypeParameter:
    TypeVariable TypeBoundopt

TypeBound:
    extends TypeVariable
    extends ClassOrInterfaceType AdditionalBoundListopt

AdditionalBoundList:
    AdditionalBound AdditionalBoundList
    AdditionalBound

AdditionalBound:
    & InterfaceType

是附加绑定,只能在附加绑定列表中使用。附加绑定列表只能在类或接口类型之后使用。并且是一个 TypeVariable,而不是 ClassOrInterfaceType。& CloneableT1

所以,是的,这是Java通用语法的局限性。


答案 2

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

我收到消息“此处预期的接口”。

jls 4.4.类型变量:

声明为类型参数的每个类型变量都有一个边界。如果没有为类型变量声明任何边界,则假定为 Object。如果声明了绑定,则它由以下任一部分组成:

- a single type variable T, or

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

如果任何类型是类型或类型变量,则为编译时错误。I1 ... In

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


推荐