简体   繁体   English

从类文件实例化通用参数化类型

[英]Instantiating Generic Parameterized Type from class file

So a client will create a class in the following fashion: 因此,客户端将以以下方式创建类:

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

Then the client will pass the .class file (IE Tester.class) to us. 然后,客户端会将.class文件(IE Tester.class)传递给我们。

We would then like to instantiate the client's class and run their method1 based on the types that the generic uses. 然后,我们想实例化客户端的类,并根据泛型使用的类型运行其method1。 I have the following code so far but I don't think I'm going down the right path: 到目前为止,我有以下代码,但我认为我没有走正确的道路:

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

But eclipse is giving me a lot of errors in the Class> line, so I don't think this is the right path. 但是eclipse在Class>行中给了我很多错误,所以我认为这不是正确的方法。 What am I doing wrong? 我究竟做错了什么?

Tere are a couple of issues here... Tere这里有几个问题...

First, both Classname.class is inherently static construct - it is even called class literal . 首先,这两个Classname.class本质上都是静态构造-甚至都称为文字 Hence, type name cannot be supplied at runtime, that's why Eclipse complains about your attempt to do so. 因此,无法在运行时提供类型名称,这就是Eclipse抱怨您尝试这样做的原因。 To obtain the Class object given the class name as the string, you can use Class.forName : 要获得以类名作为字符串的Class对象,可以使用Class.forName

Class<?> tempClass = Class.forName("Tester");

(fully qualified name and no .class suffix). (全限定名,没有.class后缀)。

Second, so is Tester<Type1, Type2, Type3> . 其次, Tester<Type1, Type2, Type3> Type arguments must be known at the compile time. 在编译时必须知道类型实参。 Now, I'm not sure why you needed this cast in this place, but I see a couple of possible reasons: 现在,我不确定为什么在这个地方需要这个演员表,但是我看到了两个可能的原因:

  • To ensure the class represented by tempClass does implement the appropriate interface - then it is of no use even if it was a syntactically legal construct. 为了确保由tempClass表示的类确实实现了适当的接口,那么即使它在语法上是合法的,也没有用。 Casting cannot dynamically check generic type arguments, since they are also entirely compile-time construct - they are not available in runtime, due to type erasure . 强制转换无法动态检查泛型类型参数,因为它们也完全是编译时构造的-由于类型擦除 ,它们在运行时不可用。 To check if a given Class object A is a subclass/implementation of type represented by Class object B, we can use Class.isAssignableFrom : 要检查给定的Class对象A是否是Class对象B表示的类型的子类/实现,我们可以使用Class.isAssignableFrom

     if (B.isAssignableFrom(A)) { // ... } 
  • To avoid warnings - sorry, such casts really are unchecked, as there is no way to ensure its correctness at runtime - again, due to type erasuer. 为了避免警告-对不起,这种类型转换真的是不加以控制,因为没有办法,以确保它的正确性在运行时-再次,由于输入erasuer。 Use @SuppressWarnings in places where you know cast is valid, and Java type system is too dumb to be able to verify your claim. 在您知道@SuppressWarnings有效且Java类型系统太笨而无法验证您的声明的地方使用@SuppressWarnings

Anyway, don't cast the class. 无论如何,不​​要上课。 Instead, cast the result of newInstance invocation. 相反, newInstance调用的结果。 Now, as for running the right methods... Now you have all the information you need, in two pieces: object to invoke methods upon, and type arguments of implemented interface. 现在,关于运行正确的方法...现在,您将获得所需的所有信息,分为两部分:调用方法的对象和已实现接口的参数类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM