javagenericsinstantiationexception

InstantiationException when using a generic java class


I would like to create a simulation containing an entity. There can be two kinds of entities, complex and simple ones. When I instantiate a simple simulation, I want the simple entity to be instantiated, and when I instantiate a complex simulation I want the complex entity to be instantiated.

Entities:

class ComplexEntity extends Entity {
    public ComplexEntity(){}
}

class SimpleEntity extends Entity  {
    public SimpleEntity(){}
}

class Entity {
    public Entity(){}
}

Simulations:

class ComplexSimulation extends Simulation<ComplexEntity>
{

    public ComplexSimulation() throws InstantiationException, IllegalAccessException {
        super(ComplexEntity.class);
    }

}

class SimpleSimulation extends Simulation<SimpleEntity>
{
    public SimpleSimulation() throws InstantiationException, IllegalAccessException
    {
        super(SimpleEntity.class);
    }
}

class Simulation<E extends Entity> {
    protected final E entity;

    public Simulation(Class<E> class1) throws InstantiationException, IllegalAccessException 
    {
        entity = class1.newInstance();
    }
}

The problem is that when I try to construct a ComplexSimulation:

ComplexSimulation c = new ComplexSimulation();

I get the following InstantiationException:

java.lang.InstantiationException: test.Test$ComplexEntity
at java.lang.Class.newInstance(Unknown Source)
at test.Test$Simulation.<init>(Test.java:55)
at test.Test$ComplexSimulation.<init>(Test.java:37)
at test.Test.go(Test.java:12)
at test.Test.main(Test.java:6)
Caused by: java.lang.NoSuchMethodException: test.Test$ComplexEntity.<init>()
at java.lang.Class.getConstructor0(Unknown Source)

The zero argument constructor cannot be the problem because my entities have them... Does anybody know what the problem can be?


Solution

  • The problem is that you're using inner classes. You cannot create an instance of an inner class without an instance of the outer class, not even if you call Class<InnerClass>.newInstance().

    Just make these inner classes to be top classes and your example should work as expected.

    If you really want/need to initialize non-static inner classes using reflection, see here: How to instantiate inner class with reflection in Java?