a
can only be final here. Why? How can I reassigna
inonClick()
method without keeping it as private member?private void f(Button b, final int a){ b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int b = a*5; } }); }
How can I return the
5 * a
when it clicked? I mean,private void f(Button b, final int a){ b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int b = a*5; return b; // but return type is void } }); }

- 10,019
- 9
- 74
- 96
-
1I don't think that Java anonymous classes provide the kind of lambda closure that you'd expect, but someone please correct me if I'm wrong... – user541686 Jan 19 '11 at 07:00
-
5What are you trying to achieve? Click handler could be executed when "f" is finished. – Ivan Dubrov Jan 19 '11 at 07:02
-
@Lambert if you want to use a in the onClick method it have to be final @Ivan how can f() method behaves like onClick() method return int when clicked – Jan 19 '11 at 07:08
-
2That's what I mean -- it doesn't support full closure because it doesn't allow access to non-final variables. – user541686 Jan 19 '11 at 07:10
-
possible duplicate of [Why inner classes require "final" outer instance variables \[Java\]?](http://stackoverflow.com/questions/3910324/why-inner-classes-require-final-outer-instance-variables-java) – Raedwald Jul 20 '13 at 11:42
-
http://stackoverflow.com/q/12830611/2073130 has a good discussion on the why. – lcn Dec 08 '15 at 23:26
-
4Note: as of Java 8, your variable only needs to be *effectively final* – Peter Lawrey Feb 24 '16 at 12:41
-
Studied the whole oracle documentation from here https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html still did not find the why answer – Mateen May 27 '18 at 08:03
16 Answers
As noted in comments, some of this becomes irrelevant in Java 8, where final
can be implicit. Only an effectively final variable can be used in an anonymous inner class or lambda expression though.
It's basically due to the way Java manages closures.
When you create an instance of an anonymous inner class, any variables which are used within that class have their values copied in via the autogenerated constructor. This avoids the compiler having to autogenerate various extra types to hold the logical state of the "local variables", as for example the C# compiler does... (When C# captures a variable in an anonymous function, it really captures the variable - the closure can update the variable in a way which is seen by the main body of the method, and vice versa.)
As the value has been copied into the instance of the anonymous inner class, it would look odd if the variable could be modified by the rest of the method - you could have code which appeared to be working with an out-of-date variable (because that's effectively what would be happening... you'd be working with a copy taken at a different time). Likewise if you could make changes within the anonymous inner class, developers might expect those changes to be visible within the body of the enclosing method.
Making the variable final removes all these possibilities - as the value can't be changed at all, you don't need to worry about whether such changes will be visible. The only ways to allow the method and the anonymous inner class see each other's changes is to use a mutable type of some description. This could be the enclosing class itself, an array, a mutable wrapper type... anything like that. Basically it's a bit like communicating between one method and another: changes made to the parameters of one method aren't seen by its caller, but changes made to the objects referred to by the parameters are seen.
If you're interested in a more detailed comparison between Java and C# closures, I have an article which goes into it further. I wanted to focus on the Java side in this answer :)

- 1,421,763
- 867
- 9,128
- 9,194
-
3Yeah. Basically, full closures support could be implemented by moving all variables that are referenced in a special auto-generated class. – Ivan Dubrov Jan 19 '11 at 07:14
-
4@Ivan: Like C#, basically. It comes with a fair degree of complexity though, if you want the same sort of functionality as C# where variables from different scopes can be "instantiated" different numbers of times. – Jon Skeet Jan 19 '11 at 07:15
-
1This auto-generated constructor, why can't I see it using reflection though? – Ustaman Sangat Sep 16 '11 at 20:42
-
1@Ustaman: I suspect you could - but it's a bit too much to go into in comments. I suggest you ask a new question with some sample code. – Jon Skeet Sep 16 '11 at 21:07
-
3http://stackoverflow.com/questions/7472195/passing-final-variables-to-anonymous-classes – Ustaman Sangat Sep 19 '11 at 14:04
-
1in turn, the reasons _why_ they choose to implement closures that way are discussed in [another question](http://stackoverflow.com/q/17736620/839601). In particular, one of the answers quotes Guy Steele that "prototype implementation *did* allow non-final variables to be referenced from within inner classes..." – gnat Jul 24 '13 at 08:53
-
12This was all true for Java 7, keep in mind that with Java 8, closures have been introduced and now it is indeed possible to access a non-final field of a class from its inner class. – Mathias Bader Oct 24 '14 at 14:41
-
1
-
24@MathiasBader: Really? I thought it is still essentially the same mechanism, the compiler is now just clever enough to infer `final` (but it still needs to be effectively final). – Thilo Mar 04 '16 at 07:56
-
4@Mathias Bader: you could always access non-final *fields*, which are not to be confused with *local* variables, which had to be final and still have to be effectively final, so Java 8 doesn’t change the semantics. – Holger Jun 02 '16 at 18:27
-
3If anyone is dumb like me and if you are beating your head against the wall just to know What the hack is this Closure....then here you go.. https://www.youtube.com/watch?v=Nj3_DMUXEbE – Piyush Kukadiya Jan 02 '17 at 07:27
-
"..any variables which are used within that class have their values copied in..". @JonSkeet, is it the values or the references that are copied in? – Peter Chaula Jan 31 '17 at 15:30
-
1@peter: The values *are* references, assuming the variables are reference type variables. It's the same kind of "value copy" as assignment to another variable. – Jon Skeet Jan 31 '17 at 15:35
-
Aliasing the activation record could have done the job. The only difficult part that is solvable is to optimised the call stack reification only when you detect that the closure can escape the current call stack. So no final could be needed.I wonder if C# is able to optimise the way they copy the environment. – mathk Mar 03 '17 at 10:59
-
@JonSkeet I understand this reasoning for making the local variables final, but then how can non-final instance variables be accessed inside an anonymous inner class? are implicitly referred by a `this`? – rd22 Mar 25 '17 at 08:19
-
is there any specs saying the variable is copied over. if it's on another mem location, then java probably should leave the original variable mutable, as anyway the copied over variable is on another mem location, and any changes on the new variable should be immune to original ? – Jackie Jul 19 '17 at 15:32
-
@Iwpro2 You seem to confuse the semantics of 'copy' in the Java sense: The inner/anonymous class gets a new reference to the variable/the object behind it. The object itself doesn't change its memory location in any way. Writes to the original variable could still be allowed, but may confuse developers thinking that the anonymous class could then use the new value. – Adowrath Sep 15 '17 at 07:23
-
1@JonSkeet I tried to comprehend your statement - This avoids the compiler...of the "local variables", but I'm not able to fathom it. I tried to follow other related answers, but fail to get an idea. Please let know as to why local variables have to be copied? Thanks! – lupchiazoem Jun 21 '19 at 01:19
-
@JonSkeet As a followup to my earlier comment, if local variables are final or effectively final, why make a copy rather than use them directly? – lupchiazoem Jun 21 '19 at 06:27
-
2@lupchiazoem: Suppose you return an anonymous inner class instance from a method. The local variables were on the stack - where are they now? How would you expect the instance to refer to them? I'm afraid the topic of "what the C# compiler does with delegates" is far too big to go into in detail in comments, and likewise "what the Java compiler does with anonymous inner classes". – Jon Skeet Jun 21 '19 at 06:37
-
I also have trouble understanding the answer. Is it possible to illustrate with code example that what happens/problems created if non final augments could be used? – tom Sep 12 '20 at 06:25
-
-
If you didn't understand this at first (like me), read [this answer](https://stackoverflow.com/a/7423059/8847871) first, then come back. – ParSal Jul 03 '23 at 07:22
There is a trick that allows anonymous class to update data in the outer scope.
private void f(Button b, final int a) {
final int[] res = new int[1];
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
res[0] = a * 5;
}
});
// But at this point handler is most likely not executed yet!
// How should we now res[0] is ready?
}
However, this trick is not very good due to the synchronization issues. If handler is invoked later, you need to 1) synchronize access to res if handler was invoked from the different thread 2) need to have some sort of flag or indication that res was updated
This trick works OK, though, if anonymous class is invoked in the same thread immediately. Like:
// ...
final int[] res = new int[1];
Runnable r = new Runnable() { public void run() { res[0] = 123; } };
r.run();
System.out.println(res[0]);
// ...

