我可以reflection性地在java中实例化generics类型吗?

是否有可能在Java中reflection性地实例化generics类型? 使用这里描述的技术我得到一个错误,因为类标记不能是通用的。 以下面的例子为例。 我想实例化一些实现Creator的Creator子类。 实际的类名称作为命令行参数传入。 我们的想法是能够在运行时指定Creator的实现。 还有另一种方法来完成我在这里要做的事情吗?

public interface Creator { T create(); } public class StringCreator implements Creator { public String create() { return new String(); } } public class FancyStringCreator implements Creator { 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> creatorClass = someClass.asSubclass(Creator.class); Constructor<? extends Creator> creatorCtor = creatorClass.getConstructor((Class[]) null); Creator creator = creatorCtor.newInstance((Object[]) null); } 

编辑:我喜欢马库斯的方法是最简单务实的,不会绕过整个仿制品。 我可以在我的情况下使用它,因为我可以指定传递的类必须是StringCreator的子类。 但正如Ericson所指出的那样,通用信息仍然存在于类型级别,而不是在运行时级别,因此仍然可以reflection性地检查给定类是否实现了正确的generics类型。

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

 public interface Creator { T create(); } public interface StringCreator extends Creator { } 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 creatorClass = someClass.asSubclass(StringCreator.class); Constructor creatorCtor = creatorClass.getConstructor((Class[]) null); Creator creator = creatorCtor.newInstance((Object[]) null); } 

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

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

这将在您提供类型安全的同时完成您要做的事情。 没有办法避免未经检查的警告,但这里完成的类型检查certificate了它的抑制。

  public static void main(String[] args) throws Exception { Class> clz = load(argv[0], String.class); Constructor> ctor = clz.getConstructor(); Creator creator = ctor.newInstance(); System.out.println(creator.create()); } public static  Class> load(String fqcn, Class type) throws ClassNotFoundException { Class any = Class.forName(fqcn); for (Class clz = any; clz != null; clz = clz.getSuperclass()) { for (Object ifc : clz.getGenericInterfaces()) { if (ifc instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) ifc; if (Creator.class.equals(pType.getRawType())) { if (!pType.getActualTypeArguments()[0].equals(type)) throw new ClassCastException("Class implements " + pType); /* We've done the necessary checks to show that this is safe. */ @SuppressWarnings("unchecked") Class> creator = (Class>) any; return creator; } } } } throw new ClassCastException(fqcn + " does not implement Creator"); } 

您必须遵守的主要限制是层次结构中的类必须指定类型参数。 例如, class MyCreator implements Creator 。 您不能将它与class GenericCreator implements Creator

它目前不处理创建新接口interface StringCreatorIfc extends Creator的有效情况interface StringCreatorIfc extends Creator ,并具有类实现。 可以通过增强来做到这一点,但我会将其作为锻炼对象。

你不需要那条线。 您也不需要构造函数,因为您只使用默认构造函数。 直接实例化该类:

 public static void main(String[] args) throws Exception { Class someClass = Class.forName(args[0]); Creator creator = (Creator) someClass.newInstance(); } 

如果你坚持,你只能在那里中途:

 public static void main(String[] args) throws Exception { Class someClass = Class.forName(args[0]); Class creatorClass = someClass.asSubclass(Creator.class); Constructor creatorCtor = creatorClass.getConstructor((Class[]) null); Creator creator = (Creator) creatorCtor.newInstance((Object[]) null); } 

不太清楚为什么你在这里使用generics。

使用reflection实例化对象会建议一般使用,但可能你会在某个时候调用create并将结果赋给String ,否则为什么要使用generics来控制返回类型。

但是如果您编写了以下Creator实现:

 public class IntegerCreator implements Creator { public Integer create() { ... } } 

并将其作为参数传递给调用create并分配结果时会得到ClassCastException。