Here is an interesting concept which I came across just recently and considered it worth sharing. I was reading about inner classes concepts where in, there is a type of inner class called the local inner class. Local inner classes are those classes which reside within the function of a method belonging to an outer class. The code can be something shown like this.

public class LocalInnerClassTest {
	public void defineInnerClass() {
		class MyLocalInnerClass {
			public void doSomething() {				
			}
		}
 
	}
}

Now lets suppose we want to pass a variable in the defineInnerClass() and pass it to the doSomething() for some computation, then according to the specifications on local inner classes methods we must declare the variables as final or else it will result in a compile time error. So the resulting code must be something as follows:

public class LocalInnerClassTest {
	public void defineInnerClass(final int var) {
		class MyLocalInnerClass {
			public void doSomething() {
				System.out.println(var);
			}
		}
	}
}

where var is the variable that must be declared as final to be passed into the doSomething() method of MyLocalInnerClass. Now the mysterious question which I faced was why exactly such a specification has been outlined. Why can’t the inner class simply take the variable as it is and process further.

In order to understand this reason as to why local inner classes can access only final variables, we have to learn how exactly inner classes get translated to the byte code. The moment you come to know this, you can easily see the logic behind making the variables final.

How Are Inner Classes Translated to the Byte Code

Here is the secret. Inner classes as you must have known them from a long time are still mysterious to the JVM. Yes its true. Inner classes have been implemented only to the compiler level. When the classes are compiled which contain inner classes, the byte code which gets generated does not actually implement inner classes as a class within a class. The book on Core Java from makes this statement:

“Inner classes are translated into regular class files with $ (dollar signs) delimiting outer and inner class names and the virtual machine does not have any special knowledge about them”

That means when the above class file from the example is compiled it will generate two class files such as:

  1. LocalInnerClassTest.class
  2. LocalInnerClassTest$MyLocalInnerClass.class

Unfurling the mystery of final variables

If you apply logic to the above theory of inner class at the byte code level, you have the answer to the mystery of having final variables. For explanation purpose, lets take the same example.

First lets say we make a call to the defineInnerClass() by creating an instance of LocalInnerClassTest. At this point, the instance of MyLocalInnerClass is still not present because the JVM treats it as a separate class at the byte code level. So when the call to defineInnerClass() is made the JVM tries to instantiate an object of MyLocalInnerClass.

But here we run into a problem. The function doSomething() accesses the var variable which is passed down from the outer class method. If you can simply apply logic over here, you can see the problem. How should the JVM pass the variable which has been declared in one class file to the method in another class file?

In order to solve this big problem, the JVM acts smart. It makes a requirement for the developer to make the variable passed from the method of an outer class to be declared as final. How would this solve the problem, you may ask? When you declare the variable var as final the compiler does a trick. The trick being, it quietly places a hidden variable with the name val$var inside the 2nd compiled class file.

The variable val$var is assigned the same value which has been assigned to var since now the compiler knows that the value cannot be changed as it has been declared final. This is very clever, since final variable must always be assigned before compilation.

So there you go. Now, when you run the program from within an application the inner class already has the value which has been assigned to var through its inner hidden variable val$var and thus the mystery gets solved. Therefore you have the concept that local inner class methods can have access to only the final variables of the outer class.

Hey, Local Inner Classes can even access Outer Class member variables directly. How?

Ok, now that we have tackled the above mystery, this is more simpler. The below code gets perfectly compiled

public class LocalInnerClassTest {
     private int var2;
     public void defineInnerClass(final int var){
 	  class MyLocalInnerClass{
 		public void doSomething(){
 			System.out.println(var+var2);
 		}
     	  }
     }
}

You can notice that the local inner class has direct access to even the private variable var2 of its outer class. The reason behind the accessibility of outer member variables directly inside the local inner classes is that, once again the compiler cleverly places one more hidden variable named as this$0 which is a final instance variable of the outer class type. When the inner class object is instantiated the variable this$0 is given a reference to the outer variable with direct access privileges. Hence you can access the outer class member variables directly from within the inner class. Smart isn’t it?


Stumble Digg Technorati Subscribe Delicious