My Reflections on Java

August 21, 2008

Static Member Classes

You can view all my Posts at jgenius.blogspot.com

Suggested Path:
Static Member Classes
Non-Static Member Classes
Local Classes

Static Member Classes

In this post I will tell you everything about Static Member Classes from inside out. You must have been frustrated by remembering about the rules governing Inner Classes. In this post I will tell you how Inner Classes actually work. This will help you get a deep knowledge of Inner Classes which will help you a lot. This code will tell how the compiler changes the Inner Classes. But remember, that is a some difference in the code given here and what is generated by the compiler. This article uses a simplified approach by removing and modifying some of the code generated by the compiler.
Static Member Classes can also be called as Static Inner Classes. To begin with let me tell you in brief about Static Member Classes.

  • They can be declared inside top-level classes or other Static Member Classes
  • These are declared within other classes with the static modifier.
  • They can declare static and non-static members.
  • All accessibility modifiers can be used with these classes.
  • To create an object of Static Member Class, you don’t need an instance of its enclosing class.
  • An instance of enclosing class is not stored in an instance of a Static Member Class.
  • They can access static members of the enclosing class including private static members.
  • They can access non-static members of the enclosing class(including private non-static members) on an object of the enclosing class.
  • The reverse is also correct i.e. members of the enclosing class can access static members of the Member Class directly and non-static members of the Member Class on an Object of the Member Class.

If you are astonished by the above list of information, don’t worry. In the course of this tutorial, you will come across all these facts.
Now let’s begin one by one how the compiler changes different types of codes in an inner class. By the end you will know completely how all the code in an inner class is transformed to make the inner class a normal top level class.

First lets see how an inner class accesses static members of the enclosing class by their names.

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

class Outer
{
    static int a = 10;
    static class Inner
    {
        void display()
        {
            System.out.println(a);    //displays 10
        }
    }
}

Now when you compile the program the compiler converts the class Inner to a normal top level class. But now the question arises that what will happen to Statement # 8. Well the answer is simple, the compiler adds the name of the enclosing class i.e. Outer before the name of the variable a. So after compilation, the program given above will look like this-

Code after Comilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

class Outer
{
    static int a = 10;
}
class Outer$Inner
{
    void display()
    {
        System.out.println(Outer.a);    //displays  10
    }
}

Note the name of the member(inner) class after compilation. The compiler adds the name of the enclosing class before the name of the member class seperated by a $. The static keyword is also gone as top-level classes cannot be static. To access the member class from any code outside the enclosing class, you have to use the syntax <enclosingClassName>.<memberClassName>. So to access the class Inner from outside the class Outer you will have to use the name of the class as Outer.Inner.
Now you know that members of a class can access private members of the class. So a member class can also access the private members of the enclosing class. But how can the member class access private members of the enclosing class after compilation. Since after compilation the member class is converted into a normal top-level class, so it has no direct access to the private members of the enclosing class. But the compiler creates some package visible methods to make this possible.

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

class Outer
{
    private static int a = 10;
    static class Inner
    {
        void display()
        {
            System.out.println(a);    //displays 10
        }
    }
}

Now after compilation the class Inner will become a top-level class. At Statement # 8 the compiler adds a method call since this statement tries to access a private member of the enclosing class. Lets see how this happens-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.

class Outer
{
    private static int a = 10;
    static int access$000()
    {
        return a;
    }
}
class Outer$Inner
{
    void display()
    {
        System.out.println(Outer.access$000()); //displays 10
    }
}

Look how cleverly the compiler generates a method at Statement # 4 which has access to private members of the class. This method returns the value of the static field a. Notice the ugly name of the compiler generated method. You cannot explicitly call this method in your code because the compiler will flag it as an error. If a local declaration or a field in the inner class or its super class hides the field of the enclosing class, you can access the field by placing the name of the enclosing class before the field name. It goes like this-

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.

class Outer
{
    static int a = 10;
    private static int b = 20;
    static class Inner
    {
        String a;
        String b;
        void display()
        {
            System.out.println(Outer.a);    //displays 10
            System.out.println(Outer.b);    //displays 20
        }
    }
}

The compiler generated code will look like this-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

