所以客户端将以下列方式创建一个类:
public class Tester implements Test<Type1, Type2, Type3> {
@override
public method1(...)
...
}
然后客户端将.class文件(I.E. Tester.class)传递给我们。
然后,我们希望实例化客户端的类,并根据泛型使用的类型运行其method1。到目前为止,我有以下代码,但我不认为我走的是正确的道路:
//tempClass = <ClassName>.class
Type[] genericTypes;
Type[] genericInterfaces = tempClass.getGenericInterfaces();
if(genericInterfaces[0] instanceof ParameterizedType){
genericTypes = ((ParameterizedType)genericInterfaces[0])
.getActualTypeArguments();
}
Class<Tester<genericTypes[0], genericTypes[1], genericTypes[2]>> classTest
= ( Class<Tester<genericTypes[0], genericTypes[1], genericTypes[2]>>) tempClass
Constuctor<...> = ... //get the constructor
//Create the new instance by calling .newInstance()
但是eclipse在Class&gt;中给了我很多错误。线,所以我不认为这是正确的道路。我做错了什么?
答案 0 :(得分:1)
这里有几个问题......
首先,Classname.class
本身就是静态构造 - 它甚至被称为 class literal 。因此,无法在运行时提供类型名称,这就是Eclipse抱怨您尝试这样做的原因。要获取给定类名作为字符串的Class
对象,可以使用 Class.forName :
Class<?> tempClass = Class.forName("Tester");
(完全限定名称且没有.class
后缀)。
第二,Tester<Type1, Type2, Type3>
也是如此。必须在编译时知道类型参数。现在,我不确定为什么你需要在这个地方进行演员表,但我看到了几个可能的原因:
为了确保tempClass
所代表的类确实实现了适当的接口 - 那么即使它是一个语法上合法的构造也是没用的。转换不能动态检查泛型类型参数,因为它们也完全是编译时构造 - 由于type erasure,它们在运行时不可用。要检查给定的Class
对象A是否是Class
对象B所代表的类型的子类/实现,我们可以使用Class.isAssignableFrom
:
if (B.isAssignableFrom(A)) {
// ...
}
为避免警告 - 抱歉,此类强制转换真的未选中,因为无法确保其在运行时的正确性 - 再次,由于类型erasuer。在您知道强制转换的地方使用@SuppressWarnings
,并且Java类型系统太愚蠢,无法验证您的声明。
无论如何,不要去上课。相反,转换newInstance
调用的结果。现在,至于运行正确的方法......现在您拥有所需的所有信息,分为两部分:对象调用方法,并键入已实现接口的参数。