如何在运行时将类<t>转换为类似<t extends =“”foo =“”>的类?

时间:2017-06-12 00:23:53

标签: java generics dynamic reflection casting

我有一个如下所示的课程:

class FooClassAnalyser<T extends Foo> extends ClassAnalyser<T>

(其中ClassAnalyser是许多具体实现的抽象基类; FooClassAnalyser是一个专门针对T扩展Foo的案例的具体实现。 {1}})。它有一个如下所示的构造函数:

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))

我的问题是,与instanceof不同,这个&#34;实例通过反射&#34; Java的类型系统是不可见的。特别是,直接将classToAnalyse作为参数传递给FooClassAnalyser的构造函数会因类型不匹配而失败,因为Java并不知道classToAnalyse实际上是{{1} }}

我到目前为止找到的最佳解决方案是使用未经检查的强制转换来使Class<U extends Foo>成为classToAnalyse实际已检查,但Java&#39 ; s不知道它被检查过)。这至少可以将它作为参数传递给Class<? extends Foo>,并获得一个new FooClassAnalyser对象作为回报。然而,问题是,这并没有转换回FooClassAnalyser<?>,因为Java并没有认识到转换ClassAnalyser<U>具有不同的通用绑定但是并没有这样做。改变classToAnalyse对象仍然是同一个对象的事实(因此仍然是Class);换句话说,所有Java都可以看到它是Class<U>,它不能识别也是FooClassAnalyser<?>,因此转换回来需要另一个未经检查的强制转换。结果是编译和运行的代码,但有很多关于类型安全的警告。

我尝试过的大多数其他事情都是语法错误(例如FooClassAnalyser<U>类型的变量无法直接声明; Java没有正确解析它。应该指出的是,我实际上在任何时候都没有Class<U extends Foo>类型的对象;我试图分析类本身,因此只能使用U个对象。

是否可以以类型安全的方式编写这样的代码?

1 个答案:

答案 0 :(得分:0)

  

我的问题是,与instanceof不同,这种“反射实例”对于Java类型系统是不可见的。特别是,直接将classToAnalyse作为参数传递给FooClassAnalyser的构造函数会因类型不匹配而失败,因为Java不知道classToAnalyse实际上是Class<U extends Foo>

只要您将Class<U>传递给constructClassAnalyser,就会发生这种情况。您没有为我们提供太多代码,因此我无法为您编写明确的解决方案;但是,如果您能找到一种方法将U传递给constructClassAnalyser而不是Class<U>,那将会更加简单。

static <U> ClassAnalyser<U> constructClassAnalyser(U objectToAnalyse)

要检查其课程,您可以使用objectToAnalyse#getClass;如果instanceof返回U extends Foo,您还可以使用objectToAnalyse instanceof Foo验证true,然后根据需要将其投放到相应的班级。