- 10,019
- 9
- 74
- 96

- 4,778
- 2
- 29
- 41
-
2thanks for your answer. I know all of this and my solution is better than this. my question is "why only final" ? – Jan 19 '11 at 07:10
-
6
-
1Thanks. I had used the trick above on my own. I was not sure if it is a good idea. If Java does not allow it, there might be a good reason. Your answer clarifies that my `List.forEach` code is safe. – RuntimeException Oct 30 '15 at 11:54
-
Read http://stackoverflow.com/q/12830611/2073130 for a good discussion of the rationale behind "why only final". – lcn Dec 08 '15 at 23:24
-
there are several workarounds. Mine is: final int resf = res; Initially I used the array approach, but I find it to have too a cumbersome syntax. AtomicReference is maybe a little slower (allocates an object). – zakmck Nov 29 '17 at 17:37
An anonymous class is an inner class and the strict rule applies to inner classes (JLS 8.1.3):
Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned before the body of the inner class.
I haven't found a reason or an explanation on the jls or jvms yet, but we do know, that the compiler creates a separate class file for each inner class and it has to make sure, that the methods declared on this class file (on byte code level) at least have access to the values of local variables.
(Jon has the complete answer - I keep this one undeleted because one might interested in the JLS rule)

- 1
- 1

- 113,398
- 19
- 180
- 268
You can create a class level variable to get returned value. I mean
class A {
int k = 0;
private void f(Button b, int a){
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
k = a * 5;
}
});
}
now you can get value of K and use it where you want.
Answer of your why is :
A local inner class instance is tied to Main class and can access the final local variables of its containing method. When the instance uses a final local of its containing method, the variable retains the value it held at the time of the instance's creation, even if the variable has gone out of scope (this is effectively Java's crude, limited version of closures).
Because a local inner class is neither the member of a class or package, it is not declared with an access level. (Be clear, however, that its own members have access levels like in a normal class.)

