【问题标题】:How to create an array of class types that can later be instantiated from the list?如何创建稍后可以从列表中实例化的类类型数组?
【发布时间】:2018-05-18 14:59:05
【问题描述】:

我会以我不是专业的 Java 程序员这一事实作为这个问题的开头。我来自强大的 C 嵌入式系统背景,但在大学时自学了 Java。

我正在创建一个简单的程序,其中有许多不同的数据“生产者”类。每个类都生成某种数据输出产品。

ArrayList< Class<? extends OtherClass> > list = new ArrayList< Class<? extends OtherClass> >();

//Register producers based on some criteria for the analysis being done
list.add(Producer1.class);
list.add(Producer2.class);

//Some time later, I want to create instances of those classes and link them to a 'report'
Report report = new Report();
report.addProducer( new list.get(0)() );

当然,上面的代码是行不通的。我能够创建一个类类型的 ArrayList,但我无法在以后实例化它们(至少我无法找到这样做的正确语法)。

我最初也打算使用interfaces 来执行此操作,但是用于创建类数组的语法似乎不像上述代码示例中的extends 那样工作。我尝试了以下方法,但语法检查失败:

ArrayList< Class<? implements OtherClass> > list = new ArrayList< Class<? implements OtherClass> >();

我四处寻找合适的答案,但不知道要问的正确问题/术语会使这变得困难。我找到了this 解决方案,但他们的意图可能不同。

当然,如果这可以通过更简单的方式完成,那么我愿意接受所有建议。

【问题讨论】:

  • extends 关键字用于泛型类型定义中的类和接口。你只需要list.get(i).newInstance() 来实例化类的一个对象(它需要有零参数的构造函数)。

标签: java class interface


【解决方案1】:

假设列表中的所有类都有无参数构造函数,您可以使用实例化它们

list.get(0).newInstance()

这也适用于接口

List<Class<? extends SomeInterface>>

工作示例

生产者界面:

public interface Producer {

  void produce();

}

第一次实现:

public class Producer1 implements Producer {

  @Override
  public void produce() {
    System.out.println("Producer 1");
  }
}

第二次实施:

public class Producer2 implements Producer {

  @Override
  public void produce() {
    System.out.println("Producer 2");
  }
}

报告类:

public class Report {

  private final List<Producer> producers = new ArrayList<>();

  public void addProducer(Producer producer) {
    producers.add(producer);
  }

  public void produce() {
    producers.forEach((p) -> p.produce());
  }

}

运行以下主要方法:

public static void main(String[] args) {
    Report report = new Report();
    List<Class<? extends Producer>> producers = new ArrayList<>();
    producers.add(Producer1.class);
    producers.add(Producer2.class);
    producers.forEach((p) -> {
      try {
        report.addProducer(p.newInstance());
      } catch (InstantiationException | IllegalAccessException ex) {
        System.out.print("Ooops");
      }
    });
    report.produce();
  }

将输出到控制台:

Producer 1
Producer 2

【讨论】:

  • 我有以下代码案例,其中此方法不起作用。这段代码有什么问题? ideone.com/WOUAip。我也尝试过使用MyInnerClass.class 而不是MyInnerClass.class.getName(),但两者都不起作用。这是需要从父类中实例化嵌套内部类的特殊情况,所以应该可以吗?
  • 运行时不存在泛型类型,您通过返回 Class>(不是 Class)的反射 (forName) 获得 MyInnerClass.class。您可以通过更改变量类型或进行不安全强制转换来解决此问题。至于实例化内部类。您将需要一个外部类实例来执行此操作。结帐ideone.com/AH5vI3
猜你喜欢
  • 2019-05-19
  • 2017-12-18
  • 2013-12-02
  • 2022-08-10
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多