我有一个奇怪的 Java 泛型歧义行为,我无法解释:
类中的这 3 个方法:
public static <E extends ClassA & ClassB> void method(E val) {}
public static <E extends ClassC & ClassB & ClassA> void method(E val) {}
public static <E extends ClassB> void method(E val) {}
编译正常。
但那些不是(违反歧义):
public static <E extends ClassA & ClassB> void method(E val) {}
public static <E extends ClassB & ClassC & ClassA> void method(E val) {}
public static <E extends ClassB> void method(E val) {}
(ClassA、ClassB、ClassC都是完全独立的接口(interface)!)
最佳答案
由于类型删除,编译器需要为编译方法中的参数类型选择一个静态已知的类型。
为此,它使用约束列表中的第一种类型。
在您的第一个示例中,这会为每个方法生成一个唯一的类型,因此它会编译为
public static method(ClassA val);
public static method(ClassC val);
public static method(ClassB val);
这是完全合法的(除了你缺少的返回类型);它使用三种不同的参数类型创建三个重载。
在您的第二个示例中,这会产生歧义:
public static method(ClassA val);
public static method(ClassB val);
public static method(ClassB val);
这是不合法的,因为最后两个方法具有相同的签名。
规范 explicitly documents这种行为。
这本来可以通过尝试从每个重载中选择一个约束类型来实现合法,这样就不会有冲突,但是对于更大的约束列表来说,这会很复杂而且很慢。
规范可能会这样说:
If it is used in erasure of a type in the parameter list, the erasure of a type variable in a generic method is chosen such that each overload of that method results in a unique signature after erasure.
If no combination of erasures will result in a unique signature, an ambiguity error occurs.
我怀疑这个问题出在NP中。
关于java - &-运算符和顺序的泛型歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21142467/