- 10,019
- 9
- 74
- 96

- 1,879
- 4
- 18
- 30
-
-
sir Can you atleast briefly what you mean by " even if the variable has gone out of scope " sir. – chandu_reddim Feb 14 '21 at 01:03
To understand the rationale for this restriction, consider the following program:
public class Program {
interface Interface {
public void printInteger();
}
static Interface interfaceInstance = null;
static void initialize(int val) {
class Impl implements Interface {
@Override
public void printInteger() {
System.out.println(val);
}
}
interfaceInstance = new Impl();
}
public static void main(String[] args) {
initialize(12345);
interfaceInstance.printInteger();
}
}
The interfaceInstance remains in memory after the initialize method returns, but the parameter val does not. The JVM can’t access a local variable outside its scope, so Java makes the subsequent call to printInteger work by copying the value of val to an implicit field of the same name within interfaceInstance. The interfaceInstance is said to have captured the value of the local parameter. If the parameter weren’t final (or effectively final) its value could change, becoming out of sync with the captured value, potentially causing unintuitive behavior.

- 401
- 3
- 13

- 210
- 2
- 5
The reason why the access has been restricted only to the local final variables is that if all the local variables would be made accessible then they would first required to be copied to a separate section where inner classes can have access to them and maintaining multiple copies of mutable local variables may lead to inconsistent data. Whereas final variables are immutable and hence any number of copies to them will not have any impact on the consistency of data.

- 454
- 6
- 12
-
This is not how it is implemented in languages like C# that support this feature. In fact, the compiler changes the variable from a local variable to an instance variable, or it creates an extra data structure for these variables that can outlife the scope of the outer class. However, there are no "multiple copies of local variables" – Mike76 Aug 27 '16 at 13:13
-
Mike76 I haven't had a look at C#'s implementation, but Scala does the second thing you mentioned I think: If an `Int` is being reassigned to inside a closure, change that variable to an instance of `IntRef` (essentially a mutable `Integer` wrapper). Every variable access is then rewritten accordingly. – Adowrath Sep 15 '17 at 07:30
Well, in Java, a variable can be final not just as a parameter, but as a class-level field, like
public class Test
{
public final int a = 3;
or as a local variable, like
public static void main(String[] args)
{
final int a = 3;
If you want to access and modify a variable from an anonymous class, you might want to make the variable a class-level variable in the enclosing class.
public class Test
{
public int a;
public void doSomething()
{
Runnable runnable =
new Runnable()
{
public void run()
{
System.out.println(a);
a = a+1;
}
};
}
}
You can't have a variable as final and give it a new value. final
means just that: the value is unchangeable and final.
And since it's final, Java can safely copy it to local anonymous classes. You're not getting some reference to the int (especially since you can't have references to primitives like int in Java, just references to Objects).
It just copies over the value of a into an implicit int called a in your anonymous class.

- 16,072
- 4
- 38
- 39
-
3I associate "class-level variable" with `static`. Maybe it is more clear if you use "instance variable" instead. – eljenso Jan 19 '11 at 12:23
-
1well, I used class-level because the technique would work with both instance and static variables. – Zach L Jan 19 '11 at 17:01
-
we already know that final are accessible but we want to know why? can you please add some more explanation on why side? – Saurabh Oza Jan 29 '19 at 12:44
When an anonymous inner class is defined within the body of a method, all variables declared final in the scope of that method are accessible from within the inner class. For scalar values, once it has been assigned, the value of the final variable cannot change. For object values, the reference cannot change. This allows the Java compiler to "capture" the value of the variable at run-time and store a copy as a field in the inner class. Once the outer method has terminated and its stack frame has been removed, the original variable is gone but the inner class's private copy persists in the class's own memory.

- 31
- 1
Methods within an anonomyous inner class may be invoked well after the thread that spawned it has terminated. In your example, the inner class will be invoked on the event dispatch thread and not in the same thread as that which created it. Hence, the scope of the variables will be different. So to protect such variable assignment scope issues you must declare them final.

- 2,661
- 3
- 23
- 37
private void f(Button b, final int a[]) {
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
a[0] = a[0] * 5;
}
});
}

