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.
You can only define the coursebookname variable one time (which is when you specify the type). Remove the String designation from before the variable name when you pass it to the Person constructor and it should work fine.
You can use any data type for a parameter of a method or a constructor. This includes primitive data types, such as doubles, floats, and integers, as you saw in the computePayment method, and reference data types, such as objects and arrays.
Parameterized Constructor – A constructor is called Parameterized Constructor when it accepts a specific number of parameters. To initialize data members of a class with distinct values. In the above example, we are passing a string and an integer to the object.
If there is any one parametrized Constructor present in a class, Default Constructor will not be added at Compile time. So if your program has any constructor containing parameters and no default constructor is specified then you will not be able to create object of that class using Default constructor.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With