Reputation: 1310
When compiling this code:
private BiConsumer<MyObject, List<? extends MyOtherObject>> setter;
<T extends MyOtherObject> void setObject(BiConsumer<MyObject, List<T>> container) {
this.setter = setter;
}
I get "Cannot convert from BiConsumer <MyObject, List<T>> to BiConsumer<MyObject, List<? extends MyOtherObject>>"
Based on the parameterized method I assumed the types are compatable, as T can only be something that extends MyOtherObject.
The other reason I think the types are correct is if I remove the List it works.
I'm not sure what it is about introducing the list that causes this error.
Upvotes: 0
Views: 67
Reputation: 131326
What you want is a List
which the generic is a upperbounded wildcard ofMyOtherObject
:
void setObject(BiConsumer<MyObject, List<? extends MyOtherObject>> container) {
this.setter = container;
}
With the scoped method T
you defined as <T extends MyOtherObject>
, the container
parameter will take the type of the received argument and List<T>
can be a different type from the List<? extends MyOtherObject>
type.
For example it could be List<MyOtherObject>
or List<MyOtherObjectOtherSubclass>
. And the problem is that these cannot be assigned to List<? extends MyOtherObject>
defined inside BiConsumer
: a generic type variable.
You can check this behavior without using a method :
private BiConsumer<MyObject, List<? extends MyOtherObject>> setter;
...
BiConsumer<MyObject, List<? extends MyOtherObject>> listWildCard = ...;
this.setter = listWildCard; // compiles
BiConsumer<MyObject, List<MyOtherObject>> listSpecificType = ...;
this.setter = listSpecificType ; // doesn't compile
The other reason I think the types are correct is if I remove the List it works.
The error you encounter happens because your declared a generic type variable that declares itself a generic type and that you try to parameterize the type of the inner generic type. Making it is not valid because the parameter is so not a subtype of BiConsumer<MyObject, List<? extends MyOtherObject>>
any longer.
With a simple List
as parameter this code also would be fine :
private List<? extends MyOtherObject> setter;
<T extends MyOtherObject> void setObject(List<T> container) {
this.setter = container;
}
Or by defining the whole parameter as a parameterized type, it would work too :
private List<? extends MyOtherObject> setter;
<T extends BiConsumer<MyObject, List<? extends MyOtherObject>>> void setObject(T container) {
this.setter = container;
}
Upvotes: 4
Reputation: 1072
You need to define the generic at class level:
public class YourClass<T extends MyOtherObject> {
private BiConsumer<MyObject, List<T>> setter;
void setObject(BiConsumer<MyObject, List<T>> container) {
this.setter = container;
}
}
Otherwise there is no relationship between the generic T of the method and the wildcard of setter. They both extend MyOtherObject but they could be entirely different classes, which is why it won't compile.
Upvotes: 0