今天我尝试用一个使用交集类型的泛型方法编写一个类,并根据相交类型对不同的错误消息感到困惑。我们假设我们有interface
和class
并在通用接口中定义泛型方法:
class ClassType {
}
interface InterfaceType {
}
interface I<T> {
public <X extends InterfaceType & InterfaceType> void foo();
public <X extends ClassType & ClassType> void foo1();
public <X extends ClassType & InterfaceType> void foo2();
public <X extends InterfaceType & ClassType> void foo3();
public <X extends T & ClassType> void foo4();
public <X extends ClassType & T> void foo5();
public <X extends InterfaceType & T> void foo6();
public <X extends T & InterfaceType> void foo7();
}
编译这会产生除public <X extends ClassType & InterfaceType> void foo2();
之外的所有方法的错误。
Main.java:8: error: repeated interface
public <X extends InterfaceType & InterfaceType> void foo();
^
Main.java:10: error: interface expected here
public <X extends ClassType & ClassType> void foo1();
^
Main.java:14: error: interface expected here
public <X extends InterfaceType & ClassType> void foo3();
^
Main.java:16: error: a type variable may not be followed by other bounds
public <X extends T & ClassType> void foo4();
^
Main.java:18: error: unexpected type
public <X extends ClassType & T> void foo5();
^
required: class
found: type parameter T
where T is a type-variable:
T extends Object declared in interface I
Main.java:20: error: unexpected type
public <X extends InterfaceType & T> void foo6();
^
required: class
found: type parameter T
where T is a type-variable:
T extends Object declared in interface I
Main.java:22: error: a type variable may not be followed by other bounds
public <X extends T & InterfaceType> void foo7();
^
7 errors
由于交叉点应该是对称的,我很惊讶foo2
被接受但foo3
被拒绝。为什么接受这一案件?
我也想知道为什么在交集类型方面为什么接口,类和类型参数之间存在区别。我可以看到在交集类型中不允许多个类的原因,但接受ClassType & InterfaceType
但不接受InterfaceType & ClassType
的当前状态似乎有点奇怪。交叉点A & A
也被禁止,但这在语义上与A
相同,所以我不明白这个原因。
我也很好奇为什么交叉路口不允许使用类型变量。最坏的情况是两个或更多类的交集,但只是一个无人居住的类型,所以底部类型。
答案 0 :(得分:2)
您只能拥有1个类但具有多个接口。如果你有一个类,它必须是指定的第一个类。如果您遵循此规则,则不应该收到任何编译错误。
请参阅https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
答案 1 :(得分:0)
这在 4.4 The Java Language specification的类型变量
中进行了说明类型变量是在类中用作类型的不合格标识符, 接口,方法和构造函数主体。
类型变量是 由泛型类的类型参数的声明引入, 接口,方法或构造函数(第8.1.2节,第9.1.2节,第8.4.4节,第8.8.4节)。
TypeParameter: {TypeParameterModifier} TypeIdentifier [TypeBound] TypeParameterModifier: Annotation TypeBound: extends TypeVariable extends ClassOrInterfaceType {AdditionalBound} AdditionalBound: & InterfaceType
在6.3节中指定了声明为type参数的类型变量的范围。
每个声明为类型的类型变量 参数有界。如果没有为类型变量声明边界, 假定对象。如果声明了界限,则界限由以下任意一项组成:
- 单个类型变量
T
或- 类或接口类型
T
后面可能跟着接口类型I1 & ... & In
。这是一个编译时错误 如果任何类型
I1 ... In
是类类型或类型变量。边界的所有组成类型的擦除(第4.6节)必须成对进行 不同,或者发生编译时错误。
类型变量不得位于 同时是两个不同接口类型的子类型 相同通用接口的参数化或编译时 错误发生。
边界中的类型顺序仅在 类型变量的擦除是由 它的边界,并且类类型或类型变量只能出现在 第一位置。
边界为
X
的类型变量T & I1 & ... & In
的成员是交集类型(§4.9)T & I1 & ... & In
的成员,出现在声明类型变量的位置。