You can get a T
from a List<? extends T>
, but the only thing you can put into it is a null
literal. You can put a T
into a List<? super T>
, but the only thing you can get from it is an Object
(which is then unsafe to cast down to T
).
So, the restrictions make these pretty good, though imperfect, reminders of the intention. With a List<? extends T>
, you can't put most things into it -- so it's kinda read-only. And with a List<? super T>
, you can't get things out of it very usefully -- so it's kinda write-only.
Note that neither one of these is actually read- or write-only. I noted some of the ways you can get things into or out of them above, and with the "read-only" construct, you can still call remove
functions, either on the object itself or on its iterator.