这里的类型推导是怎样一个逻辑?

这里需要对这样一个二维数组进行排序:

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));

这是为什么呢?

阅读 2.4k
2 个回答

首先看 Compartor#comparing 的方法签名:

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(  
  Function<? super T, ? extends U> keyExtractor)  
{ ... }

注意到 keyExtractor 是一个 Function.

再来看 Arrays.sort 的能匹配题目环境的方法签名:

public static <T> void sort(T[] a, Comparator<? super T> c) {
    ...
}

结合起来,即 aint[][]) 的类型决定了 Tint[]),这要求第二个参数的类型必须为 Compartor<? super int[]>,这就确定了 comparing 方法参数(Function<? super T, ? extends U>) 第一个泛型参数必须是 int[] 类型.

问题被简化为,给一个下面的表达式,该怎么匹配 Function<int[], ? extends U>

item -> item[1] % 2

已知 itemint[],则 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<T> thenComparing(  
  Function<? super T, ? extends U> keyExtractor)  
{ ... }

所以现在 Tint[]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));

我倒是觉得没什么特别的寓意,估计程序设计的时候不是期望你这么去使用的
分布使用就没问题

int[][] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Comparator<int[]> c = Comparator.comparing(item -> item[0] % 2);
Comparator<int[]> c1 = c.thenComparing(item -> item[1] % 3);
Arrays.sort(arr, c1);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题