动态地使用泛型实例化类型

时间:2012-09-21 20:05:06

标签: java generics reflection

我猜我绝对不可能做到这样的事情:

Class c = Class.forName("Processor<Integer, String>");
在Java中

? (当然,我之前定义过处理器)。

2 个答案:

答案 0 :(得分:2)

绝对没办法,因为泛型参数只能在编译时存在。 Class对象在运行时是相同的。它不是C ++中的类模板。类型参数只是java编译器的信息。

您可以尝试通过创建类来完成类似的事情:

class IntStringProcessor extends Processor<Integer, String> {}

Class c = Class.forName("IntStringProcessor");

在运行时,您可以通过Processor获取实际的c.getGenericSuperclass()类型参数,但这扩展了我猜的问题。

编辑:另一个想法

您的Processor可能会将classess作为参数保留,然后:

Class c1 = Class.forName("java.lang.Integer");
Class c2 = Class.forName("java.lang.String");
Processor = new Processor(c1,c2);

您的处理器现在不是通用的,但在内部使用Class实例。正如我所说,没有办法在运行时创建通用实例,因为泛型仅在编译时存在。

答案 1 :(得分:0)

首先让我理顺一些事情。 Class中的Java中没有Processor<Integer, String>个对象。 Class只有一个Processor对象,即Processor.class,所有通用实例都共享相同的Class对象:

    Processor<Integer, String> x = new Processor<Integer, String>();
    Processor<Character, Byte> y = new Processor<Character, Byte>();
    System.out.println(x.getClass() == y.getClass());        // prints true

话虽如此,如果您只需要传递泛型类型的令牌,则可以使用第三方实现。我在这里使用Java ClassMate

    TypeResolver typeResolver = new TypeResolver();
    // type token for Processor<Integer, String>
    ResolvedType type = typeResolver.resolve(Processor.class, Integer.class, String.class);
    System.out.println("type = " + type);

如果您从文件中读取Java类型的名称为String,则可能需要使用Class.forName()而不是.class文字。

你必须自己解析<>括号,但这应该很容易,因为这些单个字符在Java类型名称中总是意味着相同的东西......

您可以像这样形成嵌套参数:

    // type token for Processor<Processor<Integer, String>, Character>
    ResolvedType type = typeResolver.resolve(Processor.class,
            typeResolver.resolve(Processor.class, Integer.class, String.class),
            typeResolver.resolve(Character.class)
    );
    System.out.println("type = " + type);

如果要为编译时知道的类型创建类型标记,可以使用所谓的super-type-token pattern。只需在new GenericType<...>() {}内添加所需的任何类型名称:

    type = typeResolver.resolve(new GenericType<Processor<Processor<Integer, String>, Character>>() {});
    System.out.println("type = " + type);