Reputation: 9776
I have lost in the Jungle of Generics, please help me :) I have something like this:
public class BaseClass<TYPE> {
public BaseClass(Class<TYPE> clazz) {};
}
public class FirstLevelClass<REFRESHABLE
extends RefreshableInterface> extends BaseClass<REFRESHABLE> {
public FirstLevelClass(Class<REFRESHABLE> clazz) {
super(clazz);
};
}
public class Argument<T extends AnyOtherClass>
implements RefreshableInterface {
public refresh() {}
}
pulbic class ProblematicClass
extends FirstLevelClass<Argument<AnyOtherClassDescendant>> {
public ProblematicClass() {
//Compiler error: Constructor
//FirstLevelClass<Argument<AnyOtherClassDescendant>>(Class<Argument>) is undefined
super(Argument.class);
}
}
As far as I think, the compiler should accept Argument
since it implements RefreshableInterface
.
ProblematicClass
working?ps: if you have better title for this, please change it. I could not make up better.
Upvotes: 12
Views: 1060
Reputation: 213223
Issue is, your constructor expects a Class<T>
, and T
in your code is inferred as Argument<AnyOtherClassDescendant>
.
So, you should pass a Class<Argument<AnyOtherClassDescendant>>
, and you're passing Class<Argument>
. But you can't pass that Class
instance directly, as you cannot do Argument<AnyOtherClassDescendant>.class
.
You can however, solve the issue by typecasting the class to required instance:
public ProblematicClass() {
super((Class<Argument<AnyOtherClassDescendant>>)(Class<?>)Argument.class);
}
Note, how you've to typecast Class<Argument>
first to Class<?>
, and then the resultant type to Class<Argument<AnyOtherClassDescendant>>
. There is no simple way to achieve that.
The reason behind this is, there is only a single Class
instance for all parameterized instantiation of a generic type, that is associated with the class itself. A single compilation unit of a generic type, compiles to just a single class file. I guess this is different in how C++ implements templates. There you get different machine codes for different instantiation.
So, if you execute the below code, you'll get true
as output:
List<String> strList = new ArrayList<String>();
List<Integer> intList = new ArrayList<Integer>();
boolean isSameClassInstance = strList.getClass() == intList.getClass();
System.out.println(isSameClassInstance);
Upvotes: 10