List<Object>
aを a に割り当てるとList<? super String>
うまくいきます。
List<List<Object>>
aに a を代入しList<List<? super String>>
てもコンパイルされません。
コード
public class Main {
public static void main(String[] args) {
// works fine
List<Object> listOfObject = new ArrayList<>();
takeListSuperString(listOfObject);
// doesn't compile
List<List<String>> listOfListOfObject = new ArrayList<>();
takeListOfListSuperString(listOfListOfObject);
}
static void takeListSuperString(List<? super String> listSuperString) {
}
static void takeListOfListSuperString(List<List<? super String>> listOfListSuperString) {
}
}
質問
List<List<? super String>>
と同じように動作しないのはなぜList<? super String>
ですか?
また、このようなことを検索できる場所はありますか?
関連する質問はGenerics hell: hamcrest matcher as a method parameterです。しかし、そこにある答えは役に立ちません。
編集
最終的にそれを得る前に、JB Nizet の回答を数時間考えなければなりませんでした。というわけで、ここから少し拡大します。多分それは他の誰かを助けるでしょう。
List<List<CharSequence>>
aへの a の代入が可能であると仮定するとList<List<? super String>>
、次のコードがコンパイルされます。
// can only contain instances of CharSequence
List<List<CharSequence>> listOfListOfCharSequences = new ArrayList<>();
List<List<? super String>> listOfListSuperString = listOfListOfCharSequences;
// add a list of objects containing an Integer
List<Object> listOfObjects = new ArrayList<>();
listOfObjects.add(123);
listOfListSuperString.add(listOfObjects);
// Ups.. exception at runtime we are getting an Integer where we expect a CharSequence
CharSequence charSequence = listOfListOfCharSequences.get(0).get(0);
したがって、実行時の醜い例外を防ぐために許可されていません。
halex が指摘しているように、これは Generics 共分散であり、 a が に代入List<String>
できないのと同じList<Object>
です。そして、コードを使用すると、呼び出しが妨げList<? extends List<? super String>>
られるため、実際にコンパイルされます。? extends String
List.add()