Java thenComparing wildcard signature

前端 未结 3 1751
广开言路
广开言路 2021-02-05 18:48

Why does the declaration look like this:

default > Comparator thenComparing(
            Function

        
3条回答
  •  北海茫月
    2021-02-05 19:21

    Why is it ? extends U and not U?

    Because of code conventions. Check out @deduper's answer for a great explanation.

    Is there any actual difference?

    When writing your code normally, your compiler will infer the correct T for things like Supplier and Function, so there is no practical reason to write Supplier or Function when developing an API.

    But what happens if we specify the type manually?

    void test() {
        Supplier supplier = () -> 0;
    
        this.strict(supplier); // OK (1)
        this.fluent(supplier); // OK
    
        this.strict(supplier); // compile error (2)
        this.fluent(supplier); // OK (3)
    }
    
     void strict(Supplier) {}
     void fluent(Supplier) {}
    
    1. As you can see, strict() works okay without explicit declaration because T is being inferred as Integer to match local variable's generic type.

    2. Then it breaks when we try to pass Supplier as Supplier because Integer and Number are not compatible.

    3. And then it works with fluent() because ? extends Number and Integer are compatible.

    In practice that can happen only if you have multiple generic types, need to explicitly specify one of them and get the other one incorrectly (Supplier one), for example:

    void test() {
        Supplier supplier = () -> 0;
        // If one wants to specify T, then they are forced to specify U as well:
        System.out.println(this., Number> supplier);
        // And if U happens to be incorrent, then the code won't compile.
    }
    
     T method(Supplier supplier);
    

    Example with Comparator (original answer)

    Consider the following Comparator.comparing method signature:

    public static > Comparator comparing(
        Function keyExtractor
    )
    

    Also here is some test classes hierarchy:

    class A implements Comparable {
        public int compareTo(A object) { return 0; }
    }
    
    class B extends A { }
    

    Now let's try this:

    Function keyExtractor = null;
    Comparator.comparing(keyExtractor); // compile error
    
    error: incompatible types: Function cannot be converted to Function
    

提交回复
热议问题