I will again rename your classes, so that everything is more readable. So, let's have:
public class First<T extends Second, U extends First<T, U>> {
Third<T, U> c;
void test() {
c.acceptParameterOfTypeA(this);
}
}
class Second {
}
public class Third<X extends Second, Y extends First<X, Y>> {
void acceptParameterOfTypeA(Y a) {
}
}
From the definition of the c
member (Third<T, U>
), we can conclude that c
will expose a method with this signature:
void acceptParameterOfTypeA(U a) { .. }
What is U
? U
is a sub-type of First<T, U>
.
But if U
can be substituted with First
after type-erasure, this will mean that First extends First<T, First>
, which is not true, because U
stands for sub-type of First
, which is parameterized with some concrete sub-types of Second
and First
.
In order to get to U
, you can apply the so-called Get This
approach.
First, since you need U
, which is a sub-type of First
, but can't get it from First
, you can introduce an abstract
method that returns it:
abstract class First<T extends Second, U extends First<T, U>> {
Third<T, U> c;
void test() {
c.acceptParameterOfTypeA(getU());
}
abstract U getU();
}
Then, implement a sample sub-class of First
, called Fourth
, which extends First
with some concrete types for T
and U
, for example:
class Fourth extends First<Second, Fourth> {
Fourth getU() {
return this;
}
}
In the getU()
method, just do return this;
as this will return the correct substitute for U
in the super-class.
More info: