为什么Function.identity()会破坏类型依赖,但t - > t不会?

Gil*_*ili 9 java generics reification

Java 8 lambdas,Function.identity()或t-> t中找到的答案似乎暗示Function.identity()几乎总是等同于t -> t.然而,在测试用例看出下面,取代t -> tFunction.identity()编译错误的结果.这是为什么?

public class Testcase {

    public static <T, A, R, K, V> Collector<T, A, R> comparatorOrdering(
            Function<? super T, ? extends K> keyMapper,
            Function<? super T, ? extends V> valueMapper,
            Comparator<? super K> keyComparator,
            Comparator<? super V> valueComparator) {
        return null;
    }

    public static void main(String[] args) {    
        Map<Integer, String> case1 = Stream.of(1, 2, 3).
                collect(comparatorOrdering(t -> t, t -> String.valueOf(t),
                        Comparator.naturalOrder(), Comparator.naturalOrder()));
        Map<Integer, String> case2 = Stream.of(1, 2, 3).
                collect(comparatorOrdering(Function.identity(), t -> String.valueOf(t),
                        Comparator.naturalOrder(), Comparator.naturalOrder()));
    }
}
Run Code Online (Sandbox Code Playgroud)

案例1编译得很好,但案例2失败了:

method comparatorOrdering in class Testcase cannot be applied to given types;
                collect(comparatorOrdering(Function.identity(), t -> String.valueOf(t),
  required: Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>
  found: Function<Object,Object>,(t)->Strin[...]Of(t),Comparator<T#2>,Comparator<T#3>
  reason: inferred type does not conform to upper bound(s)
    inferred: Object
    upper bound(s): Comparable<? super T#4>,T#4,Object
  where T#1,A,R,K,V,T#2,T#3,T#4 are type-variables:
    T#1 extends Object declared in method <T#1,A,R,K,V>comparatorOrdering(Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>)
    A extends Object declared in method <T#1,A,R,K,V>comparatorOrdering(Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>)
    R extends Object declared in method <T#1,A,R,K,V>comparatorOrdering(Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>)
    K extends Object declared in method <T#1,A,R,K,V>comparatorOrdering(Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>)
    V extends Object declared in method <T#1,A,R,K,V>comparatorOrdering(Function<? super T#1,? extends K>,Function<? super T#1,? extends V>,Comparator<? super K>,Comparator<? super V>)
    T#2 extends Comparable<? super T#2>
    T#3 extends Comparable<? super T#3>
    T#4 extends Comparable<? super T#4> declared in method <T#4>naturalOrder()
Run Code Online (Sandbox Code Playgroud)

我的环境是Windows 10,64位,Oracle JDK build 1.8.0_92-b14.

更新:看到这个在ecj下编译,我有一个后续问题:这是一个错误javac吗?JLS对此案有什么看法?

k5_*_*k5_ 5

Ecj能够推断出正确的(?)类型参数(整数)以匹配约束.Javac出于某种原因得出了不同的结果.

这不是javac/ecj第一次在类型参数的推断中表现不同.

在这种情况下,您可以使用Function.<Integer> identity()为javac提供一个提示,以使其可以使用javac进行编译.

对于Function.identity()和t-> t之间的区别:

  • Function.identity()是Function <T,T>
  • t-> t在这种情况下是功能<?超级整数,?扩展整数>

所以t-> t在它可以匹配的方法中更灵活.