你能指定一个泛型类型,它继承另一个泛型类型_and_具体的接口吗?

时间:2013-11-14 17:26:17

标签: java generics

我有一个域模型系列,每个模型都有一个扩展它的子类实现一个特定的接口,就像这样(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"中收到了消息;如果我将订单切换到:

,它仍然 FAILS
<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通用语法的限制还是我使用了错误的语法?

2 个答案:

答案 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 ){}

     

我收到消息“预期接口在这里。”

来自jls 4.4. Type Variables:

  

声明为类型参数的每个类型变量都有一个绑定。如果不   为类型变量声明了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应该是一个接口。