Why Java Inner Classes Require "Final" Outer Instance Variables

Why Java inner classes require final outer instance variables?

Well first, let's all relax, and please put that gun down.

OK. Now the reason the language insists on that is that it cheats in order to provide your inner class functions access to the local variables they crave. The runtime makes a copy of the local execution context (and etc. as appropriate), and thus it insists that you make everything final so it can keep things honest.

If it didn't do that, then code that changed the value of a local variable after your object was constructed but before the inner class function runs might be confusing and weird.

This is the essence of a lot of the brouhaha around Java and "closures".


Note: the opening paragraph was a joke in reference to some all-caps text in the original composition of the OP.

Need of final variable in Inner class concept

The reason for this restriction relates mainly to multi-threading issues and ensures that all such variables have well-defined values when accessed from the local inner class. Given that the method accessing the local variable or parameter could be invoked after the completion of the method in which the local inner class was defined and hence the local variables and parameters no longer exist the value of those variables must be frozen before the local inner class object is created. If needed, you can copy a non-final variable into a final one that is subsequently accessed by the local inner class.

Reference
http://cs-fundamentals.com/java-programming/java-method-local-inner-classes.php

Effectively final - Inner classes access

It's because of the scope of the local variables. Their scope is the method in which they are declared. Once execution has left the method, they are no longer valid. However, an inner class such as your Enumerator class can live on past the method execution, e.g. by returning a reference to a class instance.

Thus, the Enumerator class and its methods can be accessed outside of the method in which it is declared. At that point, it needs to assume that the local variables it referenced have the same value they had when execution instantiated the class.

For instance variables, the scope of these and of the inner class is the same - they are both available as long as the parent class instance exists.

Inner classes defined within a method require variables declared in the method to be final, if they are accessed from within the inner classes

It's described very well in this article:

.. the methods in an anonymous class don't really have access to local
variables and method parameters. Rather, when an object of the
anonymous class is instantiated, copies of the final local variables
and method parameters referred to by the object's methods are stored
as instance variables in the object. The methods in the object of the
anonymous class really access those hidden instance variables. Thus,
the local variables and method parameters accessed by the methods of
the local class must be declared final to prevent their values from
changing after the object is instantiated
.

Also refer to the JLS - 8.1.3. Inner Classes and Enclosing Instances for details and further explanation.

Why do we use final keyword with anonymous inner classes?

Your intuition is correct, because the variable is final it is safe to make a copy of it. Of course for reference types this means copying the reference to the object and not the object it refers to.

How does marking a variable as final allow inner classes to access them?

During instantiation of the inner class, when both the method and the class are in scope, the inner class will make a copy of the variables which are constants, which means that the method can go out of scope, since the inner class is only using a copy of the variable.
Check out this article.

Java inner class and static nested class

From the Java Tutorial:

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.

Static nested classes are accessed using the enclosing class name:

OuterClass.StaticNestedClass

For example, to create an object for the static nested class, use this syntax:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:

class OuterClass {
...
class InnerClass {
...
}
}

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. Then, create the inner object within the outer object with this syntax:

OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

see: Java Tutorial - Nested Classes

For completeness note that there is also such a thing as an inner class without an enclosing instance:

class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}

Here, new A() { ... } is an inner class defined in a static context and does not have an enclosing instance.



Related Topics



Leave a reply



Submit