I've been a bit nonplussed by this behaviour of Java compiler. Could somebody explain why this happens? Consider this example:
public static abstract class GenericClass<A extends GenericClass<A>> {
protected abstract void method();
protected <B> B getB(Class<B> bclass) {
return null;
}
}
// ...
GenericClass<?> gc = new GenericClass() {
@Override
protected void method() {
String s = getB(String.class); // does not compile
}
};
String s = gc.getB(String.class); // compiles
Because no generic parameters are given in the new
, the anonymous class inherits from the raw type GenericClass
. Even though the method getB
does not mention A
, the generic information is still lost and the method call does not compile. Why does this happen?
Further, the reason I cannot specify the generic parameter for the new
is because it is supposed to be the anonymous class itself, but I cannot name the anonymous class to pass it. How do I do this correctly?
Raw types exist for compatibility with code from before generics existed. They are treated as a full "opt-out" of all things generic. If you want generics, do not use raw types. That is the intent of the language design.
The solution here is to name the class. Yes, classes can appear inside methods and other statement blocks; such things are called local classes. An anonymous class is basically a local class without a name—and local classes can do anything anonymous classes can do.
String thisIsFine() {
var cell = new Object() { String s; }; // example local variable to show local classes can access them
class GenericImpl extends GenericClass<GenericImpl> {
@Override
protected void method() {
cell.s = getB(String.class);
}
}
new GenericImpl().method();
return cell.s;
}