- 90,663
- 31
- 146
- 203

- 507
- 6
- 17
As Jon has the implementation details answer an other possible answer would be that the JVM doesn't want to handle write in record that have ended his activation.
Consider the use case where your lambdas instead of being apply, is stored in some place and run later.
I remember that in Smalltalk you would get an illegal store raised when you do such modification.

- 7,973
- 6
- 45
- 74
Try this code,
Create Array List and put value inside that and return it :
private ArrayList f(Button b, final int a)
{
final ArrayList al = new ArrayList();
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int b = a*5;
al.add(b);
}
});
return al;
}
-
OP is asking for reasons as to why something is required. Hence you should point out how your code is addressing it – NitinSingh Jul 18 '18 at 10:21
Java anonymous class is very similar to Javascript closure, but Java implement that in different way. (check Andersen's answer)
So in order not to confuse the Java Developer with the strange behavior that might occur for those coming from Javascript background. I guess that's why they force us to use final
, this is not the JVM limitation.
Let's look at the Javascript example below:
var add = (function () {
var counter = 0;
var func = function () {
console.log("counter now = " + counter);
counter += 1;
};
counter = 100; // line 1, this one need to be final in Java
return func;
})();
add(); // this will print out 100 in Javascript but 0 in Java
In Javascript, the counter
value will be 100, because there is only one counter
variable from the beginning to end.
But in Java, if there is no final
, it will print out 0
, because while the inner object is being created, the 0
value is copied to the inner class object's hidden properties. (there are two integer variable here, one in the local method, another one in inner class hidden properties)
So any changes after the inner object creation (like line 1), it will not affect the inner object. So it will make confusion between two different outcome and behaviour (between Java and Javascript).
I believe that's why, Java decide to force it to be final, so the data is 'consistent' from the beginning to end.

- 10,725
- 19
- 102
- 158
Java final
variable inside an inner class
[About]
inner class can use only
- reference from outer class
- final local variables from out of scope which are a reference type (e.g.
Object
...) - value(primitive) (e.g.
int
...) type can be wrapped by a final reference type.IntelliJ IDEA
can help you covert it to one element array
When a non static nested
(inner class
) is generated by compiler - a new class - <OuterClass>$<InnerClass>.class
is created and bounded parameters are passed into constructor[Local variable on stack] It is similar to closure[Swift about]
final variable is a variable which can not be reassign. final reference variable still can be changed by modifying a state
If it was be possible it would be weird because as a programmer you could make like this
//Not possible
private void foo() {
MyClass myClass = new MyClass(); //Case 1: myClass address is 1
int a = 5; //Case 2: a = 5
//just as an example
new Button().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
/*
myClass.something(); //<- what is the address - 1 or 2?
int b = a; //<- what is the value - 5 or 10 ?
//illusion that next changes are visible for Outer class
myClass = new MyClass();
a = 15;
*/
}
});
myClass = new MyClass(); //Case 1: myClass address is 2
int a = 10; //Case 2: a = 10
}

- 29,217
- 8
- 193
- 205
public class Closure {
public void publicMethod() {
Integer localVariable1 = 10;
Map<String, Integer> map = new HashMap<String, Integer>() {
{
put("a", localVariable1);
}
};
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println(localVariable1);
}
});
List<String> list = Arrays.asList("A", "B", "C");
Collections.sort(list, new Comparator<String>() {
public int compare(String p1, String p2) {
return p1.compareTo(p2);
}
});
}
}
- After compilation, the above would result in 4 classes (3 AIC and 1 parent class)
- During runtime if Java would have allowed to update localVariable1 or list, it would make the compiled classes invalid and the map would contain outdated data
- To avoid such inconsistent behaviour java forces it to be final or effectively final

- 932
- 11
- 13
Maybe this trick gives u an idea
Boolean var= new anonymousClass(){
private String myVar; //String for example
@Overriden public Boolean method(int i){
//use myVar and i
}
public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);

- 6,401
- 11
- 62
- 105