Почему функция Function.identity() прерывает тип, а t → t - нет?

Ответы найдены в Java 8 lambdas, Function.identity() или t- > t, по-видимому, подразумевают, что Function.identity() почти всегда эквивалентен t -> t, Однако в тестовой таблице, замеченной ниже, замена t -> t на Function.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()));
    }
}

Случай 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()

Моя среда - это Windows 10, 64-бит, Oracle JDK build 1.8.0_92-b14.

ОБНОВЛЕНИЕ. Увидев, что это компилируется под ecj, у меня есть следующий вопрос: это ошибка в javac? Что JLS должен сказать об этом случае?

Ответ 1

Ecj может вывести правильный (?) аргумент типа (Integer) для соответствия ограничениям. Джавак почему-то приходит к другому результату.

Это не первый случай, когда javac/ecj ведут себя по-разному в выводе параметров типа.

В этом случае вы можете дать javac подсказку с функцией. <Integer> identity(), чтобы сделать ее скомпилируемой с помощью javac.

За разницу между Function.identity() и t- > t:

  • Функция .identity() - это функция < T, T >
  • t- > t в этом случае является функцией <? супер целое,? extends Integer >

Таким образом, t- > t более гибко в методах, которые могут соответствовать.