Friday, September 20, 2013

Java: Get Instance of Inner Class


Today my good unpredictable friend Mishuk gave me a piece of Java code which is full of nested classes. I was not surprised at all as I already know his love for inner classes. Then he asked me whether it is possible to call a method from the innermost class, i.e. is it possible to get an instance of the nested classes. At first I thought how hard could it be, but it eventually turned out to be thought provoking. It was not as straight forward for me as I thought (I won't deny, I know a very little Java, which is why this little bit of trick had surprised me). So I just wanted to put it up here for future references.

The class he gave me follows:

  1. class A {
  2. String name="A";
  3. public class B {
  4. String name="B";
  5. public class C {
  6. String name= "C";
  7. public void print(String name){
  8. System.out.println(name);
  9. System.out.println(C.this.name);
  10. System.out.println(B.this.name);
  11. System.out.println(A.this.name);
  12. }
  13. }
  14. }
  15. }

As there was a restriction that the above code can't be modified, the only way to do this is to somehow get instances in a hierarchical manner. Because you cannot get instances of B without creating an instance of A and so on. But Java has a cool thing called reflection, and using reflection, it is possible to get instances from the inner class as well. So here is how the print() method from class C can be called. The idea is to create instances following the hierarchical order and then use the last one. Now it seems easy!

  1. import java.lang.reflect.*;
  2.  
  3. class Main {
  4. public static void main(String[] args) throws Exception {
  5. Class classAB = A.B.class;
  6. Class classABC = A.B.C.class;
  7. Constructor constructorAB = classAB.getConstructor(A.class);
  8. Constructor constructorABC = classABC.getConstructor(A.B.class);
  9. A instanceA = new A();
  10. A.B instanceAB = constructorAB.newInstance(instanceA);
  11. A.B.C instanceABC = constructorABC.newInstance(instanceAB);
  12. instanceABC.print("JAVA SUCKS WITHOUT REFLECTION");
  13. }
  14. }

Oh, one more thing, for those who don't know this yet and too lazy to run some Java codes, here is the output:

JAVA SUCKS WITHOUT REFLECTION
C
B
A

Yah I know this may be done in hundreds of different ways and exceptions should be handled and and and and .... who cares?