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:

class A {
    String name="A";
   
    public class B {
        String name="B";
       
        public class C {
            String name= "C";
           
            public void print(String name){
                System.out.println(name);
                System.out.println(C.this.name);
                System.out.println(B.this.name);
                System.out.println(A.this.name);                               
            }
        }
    }
}

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!

import java.lang.reflect.*;

class Main {
    public static void main(String[] args) throws Exception {
        Class classAB = A.B.class;
        Class classABC = A.B.C.class;
        Constructor constructorAB = classAB.getConstructor(A.class);
        Constructor constructorABC = classABC.getConstructor(A.B.class);
        A instanceA = new A();
        A.B instanceAB = constructorAB.newInstance(instanceA);
        A.B.C instanceABC = constructorABC.newInstance(instanceAB);
        instanceABC.print("JAVA SUCKS WITHOUT REFLECTION");
    }
}

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?


2 comments:

  1. O yaa... java definitely sucks without reflection. You can even call private method of a class through reflection. Offtopic but thought would show off in name of knowledge sharing :p
    [code]
    /*
    Accessing a Class's private member
    Demonstrates : reflection
    FileName : PrivateAccess.java

    Author : dumb_terminal
    */

    import java.lang.reflect.Method ;

    class privateClass{
    private void sum(int a, int b){
    int s = a + b ;
    System.out.println("sum : " + s) ;
    }
    }

    class accessClass{
    public static void main(String [] args) throws Exception{
    privateClass p = new privateClass() ;
    Class [] params = {int.class, int.class} ;
    Method privateMethod = p.getClass().getDeclaredMethod("sum", params) ;
    privateMethod.setAccessible(true) ;
    privateMethod.invoke(p, 2, 3) ;
    }
    }

    [/code]

    ReplyDelete