// чем отличаются list1, list2, list3 ?
// что можно положить в list1, list2, list3 ?
// что можно достать из list1, list2, list3 ?
В list3 можно присвоить(через =) только list<B>(инвариант)
В list2 можно присвоить(через =) только list<B> и list предков B, т.е. List<A>, List<Object>(ковариант)
В list1 можно присвоить(через =) только list<B> и list наследников B, т.е. List<C>(контрвариант)
Дальше сложнее,
в list1 через add ничего нельза добавить(Почему?)
В list2 через add можно добавить B и наследники B, т.е. С. Я так понимаю здесь работает capture conversion? Т.е. List<? super B> конвертируется в List<Object> или в List<B>,
поэтому можно добавлять B и его наследников, так как эти объектами будут как Object так и B?
В list3 через add можно добавить B и наследники B, т.е. С. Т.е. здесь тоже самое что и с List<? super B>? Или есть разница, что и когда выбирать?
в list1 через get можно читать B и A(Почему не C?)
В list2 через get можно читать Object?(Почему только Object)
В list3 через get можно читать B и A(В чем разница с List<? extends B>?)
Можно какие-то практические примеры когда какие типы более appropriate/fit?