Why does the following code give a compile 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 builder to just type MyObject? I need to do this because I am unable to use an object of type MyObject with the builder. Take a 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 like this should be allowed. Or am I missing something here? Is there a way to do this without casting builder to (Builder<MyObject>)
and having to use @SuppressWarnings ?
Also note that I need Builder to be <? extends MyObject>
because the MyObject and its Builder will be subclassed (as it is abstract).
Thanks for your help!
Because Foo<? extends Bar>
is not a Foo<Bar>
.
Say Foo
has a method:
void add (T t)
then by contract, you can only add T
objects. Now if T
is instantiated as ? extends Bar
, we don't know the type. Accepting Bar
could lead to problematic behavior: if you have an ArrayList<Foo>
you expect the ArrayList
to contain only Foo
instances. If you would see the ArrayList<Foo>
as a ArrayList<SuperFoo>
, one can't guarantee that the ArrayList<Foo>
contains only Foo
's.
Some languages enable covariance: if you only use T
as output, you can say that a class Foo<T>
is a the same as Foo<SuperT>
as well (the same with input). But currently Java doesn't support that. C# however does on the interface level.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With