class Outer
{
    static int a = 10;
    private static int b = 20;
    static int access$000()
    {
        return b;
    }
}
class Outer$Inner
{
    String a;
    String b;
    void display()
    {
        System.out.println(Outer.a);            //displays 10
        System.out.println(Outer.access$000()); //displays 20
    }
}

Now that you know everything about how a Static Member Class can access all the static members of the enclosing class, lets see how the static member class accesses the non-static members of the enclosing class on an object of the enclosing class.

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

class Outer
{
    int a = 10;
    private int b = 20;
    static class Inner
    {
        void display()
        {
            Outer outer = new Outer();
            System.out.println(outer.a);    //displays 10
            System.out.println(outer.b);    //displays 20
        }
    }
}

There is no problem in the Statement # 10 as it accesses a non-private member of the enclosing class. There is nothing wrong with it. But Statement # 11 tries to access a private member of the enclosing class. This is how it is made possible after compilation-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.

class Outer
{
    int a = 10;
    private int b = 20;
    static int access$000(Outer outer)
    {
        return outer.b;
    }
}
class Outer$Inner
{
    void display()
    {
        Outer outer = new Outer();
        System.out.println(outer.a);                 //displays 10
        System.out.println(Outer.access$000(outer)); //displays 20
    }
}

In this case the compiler generates a static package visible method at Statement # 5 which takes an object of the enclosing class as parameter. Statement # 16 accesses the private non-static member of the enclosing class by calling this method and sending the instance of the enclosing class as argument. The method returns the value of the field on the object passed to it.
Till now you have only seen how to access the value of fields from an Inner Class. But you can also mutate i.e. set the value of fields and make method calls. The example below shows you how this happens for non-private members-

Code

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.

class Outer
{
    int a = 10;
    static int b = 20;
    int getProduct()
    {
        return a * b;
    }
    static int getCube()
    {
        return b * b * b;
    }
    static class Inner
    {
        void display()
        {
            b = 2;
            System.out.println(b);                  //displays 2
            System.out.println(getCube());              //displays 8
            Outer outer = new Outer();
            outer.a = 100;
            System.out.println(outer.getProduct());     //displays 200
            System.out.println(outer.a);            //displays 100
        }
    }
}


There is not much changes made in this code by the compiler. So the code after compilation would look as-

Code after Compilation

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.

class Outer
{
    int a = 10;
    static int b = 20;
    int getProduct()
    {
        return a * b;
    }
    static int getCube()
    {
    return b * b * b;
    }
}
class Outer$Inner
{
    void display()
    {
        Outer.b = 2;
        System.out.println(Outer.b);                //displays 2
        System.out.println(Outer.getCube());    //displays 8
        Outer outer = new Outer();
        outer.a = 100;
        System.out.println(outer.getProduct()); //displays 200
        System.out.println(outer.a);                //displays 100
    }
}


The compiler adds the name of the class Outer before the field and method names at Statements # 18, 19 and 20. This is the only change made by the compiler (apart from making the class Inner a top level class). Its easy enough! But if what we are trying to access is private member of the enclosing class, then the code becomes a bit complicated. Lets see how you can mutate the values of private fields of the enclosing class-

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

class Outer
{
    private int a = 10;
    private static int b = 20;
    static class Inner
    {
        void display()
        {
            b = 2;
            Outer outer = new Outer();
            outer.a = 100;
        }
    }
}

For Statement # 9 the compiler will generate a static package visible method that takes the value that you set with the assignment. For Statement # 11 the compiler generates another static package visible method that takes the object of the class Outer and the value that you assign to the field. These methods are shown at Statements # 5 and 9 in the code below-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.

class Outer
{
    private int a = 10;
    private static int b = 20;
    static void access$000(int val)
    {
        b = val;
    }
    static void access$100(Outer outer, int val)
    {
        outer.a = val;
    }
}
class Outer$Inner
{
    void display()
    {
        Outer.access$000(2);              //b = 2;
        Outer outer = new Outer();
        Outer.access$100(outer, 100);     //outer.a = 100;
    }
}

The statements at Statements # 18 and 20 are generated by the compiler. The original statements are shown in comments. Now lets see how you can call private methods of the enclosing class-

Code

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.

