Java thenComparing通配符签名

标签 java generics wildcard comparator

为什么声明是这样的:

default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
我明白了大部分。 U是有道理的可以是任何东西,只要它可以与自身的父类(super class)相比较,因此也可以与自身相比较。
但我不明白这部分:Function<? super T, ? extends U>为什么不直接拥有:Function<? super T, U>U 不能只是参数化为 keyExtractor 返回的任何内容,并且仍然扩展 Comparable<? super U>都一样吗?

最佳答案

为什么是这样? extends U而不是 U ?
因为代码约定。退房 @deduper's answer一个很好的解释。
有什么实际区别吗?
正常编写代码时,编译器会推断出正确的 T对于诸如 Supplier<T> 之类的事情和 Function<?, T> ,所以没有实际的理由写 Supplier<? extends T>Function<?, ? extends T>在开发 API 时。
但是如果我们指定类型 会发生什么手动 ?

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>因为 IntegerNumber 不是 兼容。
  • 然后它适用于 fluent()因为 ? extends NumberInteger 兼容。

  • 在实践中,只有当您有多个泛型类型时才会发生这种情况,需要明确指定其中一个并错误地获取另一个( 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>
    

    关于Java thenComparing通配符签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63607274/

    相关文章:

    java - 如何在类路径中使用通配符来添加多个 jar?

    java - 为什么泛型类型和通配符类型输出结果不同

    java - 处理 wicket 中 AutoCompleteTextField 的 onchange 事件

    ios - 将 JSON 字符串解析为基于 iOS 类的对象

    java - 如何在android中使用cardview

    Scala 更高级的类型 : can't define a generic function that works on different collections

    c# - 泛型实现中的值和引用类型

    mysql - SQL 按通配符排序

    java - Tomcat 服务器正在运行但未在浏览器中加载

    java - 在屏幕上显示时删除 pdf 文件的安全方法