I am a bit of confused about java generics
Here is the code
class Base{}
class Derived extends Base{}
WE can instantiate a list like this
List<? extends Base> list = new ArrayList<Base>();
Why cannot I add a a new item like this
list.add(new Base());
So user cannot use "add" method as far as a wildcard ? in the genetics type?
开发者_如何学运维Thanks
PECS - producer extends, consumer super.
If you replace extends
with super
, you can add new Base()
.
List<? extends Base>
means "a list that holds instances of any subclass of Base (or Base
itself). But it cannot hold instances of two different subclasses.
If you want your list to hold Base
and Derived
, then use List<Base>
. But note that it cannot be later cast to List<Derived>
Just make it
List<Base> list = new ArrayList<Base>();
You shouldn't use wildcards when you know the actual type... just when you're being provided with something with an unknown type.
In such cases, ? extends Base
means that the List
is only allowed to contain some specific subtype of Base
, but you don't know which subtype that is. Because of that, you can't add anything but null
to the list.
You can try reading ?
as something:
List<? extends Base>
This is "List
of something that extends Base
". So it is clear that you cannot add a Base
(just as you cannot add an Object
to a List<String>
even when String
extends Object
.
What you can do in your case is:
List<? super Base>
This is "List
of something that is extended by Base
". So you can add a Base
there (just as you can add a String
to a List<Object>
, because Object
is extended by String
.
I think this is a design of Java Generics. The wildcard ? extends Base
is compiled to mean that the collection reference can point to a collection object that can hold any ( and all ) types that extend Base.You can write like this as well :
List<? extends Base> _listBaseSubtypes = new ArrayList<Derived>();
Now , with the above line , if you think about it , the below will be obviously an error :
_listBaseSubtypes.add(new Base());
I think Java designers decided to allow the first line of code as valid. In order to avoid the runtime error that the second line of code can cause , it is caught at compile time.
Having said that , the question that comes to mind is : What type of object should be allowed to be added into the collection , given the fact that the actual collection object can be a collection of 'any' derived type ?
Because you can derive as many types as you want , and there cannot be found a single type that is assignment compatible with the type held in the actual collection object ( remember , the collection object could be declared to hold 'any' derived type ) , the simple answer to the question is : None. So , you cannot add any object into the collection through the add interface, because for any object that you may try passing into the add method , there will be complier objection raised on the reason that this type is not compatible with the type that the actual collection object holds.
精彩评论