Reputation: 51
There is the unmodifiableList
method in the Collections
class. It returns a List<T>
but in the parameters it accepts List<? extends T>
.
So if I understand this right then this method accepts a List which has T objects or objects that inherited from T class.
But I don't understand why the <? extends T>
part in the parameter. I mean the parameter determines the return type of the method. If the method is called with List<Animal>
then the return will be List<Animal>
so it is going to be the same. Why we need this <? extends T>?
Why don't we need just List<T>
in the parameter list? I don't understand this.
If you could provide an example I would be happy about it. Thank you in advance!
Upvotes: 4
Views: 150
Reputation: 103018
So if I understand this right then this method accepts a List which has T objects or objects that inherited from T class
This is oversimplifying matters.
a List<Number>
can contain solely integers. The point of a List<Number>
is that it is constrained to contain only number instances. Not that each instance MUST be Number and specifically Number - that would be impossible, as Number
is abstract (no instances of Number itself can possibly exist, only instances of some subclass of it). The only difference between a List<Integer>
containing only integers and a List<Number>
containing only integers, is that you can add, say, a Double
instance to that List<Number>
, but you can't add it to a List<Integer>
.
Because a method that takes, as argument, a List<Something>
could invoke .add()
, the type system needs to worry about the difference. It needs to do so even if this method does not, in fact, call add
at all, and never intends to. The type system doesn't know that, and you're free to change the body of a method in some future version without that breaking backwards compatibility, thus, it matters. Even if you feel like it does not.
That then also explains your question:
If you have some method that demands a List<Number>
, then you may provide a List<Integer>
to Collections.unmodifiableList
, and that's fine - Collections.uL will give you that List<Number>
. This would ordinarily be broken, in that you can invoke .add(someDouble)
which you should not be doing to a list of integers, but .add
doesn't work on an unmodifiable, so it's fine.
Upvotes: 2
Reputation: 16373
List<? extends T>
means it also accepts lists of subtypes.
Imagine having a class Plant
and a class Tree
that extends Plant
.
You could create an unmodifiable List
of Plant
s using a List<Tree>
because Collections.unmodifiableList
accepts lists of any subtype of T
.
If it was List<T>
, it would accept a List<Plant>
as a parameter in order to create an unmodifiable List<Plant>
but you could not create an unmodifiable List<Plant>
using a List<Tree>
as parameter.
Upvotes: 0