我可以在java中反射性地实例化一个泛型类型吗? [英] can I reflectively instantiate a generic type in java?

查看:122
本文介绍了我可以在java中反射性地实例化一个泛型类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能在Java中反射性地实例化泛型类型?使用这里描述的技术,我得到一个错误,因为类标记不能是通用的。以下面的例子。我想实例化实现Creator的Creator的一些子类。实际的类名称作为命令行参数传入。这个想法是能够在运行时指定Creator的实现。

  public interface Creator< T>是否有另一种方法来完成我在此尝试做的事情? {
T create();
}
public class StringCreator实现了Creator< String> {
public String create(){return new String(); }
}
public class FancyStringCreator实现了Creator< String> {
public String create(){return new StringBuffer()。toString(); }
}
public static void main(String [] args)throws Exception {
Class<?> someClass = Class.forName(args [0]);
/ *错误* / Class <?扩展Creator< String>> creatorClass = someClass.asSubclass(Creator.class);
构造函数<?扩展Creator< String>> creatorCtor = creatorClass.getConstructor((Class <?>> [])null);
Creator< String> creator = creatorCtor.newInstance((Object [])null);





编辑:我喜欢马库斯的方法,因为它是最简单实用的方法,没有规避整个泛型的东西。我可以在我的情况中使用它,因为我可以指定传递的类必须是StringCreator的子类。但是正如Ericson所指出的那样,通用信息仍然存在于类型级别,而不是在运行级别,因此仍然可以反思性地检查给定的类是否实现了正确的泛型类型。

解决方案

通用信息在运行时丢失。没有运行时等效的Creator< String> .class。您可以在Creator和StringCreator之间创建一个类型,修复泛型类型:

  public interface Creator< T> {
T create();
}
public interface StringCreator扩展了Creator< String> {}
public class StringCreatorImpl implements StringCreator {
public String create(){return new String(); }
}
public class FancyStringCreator implements StringCreator {
public String create(){return new StringBuffer()。toString(); }
}
public static void main(String [] args)throws Exception {
Class<?> someClass = Class.forName(args [0]);
Class <?扩展StringCreator> creatorClass = someClass.asSubclass(StringCreator.class);
构造函数<?扩展StringCreator> creatorCtor = creatorClass.getConstructor((Class <?>> [])null);
Creator< String> creator = creatorCtor.newInstance((Object [])null);
}

但是当然你会失去一点灵活性,因为你不能使用以下创建者类:

 公共类AnotherCreator实现了Creator< String> {
public String create(){return; }
}


Is it possible to reflectively instantiate a generic type in Java? Using the technique described here I get an error because class tokens cannot be generic. Take the example below. I want to instantiate some subclass of Creator that implements Creator. The actual class name is passed in as a command line argument. The idea is to be able to specify an implementation of Creator at runtime. Is there another way to accomplish what I'm trying to do here?

public interface Creator<T> {
    T create();
}
public class StringCreator implements Creator<String> {
    public String create() { return new String(); }
}
public class FancyStringCreator implements Creator<String> {
    public String create() { return new StringBuffer().toString(); }
}
public static void main(String[] args) throws Exception {
    Class<?> someClass = Class.forName(args[0]);
    /*ERROR*/Class<? extends Creator<String>> creatorClass = someClass.asSubclass(Creator.class);
    Constructor<? extends Creator<String>> creatorCtor = creatorClass.getConstructor((Class<?>[]) null);
    Creator<String> creator = creatorCtor.newInstance((Object[]) null);
}

Edit: I like Marcus' approach as being the most simple and pragmatic without circumventing the whole generics thing. I can use it in my situation because I can specify that the class passed must be a subclass of StringCreator. But as Ericson pointed out the generic information is still there at the type level, just not at the runtime level so it is still possible to reflectively examine whether a given class implements the correct generic type.

解决方案

The generic information is lost in runtime. There is no runtime equivalent of a Creator<String>.class. You could create a type between Creator and StringCreator which fixes the generic type:

public interface Creator<T> {
        T create();
}
public interface StringCreator extends Creator<String> { }
public class StringCreatorImpl implements StringCreator  {
        public String create() { return new String(); }
}
public class FancyStringCreator implements StringCreator  {
        public String create() { return new StringBuffer().toString(); }
}
public static void main(String[] args) throws Exception {
        Class<?> someClass = Class.forName(args[0]);
        Class<? extends StringCreator> creatorClass = someClass.asSubclass(StringCreator.class);
        Constructor<? extends StringCreator> creatorCtor = creatorClass.getConstructor((Class<?>[]) null);
        Creator<String> creator = creatorCtor.newInstance((Object[]) null);
}

But of course you lose a bit of flexibility, because you cannot use the following creator class:

public class AnotherCreator implements Creator<String> {
    public String create() { return ""; }
}

这篇关于我可以在java中反射性地实例化一个泛型类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