这里需要对这样一个二维数组进行排序:
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
的方法签名:注意到
keyExtractor
是一个Function
.再来看
Arrays.sort
的能匹配题目环境的方法签名:结合起来,即
a
(int[][]
) 的类型决定了T
(int[]
),这要求第二个参数的类型必须为Compartor<? super int[]>
,这就确定了comparing
方法参数(Function<? super T, ? extends U>
) 第一个泛型参数必须是int[]
类型.问题被简化为,给一个下面的表达式,该怎么匹配
Function<int[], ? extends U>
:已知
item
为int[]
,则item[x]
即为int
,则item[1] % 2
必定为int
,但必须装箱成Integer
才能作为泛型参数.那么对于
为什么推导不出来,结合前面所说,现在要匹配
Arrays.sort(T[], Compartor<? super T>)
方法,就要求最终是个
Compartor<int[]>
.我们手动推一下:
先来看一下
thenComparing
的方法签名:所以现在
T
为int[]
,U
的类型是什么都无所谓了,因为这里的T
与前面Compartor.comparing
里的T
是同一个.那么为什么 IDE、编译器推导不出来呢?
因为:它们没办法从后往前推导.
编译器在编译一个
java
文件时,会进行类型检查并擦除泛型.问题就在于,在第一个
Compartor.comparing
时,没有足够的信息让编译器知道T
是什么类型,编译器会认为表达式item -> item[0] % 2
是不被允许的(不知道T
的类型那么就当作Object
处理,而Object
不是一个Array type
,且不支持%
运算符)从而报错,这时就已经阻断了编译进程,没去管后面的东西.所以我们只需要提前告诉编译器
comparing
使用的T
是什么就行了: