私は約2つのトラブルの理解、次のコード持っているPredicate
オブジェクトを。最初のものは、より低い有界ワイルドカード、上部境界第2のAを使用します。
Predicate<? super String> p1 = s -> s.startsWith("a"); // why can I call startsWith()?
Predicate<? extends String> p2 = s -> s.startsWith("a");
p1.test("a"); // works
p2.test("a"); // doesn't work (why?)
どのような私が理解していないp1
で、なぜそれがクラスからメソッドを呼び出すことが可能であるString
などの、startsWith()
?なぜ私は渡すことができますString
にオブジェクトをp1.test()
、私はそれを呼び出すことができると期待Number
してObject
、同様のオブジェクト。
以下のようp1
に振る舞う私が思ったp2
だろうが、しかし、これはそうではありません。私も渡すことはできませんString
にオブジェクトをp2.test()
。私たちが継承したオブジェクトを期待ので、これは、私には理にかなっていませんString
(含むがString
)。
私はそれは多分、我々は参照型ではなく、オブジェクト自体のタイプを指定することを、事実とは何かを持っていると思います。しかし、どのようなタイプ、オブジェクトのために使用されていますか?
あなたが呼び出すことが合法startsWith
のためにp1
もかかわらず、p1
下限に入力される? super String
型引数があることを推測されているので、String
。ラムダ式は、s -> s.startsWith("a");
であることが推測されるPredicate<String>
タイプの変数に割り当てることが合法です、Predicate<? super String>
。
このコンパイル:
Predicate<String> ps = s -> s.startsWith("a");
Predicate<? super String> p1 = ps;
これはしていません。
// no "startsWith" on Object
Predicate<? super String> p1 = (Object s) -> s.startsWith("a");
JLSの参照がであるセクション15.27.3、「ラムダ式のタイプ」。
Tは、ワイルドカード・パラメータ、機能インターフェイスタイプであり、ラムダ式が暗黙的に入力され、その後、グランド・ターゲット・タイプは、Tの非ワイルドカードパラメータ(§9.9)である場合
ここでは、地上のターゲット・タイプは、ラムダ式の一種であり、T
ここではあなたの下限変数のデータ型であるターゲット・タイプ、です。これは、コンパイラが割り当てを可能にするPredicate<String>
ラムダ式の型となる接地ターゲット・タイプとして。
また、予告あなたはにスーパークラスのオブジェクトを渡すことができないことをp1.test
あなたが(あなたがすでに持っている)可能性があるため、割り当てられた、Predicate<String>
にp1
とります、String
。
p1.test(new Object()); // Error: can't pass something higher than String
あなたが渡すことができない理由についてString
のp2.test
あなたが上位ワイルドカードのような有界持っているとき、? extends String
タイプパラメータのどちらかである任意のクラスできることを意味し、そのString
またはサブタイプを。(コンパイラは無視String
されfinal
、ここでの任意のサブクラスが存在することはできないがString
。)述語は、p2
Aを割り当てることができるPredicate<SillyString>
と仮定すると、SillyString
のサブクラスですString
。しかし、あなたは渡すことはできませんString
が期待できる方法にSillyString
。