Javaでの分散の仕組みを理解するのは苦労しています。ジェネリックタイプのJavaタイプ分散、
次の例では、test
という関数を定義します。これはConsumer
です。この関数は反反変数なしで定義されているので、Consumer<Object>
はConsumer<Pair<Animal, Animal>>
のサブタイプではないと考えられます。しかし、コードはコンパイルされ、テストではラムダVariance:::superAction
が受け入れられます。
私には何が欠けていますか?
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.util.function.Consumer;
public class Variance {
public static void main(String[] args) {
test(Variance::exactMatchAction);
test(Variance::superAction);
}
private static void exactMatchAction(Pair<Animal, Animal> pair) {
System.out.println(pair.getLeft().getClass().getName());
}
private static void superAction(Object obj) {
System.out.println(obj.getClass().getName());
}
private static void test(Consumer<Pair<Animal, Animal>> action) {
action.accept(ImmutablePair.of(new Animal(), new Animal()));
action.accept(ImmutablePair.of(new Dog(), new Dog()));
}
static class Animal { }
static class Dog extends Animal { }
}
編集は:Thieloさんのコメント@ごとに、参照superAction
はConsumer<Pair<Animal, Animal>>
ませConsumer<Object>
に脱糖されます。
test
方法を与えるために、正しいタイプのようなものです:このタイプは、私たちがConsumer<Object>
test
にを渡すことができ、また、私たちはちょうどPair<Dog, Dog>
の代わりのような引数を持つ消費者を呼び出すことができるようになります
void test(Consumer<? super Pair<? extends Animal, ? extends Animal>>)
Pair<Animal, Animal>
。
このアップデートされたテスト用のタイプでは、void exactMatchAction<Pair<Animal, Animal>>
のようなメソッド参照はもう受け付けません。void exactMatchAction<Pair<? extends Animal, ? extends Animal>>
です。どうしてこれなの?
私が知る限り、警告は表示されません。 – asp
これがどのように実装されているかわかりませんが、意味があります。オブジェクトのコンシューマはペアを使用することもできます。そのパラメータを変更するとエラーが発生します。文字列、そうですか? – Thilo
本当に、私は分かりません。しかし、私の推測では、これは '@ FunctionalInterface'の処理方法と関係があります。おそらく、インタフェース自体の型パラメータについては気にしませんが、メソッド内でどのように参照されているかのみです。だから、 'Object - > void'メソッドはおそらく' Pair <> - > void'として使うことができます。 – ryachza