对具有接口类和类型变量的Java交集类型的限制
今天,我试图用一个使用交集类型的泛型方法编写一个类,但由于交集类型不同,错误消息也不同,这让我感到困惑。假设我们有一个对具有接口类和类型变量的Java交集类型的限制,java,types,jls,Java,Types,Jls,今天,我试图用一个使用交集类型的泛型方法编写一个类,但由于交集类型不同,错误消息也不同,这让我感到困惑。假设我们有一个接口和一个类,并在通用接口中定义通用方法: class ClassType { } interface InterfaceType { } interface I<T> { public <X extends InterfaceType & InterfaceType> void foo(); public <X ext
接口
和一个类
,并在通用接口中定义通用方法:
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();
}
class类类型{
}
接口类型{
}
接口I{
公开无效foo();
公共空间1();
公共空间2();
公共空间3();
公共空间4();
公共空间5();
公共空间6();
公共图书馆7();
}
编译它会为所有方法产生错误,除了public void foo2()代码>
Main.java:8:错误:接口重复
公开无效foo();
^
java:10:错误:此处需要接口
公共空间1();
^
java:14:错误:此处需要接口
公共空间3();
^
java:16:error:类型变量后面不能跟其他边界
公共空间4();
^
java:18:错误:意外类型
公共空间5();
^
必修课:课堂
找到:类型参数T
其中T是一个类型变量:
T扩展接口I中声明的对象
java:20:错误:意外类型
公共空间6();
^
必修课:课堂
找到:类型参数T
其中T是一个类型变量:
T扩展接口I中声明的对象
java:22:error:类型变量后面不能跟其他边界
公共图书馆7();
^
7个错误
由于交叉点应该是对称的,我很惊讶foo2
被接受,而foo3
被拒绝。为什么受理这一案件
我还想知道,当涉及交叉点类型时,为什么接口、类和类型参数之间会有区别。我可以看到在交叉点类型中不允许有多个类的原因,但是当前接受ClassType和InterfaceType
但不接受InterfaceType和ClassType
的状态看起来异常随意。交叉口A&A
也被禁止,但这在语义上与A
相同,所以我看不出原因
我也很好奇为什么不允许在交叉点中使用类型变量。最坏的情况是两个或多个类的交集,但它只是一个无人居住的类型,所以底部的类型是。您只能有一个类,但有多个接口。如果您有一个类,它必须是第一个指定的类。如果遵循此规则,则不会出现任何编译错误
参见这在4.4类型变量一节中解释
类型变量是用作类中类型的非限定标识符,
接口、方法和构造函数主体
类型变量是
由泛型类的类型参数声明引入,
接口、方法或构造函数(§8.1.2、§9.1.2、§8.4.4、§8.8.4)
§6.3规定了声明为类型参数的类型变量的范围
声明为类型的每个类型变量
参数有一个界限。如果没有为类型变量声明绑定,
对象是假定的。如果声明了边界,则它由以下任一部分组成:
- 单一类型变量
T
,或
- 类或接口类型
T
后面可能跟接口类型I1&…&在
中李>
这是一个编译时错误
如果任何类型I1。。。在
中是类类型或类型变量
绑定的所有组成类型的擦除(§4.6)必须成对进行
不同,或发生编译时错误
类型变量不能同时存在
同时可以是两种不同接口类型的子类型
相同泛型接口或编译时的参数化
发生错误
绑定中类型的顺序仅在
类型变量的擦除由中的第一个类型确定
它的边界,并且类类型或类型变量只能出现在
第一个位置
类型变量X
的成员,其绑定T&I1&…&在
中,是交叉口类型(§4.9)T&I1&……&&在
中,出现在声明类型变量的点处
1.显然,您只能有一个类和多个接口。2.根据文档,该类必须在任何接口之前列出。@isaace您能给文档提供一个链接吗?我很好奇他们为什么对交叉点操作的顺序施加限制我不知道为什么,但我认为首先使用类而不是随机顺序是合乎逻辑的。@isaace对我来说似乎不太合乎逻辑。交集是对称的,所以A&B
相当于B&A
@Jens可能在某种程度上简化了编译器,或者他们只是想加强组织(很方便知道交集中的所有内容都是接口,可能第一种类型除外)。您好,感谢您的参考。然而,它只是说“类类型或类型变量可能只出现在第一个位置”,我想知道为什么会引入这个限制,因为交集是对称的,所以逻辑上X&Y
相当于Y&X
“绑定中类型的顺序仅在类型变量的擦除由其绑定中的第一个类型决定时才有意义,并且类类型或类型变量可能只出现在第一个位置。”因此,可能是因为它在擦除时需要类类型,但不确定
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
TypeParameter:
{TypeParameterModifier} TypeIdentifier [TypeBound]
TypeParameterModifier:
Annotation
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
AdditionalBound:
& InterfaceType