I have a class representing a pair of two values of the same type (type which can be any of a specific set of types ):
public class Pair<E extends AClass>{
private E var1;
private E var2;
}
This class is used by a framework, so it needs a no-argument constructor in which I have to instantiate the 2 variables (var1, var2):
public class Pair<E extends AClass>{
private E var1;
private E var2;
public Pair(){
var1 = invoke constructor of type E;
var2 = invoke constructor of type E
}
}
There are obviously a number of problems here:
-
In order to instantiate the variables I should somehow know its exact type and invoke that specific type’s constructor; in the best case this means to have a pretty large if else statement in the constructor, something like:
public Pair(){ if(var1 instanceof SpecificType1){ var1 = new SpecificType1(); var2 = new SpecificType2(); } } -
Even if I do as above, I will have some problems because var1 is declared of type E and I will get a type mismatch error when trying to instantiate SpecficType1 and to assign the resulted object to var1/var2. In order to make it work, I have to cast to E :
var1 = (E)new SpecificType1();
But this destroys the compile time type checking as I’m trying to cast a specific type to a generic type.
Is this a limitation of the Generics in java or is this scenario a bad one for using Generics ?
You’ll run into problems before that.
var1isnullat this point, sovar1 instanceof Tisfalsefor allT.One limitation of Java generics is that generic type parameters are erased so there’s no way that you can reflect on the type parameter from a zero-argument constructor.
The caller has to provide some context to tell you how to initialize
var1andvar2, and the typical way to provide that context is via constructor arguments.Your best option is probably to let
var1andvar2start offnulland then delay initialization until such time as you can get the context you need.Perhaps
This isn’t perfect since you still can’t distinguish
E extends List<String>fromE extends List<Number>but it may be good enough for your case, and the.castmethod will give you a type-safe cast toE.Alternatively, Guava, Guice, and related libraries provide things like the
Supplier<E>interface which may come in handy in aninitmethod.