11

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()));
    }
}

ケース 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 ビルド 1.8.0_92-b14 です。

更新: これが ecj の下でコンパイルされるのを見て、フォローアップの質問があります: これは のバグjavacですか? この事件についてJLSは何を言わなければなりませんか?

4

2 に答える 2

5

Ecj は、正しい (?) 型引数 (Integer) を推論して、制約に一致させることができます。何らかの理由でJavacは異なる結果になります。

型パラメーターの推論で javac/ecj が異なる動作をするのはこれが初めてではありません。

その場合、Function.<Integer>identity() を使用して javac にヒントを与え、javac でコンパイルできるようにすることができます。

Function.identity() と t->t の違いについて:

  • Function.identity() は Function<T,T> です
  • その場合の t->t は Function<? 超整数、? 整数を拡張>

したがって、t->t は、一致できるメソッドにおいてより柔軟です。

于 2016-06-26T05:35:28.770 に答える