在编译时获取泛型类

时间:2013-08-18 13:09:20

标签: java generics 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???
}

这里编译器知道handle的泛型的类型,我想要的是什么,所以我不必更改handleinstanceof检查的类型(和当我决定改变类时(在代码中,当然不是在运行时)。

1 个答案:

答案 0 :(得分:2)

由于泛型类型需要擦除,因此您需要在代码中的某处指定java.lang.Class。一种方法是将其传递给通用方法:

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));
    }
}

如果您不知道要查找的ObjType的子类,则需要向ObjectHandle添加可重新生成的Class属性,类似于java.util.EnumSet和java.util.EnumMap的操作方式:

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));
}