问题
While I know you cannot actually get the type of a generic at runtime because of type erasure, I was wondering if it is possible to get it at compile time.
class ObjectHandle<T extends ObjType> {
T obj;
void setObj(T o) {
obj = o;
}
}
class ObjType {}
class SubObjType extends ObjType {}
...
ObjectHandle<SubObjType> handle = new ObjectHandle<SubObjType>();
...
ObjType obj = [method that returns an ObjType];
if(obj instanceof [handle's generic class, here SubObjType]) {
handle.setObj(obj); // cast???
}
Here the compiler knows the type of the generic of handle
and what I want is something so I don't have to change the type of handle
and the instanceof
check (and the cast) when I decide to change the class (in the code, not at runtime of course).
回答1:
Since generic types are subjected to erasure, you will need to specify the java.lang.Class somewhere in the code. One way is to pass it to a generic method:
ObjType obj = /*...*/;
handleObj(obj, SubObjType.class);
// ...
private <T extends ObjType> void handleObj(ObjType obj,
ObjectHandle<T> handle,
Class<T> handleableObjClass) {
if (handleableObjClass.isInstance(obj)) {
handle.setObj(handleableObjClass.cast(obj));
}
}
If you don't know what subclasses of ObjType you're looking for, you will need to add a reifiable Class property to ObjectHandle, similar to how java.util.EnumSet and java.util.EnumMap do it:
class ObjectHandle<T extends ObjType> {
T obj;
private final Class<T> objectClass;
ObjectHandle(Class<T> cls) {
objectClass = Objects.requireNonNull(cls);
}
Class<T> getObjectClass() {
return objectClass;
}
void setObj(T o) {
obj = o;
}
}
// ...
ObjectHandle<SubObjType> handle = new ObjectHandle<SubObjType>();
// ...
ObjectType obj = /*...*/;
if (handle.getObjectClass().isInstance(obj)) {
handle.setObj(handle.getObjectClass().cast(obj));
}
来源:https://stackoverflow.com/questions/18299444/get-generic-class-at-compile-time