双超级通配符

Double super wildcard

在这段代码中,第一行成功编译时,第二行出现错误:

Comparator<? super Integer> a = (x, y) -> Integer.compare(x, y);
Comparator<? super Integer> b = a.thenComparing((x, y) -> Integer.compare(x, y));

错误是"incompatible types: Object cannot be converted to int"

thenComparing 具有以下签名:thenComparing(Comparator<? super T> other), 据我了解 other 在这种情况下会变成类似 Comparator<? super super T>Comparator<? super super Integer>.

为什么在我的示例中它变成了 Comparator<Object>

这是编译器缺陷还是它在保护我免受某些事情的影响?

您将 a 定义为 Comparator<? super Integer>,而您的作业 (x, y) -> Integer.compare(x, y) 满足了它。

但是,编译器不知道 ? 的确切类型是什么。它可能是 ObjectNumberInteger 本身,但 哪个 未知。 thenComparing() 依赖于 a 的类型参数,因为它的签名是 Comparator<T> thenComparing(Comparator<? super T>)。您正在传递 Comparator<Integer>,但 a 的类型参数不匹配。

泛型是不变的Comparator<? super Integer> 不是 Comparator<Integer>。仅当您不关心类型时才使用通配符。否则,请使用正确的类型参数。

a 定义为 Comparator<Integer> 以便修复它。


这是对另一个 Whosebug post 的出色回答,解释了 为什么 泛型不是隐式多态的。它还解释了如果使用泛型会出现什么问题。

  • Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?