为何java.util.Comparator.reversed API与泛型类配合时编译失败?
这个编译错误的核心原因是Java泛型类型推断在链式调用场景下的局限性,具体逻辑如下:
为什么Case3能正常编译?
当调用Comparator.comparing(Bar::getSeq)时,编译器可以直接从上下文获取足够的类型信息:bars.stream()的元素类型是Bar<Integer>,而sorted方法需要的是Comparator<Bar<Integer>>。基于这些信息,编译器能直接推断出comparing方法的泛型参数:T=Bar<Integer>(即比较的对象类型),U=Integer(即排序键的类型)。此时Bar::getSeq作为实例方法引用,完全匹配Function<Bar<Integer>, Integer>的类型要求(实例方法引用的第一个参数就是实例本身,对应Function的输入类型),因此编译通过。
为什么Case4会报错?
当链式调用.reversed()时,编译器的类型推断逻辑遇到了障碍:它需要先确定comparing返回的Comparator<T>的具体类型,才能处理.reversed()(该方法返回同类型的Comparator<T>),最终匹配sorted需要的Comparator<Bar<Integer>>。但Java的类型推断机制无法从后续的.reversed()和sorted的需求中回溯推导comparing的泛型参数T,导致它错误地将Bar::getSeq解析为不需要实例的静态方法引用——而getSeq是实例方法,因此抛出“非静态方法不能在静态上下文引用”的错误。
验证与解决方法
显式指定comparing的泛型参数,就能绕过类型推断的限制,让Case4正常编译:
List<Bar<Integer>> barRet2 = bars.stream() .sorted(Comparator.<Bar<Integer>, Integer>comparing(Bar::getSeq).reversed()) .toList();
内容的提问来源于stack exchange,提问作者Lebecca

