Consider the following simplified example:
package com.test;
class B<S> {
B(Class<S> clazz) {}
}
class A<T> {
class SubB extends B<SubB> {
SubB() {
super(SubB.class);
}
}
}
Although IntelliJ is not showing any error (as it usually does when compile errors exist), the actual compilation when starting the program ends with error located in super(SubB.class);
:
Error:(8, 23) java: incompatible types:
java.lang.Class<com.test.A.SubB>
cannot be converted tojava.lang.Class<com.test.A<T>.SubB>
I am curious, why is this happening? And how could I solve it?
Compilation is done with AdoptOpenJDK 11.
The reason for this behavior is a bit complicated. Consider java.util.List.class
, which has the type Class<java.util.List>
, not Class<java.util.List<?>>
. This is a limitation of the class literal.
In your example, SubB.class
has the type Class<com.test.A.SubB>
, again with the raw type of SubB. But the constructor expects some type of Class<com.test.A<T>.SubB>
.
That's why we need to cast the literal to it's desired type:
super((Class<SubB>) (Class<?>) SubB.class);
This will produce a warning, but a quick examination will show that there is nothing to worry about.