If I have a generic <T2 extends T1>, does the compiler infer T1 super T2?
I have a more complex collection, which I reduced to the MWE below. The collection shall be mergeable with any such collection with elements of any subtype.
Now I'm wondering, why the call to forEach in merge is not accepted. It fails with
java.util.function.Consumer<java.util.Optional> cannot be converted to java.util.function.Consumer<java.util.Optional<? super T2>>
I've depicted the type relationships in the diagram below. In merge, T2 extends T1. The call to forEach is applied on the other object, hence the T1 of this becomes the ? of other.forEach and the T2 of this.merge is the T1 of other. Hence, this' T1 should be accepted as super of other's T1.
I also tried public void merge(Group<? extends T> other) with the same result. And public void merge(Group<T> other) does not accept such collections with elements of any subtype of T1.
MWE:
class Group<T1> {
public <T2 extends T1> void merge(Group<T2> other) {
Consumer<Optional<T1>> task = t -> t.ifPresentOrElse(this::foo, this::bar);
other.forEach(task);
}
public Collection<Optional<T1>> values() {
return List.of();
}
public void forEach(Consumer<Optional<? super T1>> consumer) {
values().forEach(consumer);
}
private void foo(T1 t) {}
private void bar() {}
}
Relationships:
this.T1 -becomes-> other.forEach.?
^ |
| super
extends |
| v
this.merge.T2 -is-> other.T1
>` is not compatible with `List
– ernest_k Jan 31 '22 at 19:51>`. You may want to try `Consumer super Optional>`, with `task` being declared as `Consumer> task`. There's no reason to make `task` a `Consumer>`