假设我有以下课程:
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>
所以问题是,在给定上述场景的情况下,如何将通用基类型及其反射类型转换为?
答案 0 :(得分:0)
由于type erasure,这是不可能的。反射在这里无法帮助您,因为在运行时,泛型类型信息不可用。换句话说,在运行时没有MyClass<String>
,只有MyClass
。 MyClass<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版本中代码可能会更长。