Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: How to load a class (and its inner classes) that is already on the class path?

How can I load a class that is already on the class path, instantiate it, and also instantiate any inner classes defined within it?

EG:

public class TestClass {


    public class InnerClass { }

}
like image 346
Zombies Avatar asked May 19 '10 18:05

Zombies


People also ask

How do I access an inner class from another class?

They are accessed using the enclosing class name. To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax: OuterClass.

Can an inner class be used in a class other than the class in which it nests?

An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance. To instantiate an inner class, you must first instantiate the outer class.

Can a Java class contain inner class?

Nested Classes In Java, just like methods, variables of a class too can have another class as its member. Writing a class within another is allowed in Java. The class written within is called the nested class, and the class that holds the inner class is called the outer class.

Can an inner class extend another class?

You can extend static inner class with another inner class.


2 Answers

Inner classes cannot exist outside the parent class. You need to construct the parent class first. Without reflection this would look like:

InnerClass innerClass = new TestClass().new InnerClass();

In reflection, you need to pass the parent class in during construction of the inner class.

Object testClass = Class.forName("com.example.TestClass").newInstance();
for (Class<?> cls : testClass.getClass().getDeclaredClasses()) {
    // You would like to exclude static nested classes 
    // since they require another approach.
    if (!Modifier.isStatic(cls.getModifiers())) {
        Object innerClass = cls
            .getDeclaredConstructor(new Class[] { testClass.getClass() })
            .newInstance(new Object[] { testClass });
    }
}
like image 197
BalusC Avatar answered Sep 30 '22 00:09

BalusC


As a side note, given that your primary question has been answered - often people will declare inner classes as in your example above, without giving a thought to whether they can be static inner classes instead.

In my experience, the vast majority of (non-anonymous) inner classes can be static, as they don't need to access their parent class' instance members. Declaring the inner class as static in this case is both more efficient (as the runtime doesn't need to define a new class for each parent instance), less confusing (since new TestClass().new InnerClass().getClass() != new TestClass().new InnerClass().getClass()) and easier to instantiate if you don't have an appropriate instance of TestClass handy.

So if this applies to you, you could (and arguably should) declare you inner class thusly:

public class TestClass {

    public static class InnerClass { }

}

and then you can simply instantiate it as new TestClass.InnerClass().

(If you need to access member fields from within InnerClass, then just ignore all this of course!)

like image 23
Andrzej Doyle Avatar answered Sep 30 '22 00:09

Andrzej Doyle