开发者

Java generics confusion

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