0

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.

sherrellbc
  • 4,650
  • 9
  • 48
  • 77
  • Take a look at https://stackoverflow.com/questions/6094575/creating-an-instance-using-the-class-name-and-calling-constructor – Thiyagu May 18 '18 at 15:15
  • The `extends` keyword is used for both classes and interfaces in the generic type definition. You'll just need `list.get(i).newInstance()` to instantiate an object of the class (it needs to have zero-arg constructor). – Kayaman May 18 '18 at 15:23

1 Answers1

2

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
butchyyyy
  • 355
  • 1
  • 10
  • I have the following code case where this method does not work. What is wrong with this code? https://ideone.com/WOUAip. I also tried using `MyInnerClass.class` rather than `MyInnerClass.class.getName()`, but neither one works. This is a special case of needing to instantiate a nested inner class _from within the parent class_, so it should be possible? – sherrellbc May 22 '18 at 14:10
  • Generic types are not present at runtime and you're getting MyInnerClass.class via reflection (forName) which returns Class> (not Class). You can remedy that by changing the variable type or by making an unsafe cast. As for instantiating inner class. You will need an outer class instance to do so. Checkout https://ideone.com/AH5vI3 – butchyyyy May 22 '18 at 20:13