这里的类型推导是怎样一个逻辑?
这里需要对这样一个二维数组进行排序:
int[][] arr = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
如下,像这样写类型推导能够完成:
// int[] -> T, T[]
Arrays.sort(arr, Comparator.comparing(item -> item[0] % 2));
但是这样就不行了:
Arrays.sort(arr, Comparator.comparing(item -> item[0] % 2).thenComparing(item -> item[1] % 3));
这是为什么呢?
首先看 Compartor#comparing 的方法签名:
public static <T, U extends Comparable<? super U>> Comparator
comparing(
Function<? super T, ? extends U> keyExtractor)
{ ... } 注意到 keyExtractor 是一个 Function.
再来看 Arrays.sort 的能匹配题目环境的方法签名:
public static void sort(T[] a, Comparator<? super T> c) { ... } 结合起来,即 a(int[][]) 的类型决定了 T(int[]),这要求第二个参数的类型必须为 Compartor<? super int[]>,这就确定了 comparing 方法参数(Function<? super T, ? extends U>) 第一个泛型参数必须是 int[] 类型.
问题被简化为,给一个下面的表达式,该怎么匹配 Function<int[], ? extends U>:
item -> item[1] % 2 已知 item 为 int[],则 item[x] 即为 int,则 item[1] % 2 必定为 int,但必须装箱成 Integer 才能作为泛型参数.
那么对于
Arrays.sort(arr, Comparator.comparing(item -> item[0] % 2).thenComparing(item -> item[1] % 3)); 为什么推导不出来,结合前面所说,现在要匹配 Arrays.sort(T[], Compartor<? super T>) 方法,就要求
Compartor.comparing(item -> item[0] % 2) .thenComparing(item -> item[1] % 3) 最终是个 Compartor<int[]>.
我们手动推一下:
先来看一下 thenComparing 的方法签名:
default <U extends Comparable<? super U>> Comparator
thenComparing(
Function<? super T, ? extends U> keyExtractor)
{ ... } 所以现在 T 为 int[],U 的类型是什么都无所谓了,因为这里的 T 与前面 Compartor.comparing 里的 T 是同一个.
那么为什么 IDE、编译器推导不出来呢?
因为:它们没办法从后往前推导.
编译器在编译一个 java 文件时,会进行类型检查并擦除泛型.
问题就在于,在第一个 Compartor.comparing 时,没有足够的信息让编译器知道 T 是什么类型,编译器会认为表达式 item -> item[0] % 2 是不被允许的(不知道 T 的类型那么就当作 Object 处理,而 Object 不是一个 Array type,且不支持 % 运算符)从而报错,这时就已经阻断了编译进程,没去管后面的东西.
所以我们只需要提前告诉编译器 comparing 使用的 T 是什么就行了:
Arrays.sort(arr, Comparator.<int[], Integer>comparing(item -> item[0] % 2) .thenComparing(item -> item[1] % 3));
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。