I have a class with a collection of Wildcard Types that is a singleton, something like:
public ObliviousClass{
private static final ObliviousClass INSTANCE
Your ObliviousClass
, by design, doesn't know the parameterized type of the item it holds. So to be type safe, you should avoid such design :-\
But if you want to keep it, first things is that you will have to cast. There is no way out of this. But the way you do it is very error prone. For example:
oc.put(k1, intType);
oc.put(k2, strType);
Type tint = oc.get(k1, Integer.class)
Type tstr = oc.get(k1, String.class) // typo in k2: compile fine
And worst, due to type erasure, it will fail at runtime only once you actually use tstr
, not when you get it from ObliviousClass
.
So you can improve safety by tracking the parameterized type in some other way. For example, you could associate the key to the type, not losing it:
@Value // lombok
class Key {
private int index;
}
class Type {}
class ObliviousClass {
// side note: static final can be public safely
public static final ObliviousClass instance = new ObliviousClass();
private List> map = new ArrayList<>();
public Key appendType(Type type){
// here, I found it nicer that obliviousClass generates and return the key
// otherwise use: "public void appendType(key key, Type type)"
// that binds parametrized type of both key and type arguments
map.add(type);
return new Key<>(map.size() - 1);
}
public Type get(Key key){
return (Type) map.get(key.index);
}
}
Then you can use it such as:
Type intType = new Type<>();
Type strType = new Type<>();
Key k1 = ObliviousClass.instance.appendType(intType);
Key k2 = ObliviousClass.instance.appendType(strType);
Type t1 = ObliviousClass.instance.get(k1);
Type t2 = ObliviousClass.instance.get(k2);
Type t3 = ObliviousClass.instance.get(k1); // won't compile