sherrellbc
sherrellbc

Reputation: 4853

How to create an array of class types that can later be instantiated from the list?

I'll preface this question with the fact that I am not a professional Java programmer. I come from a strong C embedded systems background, but was self-taught Java back in college.

I am creating a simple program where there are many different data "producer" classes. Each class generates some kind of data output product.

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)() );

Of course, the above code does not work. I am able to create an ArrayList of class types, but I am not able to instantiate them at a later time (at least I am not able to find the correct syntax to do so).

I also intended originally to do this with interfaces, but the syntax for creating an array of classes does not seem to work like extends in the above code sample. I tried the following, but it failed syntax checking:

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

I searched around for a suitable answer, but not knowing the correct question/terminology to ask can make that difficult. I found this solution, but their intentions may have been different.

Of course, if this can be done in a simpler way then I am open to all suggestions.

Upvotes: 0

Views: 58

Answers (1)

butchyyyy
butchyyyy

Reputation: 355

Assuming all the classes in the list have no-arg constructor, you can instantiate them with

list.get(0).newInstance()

Also this works just fine for interfaces

List<Class<? extends SomeInterface>>

Working example

The Producer interface:

public interface Producer {

  void produce();

}

First implementation:

public class Producer1 implements Producer {

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

Second implementation:

public class Producer2 implements Producer {

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

Report class:

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());
  }

}

Running following main method:

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();
  }

Will output to console:

Producer 1
Producer 2

Upvotes: 2

Related Questions