我有一个域模型系列,每个模型都有一个扩展它的子类和实现一个特定的接口,就像这样(Cloneable
不是有问题的接口,它是为仅供参考):
class A{}
class B extends A implements Cloneable{}
class C{}
class D extends C implements Cloneable{}
我想创建一个强制执行此配对的通用类型签名,我已尝试过 FAILS :
<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泛型类型系统的一个奇怪限制,我不能拥有泛型类(即T2
)扩展另一个泛型类(即T1
)< em>和具体的界面(例如Cloneable
)?
tl; dr:那么,为什么<T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}
不会编译:它是Java通用语法的限制还是我使用了错误的语法?
答案 0 :(得分:6)
答案在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通用语法的限制。
答案 1 :(得分:0)
<T1,T2 extends Cloneable & T1> void f ( T1 t1, T2 t2 ){}
我收到消息“预期接口在这里。”
声明为类型参数的每个类型变量都有一个绑定。如果不 为类型变量声明了bound,假定为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
应该是一个接口。