'java type generic: why Function<? super E, ? extends F> is more preferred than Function<E, F>? [duplicate]
There is class called Foo as following:
public class Foo<E> {
private List<E> ls;
public Foo(List<E> ls) {
this.ls = ls;
}
public void add(E l) {
this.ls.add(l);
}
public <F> Foo<F> map(Function<? super E, ? extends F> f) {
Foo<F> res = new Foo<F>(new ArrayList<F>());
for (E l : ls) {
res.add(f.apply(l));
}
return res;
}
}
Then, I call from main:
//Main.java
Foo<Integer> foo1 = new Foo<>(Arrays.asList(1,2,3,4));
Foo<String> foo2 = foo1.map(a -> a.toString());
I want to see how defining the function as Function<? super E, ? extends F> gives an advantage over Function<E,F>? Is Function<? super E, ? extends F> for has the maximum flexibility? Could you please show it in a example by changing Main.java?
Solution 1:[1]
It's a bad idea to try to reason about generics with final classes like String and Integer.
Try a hierarchy like A > B > C
class A {}
class B extends A {}
class C extends B {}
Then an example like
Foo<B> foo1 = new Foo<>(new B());
Function<A, C> aToC = a -> new C();
Foo<B> foo2 = foo1.map(aToC);
This won't work without both super E and extends F. The function takes an A - foo1 is a B, but A is a super class of B - and returns a C - foo2 is expecting a B, but C extends B.
If your map function were simply declared as
public <F> Foo<F> map(Function<E, F> f) {
then the above snippet wouldn't compile. The function would have to be Function<B, B>.
Hopefully that demonstrates why the more complex signature is more flexible.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Michael |