class Outer
{
    private void getProduct(int x, int y)
    {
        System.out.println(x * y);
    }
    private static int getCube(int x)
    {
        return x * x * x;
    }
    static class Inner
    {
        void display()
        {
            System.out.println(getCube(3));    //displays 9
            Outer outer = new Outer();
            outer.getProduct(10,20);           //displays 200
        }
    }
}


For both these methods, the compiler generates static package visible methods which inturn calls these methods which are unavailable to the inner class after compilation. The methods generated by the compiler for the mehods and their call are shown in the code below-

Code after Compilation

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.

class Outer
{
    private void getProduct(int x, int y)
    {
        System.out.println(x * y);
    }
    private static int getCube(int x)
    {
        return b * b * b;
    }
    static int access$000(int x)
    {
        return getCube(x);
    }
    static void access$100(Outer outer, int x, int y)
    {
        outer.getProduct(x, y);
    }
}
class Outer$Inner
{
    void display()
    {
        System.out.println(Outer.access$000(3)); //System.out.println(getCube(3));
        Outer outer = new Outer();
        Outer.access$100(outer, 10, 20);         //outer.getProduct(10, 20);
    }
}


The methods at Statements # 11 and 15 call the methods getCube() and getProduct() respectively. The methods calls at Statements # 24 and 27 are generated by the compiler. The original calls are shown in comments. Lets see the opposite of this i.e. accessing the private members of the inner class from the members of the enclosing class.

Code

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.

class Outer
{
    static class Inner
    {
        static int staticVal = 10;
        int nonPrivateVal = 20;
        private int privateVal = 30;
        private void nonPrivateDisplay()
        {
            System.out.println("Non-Private Display!");
        }
        private void privateDisplay()
        {
            System.out.println("Private Display!");
        }
    }
    void display()
    {
            System.out.println(Inner.staticVal);    //displays 10
            Inner in = new Inner();
            System.out.println(in.nonPrivateVal);   //displays 20
            System.out.println(in.privateVal);      //displays 30
            in.nonPrivateDisplay();             //displays Non-Private Display!
            in.privateDisplay();                    //displays Private Display!
    }
}


The compiler will generate package visible methods for the access statements at Statements # 22 and 24. So the code would look like this-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.

class Outer
{
    void display()
    {
        System.out.println(Inner.staticVal);            //displays 10
        Outer.Inner in = new Outer.Inner();
        System.out.println(in.nonPrivateVal);           //displays 20
        System.out.println(Outer.Inner.access$000(in)); //displays 30
        in.nonPrivateDisplay();                             //displays Non-Private Display!
        Outer.Inner.access$100(in);                     //displays Private Display!
    }
}
class Outer$Inner
{
    static int staticVal = 10;
    int nonPrivateVal = 20;
    private int privateVal = 30;
    private void nonPrivateDisplay()
    {
        System.out.println("Non-Private Display!");
    }
    private void privateDisplay()
    {
        System.out.println("Private Display!");
    }
    static int access$000(Outer outer)
    {
        return outer.privateVal;
    }
    static void access$100(Outer outer)
    {
        outer.privateDisplay();
    }
}

Note that I have used the name Outer.Inner to represent the inner class in the enclosing class at Statements # 6, 8 and 10. This is just to avoid any confusion as the name Outer.Inner must be used to represent the inner class from any code outside the enclosing class. There is one last thing that you must note before we move to Non Static Member Classes. If you don’t access some members of the enclosing class from the inner class then the compiler doesn’t generates methods for them. For Example-

Code
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

class Outer
{
    static int a = 10;
    static class Inner
    {
        void display()
        {
            System.out.println("Hello!");
        }
    }
}

The code above will not be altered much by the compiler. Since the field a is not accessed in the inner class so no method will be generated for that. So the code after compilation will look like this-

Code after Compilation
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.

class Outer
{
    private static int a = 10;
}
class Outer$Inner
{
    void display()
    {
        System.out.println("Hello!");
    }
}

I think now you know about Static Member classes from inside out. I hope this will help you a lot. View my other posts to learn more about the other forms of Inner Classes.

The next recommended post is about Non-Static Member classes which you can view at jgenius.blogspot.com

Blog at WordPress.com.