java - &-运算符和顺序的泛型歧义

标签 java generics

我有一个奇怪的 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/

相关文章:

java - 为什么 Java 的 TreeSet<E> remove(Object) 不带 E

java - 在 Android Java 代码中使用泛型

c# - C# 中的类<类型>

c# - 原始泛型类型列表 C#

java - 使用 List<type> 而不是 ArrayList<Hashmap<String,String>> 进行 ListView

java - 在 JSoup 中按名称查找字符串值

java - 如何在字符串或表列中查找未知的重复子字符串

java - 单行java注释的正则表达式

Java 反射 - 获取通用接口(interface)中 T 的实际类型<T>

java - 如何将一个字符串与另一个字符串的越来越小的部分进行比较?