java - Java thenComparing通配符签名
问题描述
为什么声明看起来像这样:
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
我明白了大部分。U
只要它与自身的超类具有可比性,因此也可以与自身具有可比性,它可以是任何东西,这是有道理的。
但我不明白这部分:Function<? super T, ? extends U>
为什么不只是有:Function<? super T, U>
U 不能参数化为 keyExtractor 返回的任何内容,并且仍然扩展Comparable<? super U>
相同吗?
解决方案
为什么是? extends U
而不是U
?
因为代码约定。查看@deduper 的答案以获得很好的解释。
有什么实际区别吗?
正常编写代码时,编译器会推断出T
诸如Supplier<T>
and之类的正确性,因此在编写或开发 API 时Function<?, T>
没有实际理由。Supplier<? extends T>
Function<?, ? extends T>
但是如果我们手动指定类型会发生什么?
void test() {
Supplier<Integer> supplier = () -> 0;
this.strict(supplier); // OK (1)
this.fluent(supplier); // OK
this.<Number>strict(supplier); // compile error (2)
this.<Number>fluent(supplier); // OK (3)
}
<T> void strict(Supplier<T>) {}
<T> void fluent(Supplier<? extends T>) {}
如您所见,
strict()
无需显式声明即可正常工作,因为T
被推断为Integer
匹配局部变量的泛型类型。然后,当我们尝试通过
Supplier<Integer>
因为并且不兼容时Supplier<Number>
,它会中断。Integer
Number
然后它适用于
fluent()
因为? extends Number
并且Integer
兼容。
实际上,只有当您有多个泛型类型时才会发生这种情况,需要显式指定其中一个并错误地获取另一个(Supplier
一个),例如:
void test() {
Supplier<Integer> supplier = () -> 0;
// If one wants to specify T, then they are forced to specify U as well:
System.out.println(this.<List<?>, Number> supplier);
// And if U happens to be incorrent, then the code won't compile.
}
<T, U> T method(Supplier<U> supplier);
示例Comparator
(原始答案)
考虑以下Comparator.comparing
方法签名:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, U> keyExtractor
)
这里还有一些测试类层次结构:
class A implements Comparable<A> {
public int compareTo(A object) { return 0; }
}
class B extends A { }
现在让我们试试这个:
Function<Object, B> keyExtractor = null;
Comparator.<Object, A>comparing(keyExtractor); // compile error
error: incompatible types: Function<Object,B> cannot be converted to Function<? super Object,A>
推荐阅读
- ruby - Rails 用户邮件程序未在生产中发送电子邮件
- php - 将特殊字符数组转换为字符串
- split - 如何在 TCL/tk 中实现类似功能?
- google-apps-script - oAuth 在谷歌脚本上被禁用
- zapier - 如何将 CSV 文件转换为单个 JSON 可序列化变量?
- react-native - 标题未显示 createBottomTabNavigator - React Native
- python - Exception Handling in Loops in python
- ios - Swift:解码任意协议类型
- go - 使用 Application Insights
- sql - SQL 语句在 Microsoft Access 2010 VBA 中将数据从条目表单抓取到数据表