4

虽然我知道由于类型擦除,您实际上无法在运行时获得泛型的类型,但我想知道是否有可能在编译时获得它。

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我不必更改类型handle和检查(和强制转换)instanceof当然)。

4

1 回答 1

3

由于泛型类型会被擦除,因此您需要在代码中的某处指定 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));
}
于 2013-08-18T19:58:05.407 回答