我有一个模板方法,需要实例化类对象与给定的类名字符串使用反射。这种情况有点复杂,因为返回类是使用类型变量的接口的实现。我想传递类名字符串和接口的类型变量的类型,并创建类对象。下面是一个方法签名示例:
<T> Class<? extends Foo<T>>
createClassObject(String className, Class<T> classTypeVariable);
是否有可能在Java 1.5中实现此方法而没有任何警告或@SuppressWarnings注释的任何使用?
编辑:示例方法签名编辑感谢Thomas注释
不,如果没有任何警告或使用@SuppressWarnings注释,就无法实现这一点。这是因为Class. forname()将被键入为Class。任何将其强制转换为更具体的内容(例如,类似Class<? extends Foo<T>>
的内容)的尝试都会产生与类型擦除相关的警告。如果您尝试强制转换Class.forName(). newinstance(),也会发生同样的情况。
也就是说,我认为这个方法是积极使用@SuppressWarnings的主要例子。我认为在这种情况下使用这个注释没有任何问题。当然,您可能想要添加一些逻辑来检查Class.forName(className)
是否扩展了Foo<T>
,以确保铸造是合理的。请注意,这种运行时检查不会使方法更加脆弱:当您在方法中调用Class.forName()
时,您已经有潜在的运行时类型错误。
如果返回的类应该是通用的(Bar<T> extends Foo<T>
或什么的),那么我很有信心,这是不可能的,因为(由于擦除)类型系统没有办法在运行时检查,如果Class.forName(...)
返回的类是Class<Bar<T>>
,而不是Class<Bar<U>>
或其他东西。(实际上只有一个单独的Class
对象表示所有的Bar<...>
类型,但是类型系统没有相应的表示,所以它假装Class<Bar<T>>
和Class<Bar<U>>
是具有不同类型的完全独立的对象。)你能得到的最接近的东西是这样的:
<T> Class<? extends Iterable<T>> createClassObject
(final String className, final Class<T> clazz) throws Exception
{ return Class.forName(className).asSubclass(getIterableTClass(clazz)); }
@SuppressWarnings("unchecked")
<T> Class<? extends Iterable<T>> getIterableTClass(final Class<T> clazz)
{ return (Class<? extends Iterable<T>>)(Class<?>)Iterable.class; }
使用未检查强制转换来欺骗编译器,使其认为它有足够的关于Foo<T>
(在本例中是Iterable<T>
)的信息来执行asSubclass
检查。
然而,如果返回的类是不是应该是通用的(Bar extends Foo<String>
或什么的),那么我不确定;我从来没有过多地讨论过与此相关的反射部分,尽管我知道它们是存在的。我很确定他们会允许你检查足够的Bar
的继承层次结构,以确定它是否真的扩展了Foo<String>
,但我真的不知道他们是否会给你一种方法,让编译器意识到你已经这样做了。
可以做到。在NetBeans IDE 7中,我没有得到任何警告。
更正:对不起,这不能工作,没有类构造。当然,你可以使用ClassLoader、代理类或ASM。
public class Bar<T> extends Foo<T> {
}
这真的是合乎逻辑和简单。线索可能是执行链式newInstance()。
public <T> Class<? extends Foo<T>> createClassObject(String className, Class<T> classTypeVariable) {
try {
Class<? extends Class> resultType = Bar.class.getClass();
return resultType.getConstructor(classTypeVariable).newInstance();
} catch (InstantiationException ex) {
throw new IllegalStateException(ex);
} catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
} catch (IllegalArgumentException ex) {
throw new IllegalStateException(ex);
} catch (InvocationTargetException ex) {
throw new IllegalStateException(ex);
} catch (NoSuchMethodException ex) {
throw new IllegalStateException(ex);
} catch (SecurityException ex) {
throw new IllegalStateException(ex);
}
}