Understanding Bounded Generic Parameter to a constructor

lwi :

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

davidxxx :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=89068&siteId=1