I have a function multi2
which returns inner class Inner
as an Object
.
What happens to a
- where is it saved and how can I access it?
public class C {
private static Object multi2(final int a) {
class Inner {
public int hashCode() {
return 2*a;
}
}
return new Inner(); // What happens to a?
// Who allocates a?
// Can I Access a?
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
}
}
What happens at the implementation level is that a copy of the value of a
is saved in a synthetic instance variable declared in the compiled version of the C.Inner
class.
The value of a
is passed to the compiled Inner
constructor via an extra parameter.
The C.Inner.hashCode
method uses the value of the synthetic variable. Accessing a
in the source code of Inner.hashCode
is transformed into accessing the corresponding synthetic variable in the compiled code.
The variable in the outer scope must be final
1. The synthetic variable must be final
2 in the Inner
class. This maintains the illusion that (potentially) multiple instances of the Inner
class are seeing the same a
variable. (They aren't, but since the variable(s) can't be changed, it is not possible for the code of the inner class to tell the difference.)
If you use javap
to look at the bytecodes for the compiled example, you will see the mechanisms used to implement this in the outer and the inner classes.
1 - or effectively final from Java 8 onwards.
2 - If a
could be mutated by an Inner
method, then two Inner
instances with the same outer class need to share a mutable variable whose lifetime is (now) longer than the stackframe for a multi2
call. That entails somehow turning a
from stack variable into something that lives on the heap. It would be expensive and complicated.