I am confused, why is the first code snippet compiling but the second isn't?
I would assume that in both cases the generic parameter T describes the same set of possible types and thus they are equivalent.
First example
public class Main {
static Function<B, Integer> f = (b) -> 1;
Main() {
this(f);
}
<T extends A> Main(Function<T, Integer> f) {
}
}
class A { }
class B extends A { }
Second example:
public class Main<T extends A> {
static Function<B, Integer> f = (b) -> 1;
Main() {
this(f);
}
Main(Function<T, Integer> f) {
}
}
class A { }
class B extends A { }
Yields the error:
The constructor Main <T>(Function<B,Integer>) is undefined
In the first code, the T
parameter is scoped to the method :
<T extends A> Main(Function<T, Integer> f) {
}
It uses inference of the target (client declared type return) to determinate the T
value.
So it can only compile while the first type of the Function
is a A
or a subclass of A
to respect the <T extends A>
constraint.
For example declare these other classes :
class B extends A { }
class C extends A { }
class D extends B { }
And these will also work :
static Function<B, Integer> fb = (b) -> 1;
static Function<C, Integer> fc = (b) -> 1;
static Function<D, Integer> fd = (b) -> 1;
In the second code, you want to pass a Function<B, Integer>
declared variable to the Main
constructor that relies on the T
generic type of the class :
public class Main<T extends A> {
Main(Function<T, Integer> f) {
}
}
The problem is that here T
could be A
, B
or any other subclass of A
according to the generic type used by the client of the class.
So Function<B, Integer>
is not assignable to Function<T, Integer>
and the compilation fails.