如何通过Java中的反射来转换泛型基类型?

时间:2014-11-30 05:13:54

标签: java reflection

假设我有以下课程:

public class MyClass<T> {
    Class<T> type;
    List<T> items;
    public Class<T> getType() { return type; }
    ...
}

我需要将上述类的对象存储在通用容器中:

public class MyContainer<T> {
    Class<T> type;
    List<MyClass<T>> myClasses;
    public Class<T> getType() { return type; }
    ...
}

让我们稍后在我的代码中说我给了一个通用对象作为参数:

public class Main {
    public static void main() {
        List<MyContainer<?>> containers;
        ...
    }
    public void someMethod(MyClass<?> myClass){
        ...
    }
}

我将T型作为反射。我需要将MyClass<?>强制转换回其预期的类型。因此,如果它被声明为MyClass<String>,我需要将其转回MyClass<String>。我似乎无法用反射类型执行此操作,因为它只能投射T,而不是MyClass<T>

我可以通过这样做来施放T,例如:

myClass.getType().cast(myClass.getItem()); // Where getItem returns an object of the type T

但我想要的是:

myClass.getType().cast(myClass); // getType() returns T not MyClass<T>

所以问题是,在给定上述场景的情况下,如何将通用基类型及其反射类型转换为?

2 个答案:

答案 0 :(得分:0)

由于type erasure,这是不可能的。反射在这里无法帮助您,因为在运行时,泛型类型信息不可用。换句话说,在运行时没有MyClass<String>,只有MyClassMyClass<String>是纯粹的编译时生物。

如果您有一些需要某种类型的代码,请在编译时声明。这种类型的期望可以是具体的或通用的:

public void someMethod(MyClass<String> myClass)

public <T> void someMethod(MyClass<T> myClass)

如果您知道类型,则不需要cast(),您可以直接投射:

@SuppressWarnings("unchecked")
MyClass<String> myClassStr = (MyClass<String>)expression;

答案 1 :(得分:0)

由于T在运行时不存在,您知道,因此无法使用它。您也无法获得Class<List<T>>

myClass.getType().cast(myClass.getItem())并不适合您,因为如果您有MyClass<?>,那么您还有Class<?>只返回Object。 Class<T>对您也没有帮助,因为您需要真正知道T是什么。

你几乎可以做两件事。

使用决定:

if(myClass.getType() == String.class) {
    @SuppressWarnings("unchecked")
    final MyClass<String> myStrings = (MyClass<String>)myClass;

    // use MyClass<String> ...
}

使用多态:

MyClass<String> myClass = new MyClass<String>(...,
        new BiConsumer<String, JTable>() { // (or lambda ...)
    @Override
    public void accept(String s, JTable table) {
        // use String ...
        // configure JTable ...
    }
});

... elsewhere ...

public void someMethod(MyClass<?> myClass) {
    someCaptureMethod(myClass);
}

private <T> void someCaptureMethod(MyClass<T> myClass) {
    Consumer<T, JTable> consumer = myClass.getConsumer();

    for(T theT : myClass.getList()) {
        consumer.accept(theT, myTable);
    }
}

一般来说,第二个例子被认为是更好的&#34;方式,但在8之前的Java版本中代码可能会更长。