Java Generics - unable to convert from <? extends MyObject> to <MyObject>

Why does the following code give a compilation error?

public MyObject(Builder<? extends MyObject> builder) { // Type mismatch: cannot convert from MyObject.Builder<capture#5-of ? extends MyObject> to MyObject.Builder<MyObject> Builder<MyObject> myObjBuilder = builder; } 

If the Builder type is a subclass of MyObject, then why can't you assign a builder to simply enter MyObject? I need to do this because I cannot use an object of type MyObject with a builder. Look at this code, for example:

 public MyObject(Builder<? extends MyObject> builder) { // The method getData(capture#8-of ? extends MyObject) in the type Builder<capture#8-of ? extends MyObject> is not applicable for the arguments (MyObject) this.data = builder.getData(this); } 

I feel this should be allowed. Or am I missing something? Is there a way to do this without dropping the builder before (Builder<MyObject>) and using @SuppressWarnings?

Also note that I need the Builder to be <? extends MyObject> <? extends MyObject> , because MyObject and its Builder will be subclassed (as abstract).

Thanks for your help!

+5
source share
1 answer

Because Foo<? extends Bar> Foo<? extends Bar> not a Foo<Bar> .

Tell Foo has a method:

 void add (T t) 

then under the contract you can add only T objects. Now, if T is created like ? extends Bar ? extends Bar , we do not know the type. Accepting Bar can lead to problematic behavior: if you have an ArrayList<Foo> , you expect the ArrayList to only contain Foo instances. If you see ArrayList<Foo> as ArrayList<SuperFoo> , you cannot guarantee that ArrayList<Foo> contains only Foo .

Some languages โ€‹โ€‹include covariance : if you use only T as output, you can say that the class Foo<T> is the same as Foo<SuperT> (the same with input). But currently, Java does not support this. C # however works at the interface level.

+4
source

Source: https://habr.com/ru/post/1211842/


All Articles