从类文件实例化泛型参数化类型



所以客户端将以以下方式创建一个类:

public class Tester implements Test<Type1, Type2, Type3> {
    @override
    public method1(...)
    ...
}

然后客户端将.class文件(即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>行中给了我很多错误,所以我认为这不是正确的路径。我做错了什么?

这里有几个问题…

首先,两个Classname.class本质上都是静态构造——它甚至被称为literal。因此,类型名不能在运行时提供,这就是Eclipse抱怨您尝试这样做的原因。要获取给定类名作为字符串的Class对象,您可以使用 class . forname :
Class<?> tempClass = Class.forName("Tester");

(全限定名,无.class后缀)。

第二,Tester<Type1, Type2, Type3>也是。类型参数必须在编译时已知。现在,我不确定为什么在这个地方需要这个角色,但我看到了几个可能的原因:

  • 确保tempClass表示的类确实实现了适当的接口-那么即使它是一个语法上合法的结构也没有用。强制转换不能动态检查泛型类型参数,因为它们也完全是编译时构造——由于类型擦除,它们在运行时不可用。要检查给定的Class对象a是否是由Class对象B表示的类型的子类/实现,我们可以使用Class.isAssignableFrom:

    if (B.isAssignableFrom(A)) {
        // ...
    }
    
  • 为了避免警告——抱歉,这样的强制转换实际上是未检查的,因为没有办法确保其在运行时的正确性——同样,由于类型擦除。在你知道强制类型转换是有效的地方使用@SuppressWarnings,而Java类型系统太笨了,无法验证你的声明。

无论如何,不要强制转换类。相反,转换newInstance调用的结果。现在,至于运行正确的方法…现在您有了所需的全部信息,分为两部分:调用方法的对象和实现接口的类型参数。

相关内容

  • 没有找到相关文章

最新更新