提问人:smithaiw 提问时间:6/12/2017 更新时间:6/12/2017 访问量:435
如何在运行时将 Class<T> 转换为类似于 Class<T 扩展 Foo> 的东西?
How can I cast a Class<T> to something that acts like a Class<T extends Foo> at runtime?
问:
我有一个如下所示的类:
class FooClassAnalyser<T extends Foo> extends ClassAnalyser<T>
(其中是许多具体实现的抽象基类;并且是专门针对扩展情况的具体实现)。它有一个构造函数,如下所示:ClassAnalyser
FooClassAnalyser
T
Foo
FooClassAnalyser(Class<T> classToAnalyse)
在另一个类中,我有一个静态工厂方法,它根据 的类型调用适当的构造函数:ClassAnalyser
classToAnalyse
static <U> ClassAnalyser<U> constructClassAnalyser(Class<U> classToAnalyse)
我想要的功能是检查是否,然后构造一个,如果是,则返回它。U instanceof Foo
FooClassAnalyser
但是,我找不到一种方法将其融入 Java 的类型系统。类型擦除意味着我们不能直接做任何聪明的事情。但是,我们作为参数传入的事实使得测试是否通过使用反射来查看:U
classToAnalyse
U instanceof Foo
if (Foo.class.isAssignableFrom(classToAnalyse))
我的问题是,与此不同的是,这个“通过反射的实例”对 Java 的类型系统是不可见的。特别是,直接作为参数传递给 的构造函数会因类型不匹配而失败,因为 Java 不知道这实际上是 .instanceof
classToAnalyse
FooClassAnalyser
classToAnalyse
Class<U extends Foo>
到目前为止,我发现的最好的解决方案是使用未经检查的强制转换来制作一个(它实际上被检查了,但 Java 不知道它被检查了)。这至少使得将它作为参数传递给 成为可能,并得到一个对象作为回报。然而,问题在于这不会转换回 ,因为 Java 不承认强制转换为具有不同的泛型边界并不能改变对象仍然是同一对象(因此仍然是 );换句话说,Java 所能看到的只是一个它无法识别的 ,也是一个 ,因此转换回来需要另一个未经检查的强制转换。结果是编译和运行的代码,但带有许多有关类型安全的警告。classToAnalyse
Class<? extends Foo>
new FooClassAnalyser
FooClassAnalyser<?>
ClassAnalyser<U>
classToAnalyse
Class
Class<U>
FooClassAnalyser<?>
FooClassAnalyser<U>
我尝试过的大多数其他事情都是语法错误(例如,不能直接声明类型的变量;Java 无法正确解析它)。应该注意的是,我实际上在任何时候都没有类型的对象;我正在尝试分析类本身,因此只有对象可以使用。Class<U extends Foo>
U
Class<U>
是否可以以类型安全的方式编写这样的代码?
答:
我的问题是,与此不同的是,这个“通过反射的实例”对 Java 的类型系统是不可见的。特别是,直接作为参数传递给 的构造函数会因类型不匹配而失败,因为 Java 不知道这实际上是 .
instanceof
classToAnalyse
FooClassAnalyser
classToAnalyse
Class<U extends Foo>
只要您将 a 传递给 .你没有给我们提供太多代码,所以我无法为你写一个明确的解决方案;但是,如果您能找到一种方法来传递而不是 .Class<U>
constructClassAnalyser
U
constructClassAnalyser
Class<U>
static <U> ClassAnalyser<U> constructClassAnalyser(U objectToAnalyse)
要检查其类,可以使用 ;您还可以使用 to 验证 if 返回 ,然后根据需要将其强制转换为其各自的类。objectToAnalyse#getClass
instanceof
U extends Foo
objectToAnalyse instanceof Foo
true
评论
ClassAnalyser
Class#newInstance
final
评论
clazz.asSubclass(Foo.class)。
Class<? extends Foo>
clazz.asSubclass(Foo.class)
Class<? extends Foo>
<U>
FooClassAnalyser<? extends Foo>
ClassAnalyser<U>