当前位置:  开发笔记 > 编程语言 > 正文

我可以在java中反射性地实例化泛型类型吗?

如何解决《我可以在java中反射性地实例化泛型类型吗?》经验,为你挑选了2个好方法。

是否有可能在Java中反射性地实例化泛型类型?使用这里描述的技术我得到一个错误,因为类标记不能是通用的.以下面的例子为例.我想实例化一些实现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> creatorClass = someClass.asSubclass(Creator.class);
    Constructor> creatorCtor = creatorClass.getConstructor((Class[]) null);
    Creator creator = creatorCtor.newInstance((Object[]) null);
}

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



1> 小智..:

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

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 ""; }
}



2> erickson..:

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

  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,并且具有类实现.可以通过增强来做到这一点,但我会将其作为锻炼对象.

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有