Related
a can only be final here. Why? How can I reassign a in onClick() 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
}
});
}
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 :)
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]);
// ...
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)
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.)
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.
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.
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.
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.
(http://en.wikipedia.org/wiki/Final_%28Java%29)
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.
private void f(Button b, final int a[]) {
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
a[0] = a[0] * 5;
}
});
}
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.
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;
}
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.
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
}
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);
class A
{
int i = 10;
public static void main(String[] args)
{
A a= new A();
a.i=20;
}
}
is running fine but when try to write following code
class A
{
A a= new A();
int i = 10;
public static void main(String[] args)
{
a.i=20;
}
}
it is giving compile time error. It means that whatever(assume reference variable) we write inside the static method is treated as a static variable implicitly.
You are mixing up class scope, method scope, and instance scope.
First remember that when you have something that is static, it is available to all instances of that class. When something isn't static, it is only available to a specific instance of a class, and is not shared. Because of that, static methods cannot act on instance variables (or methods).
In the first example, you create an A scoped to the main() method. The fact that main() is static has nothing to do with it, this is method-level scoping. When you call .i on that instance of A, you are calling it on the instance local to your scope.
In the second example, you are saying that whenever an A is instantiated, it will have another instance of A within it (which leads to other problems, see below). This is at the object instance scope. When you try to call it from your static-scoped main() method, the compiler has no idea which specific instance of A you want to use. Each one has its own version of i.
And finally, by creating an instance of A within every other instance of A (A a = new A();) your code will never run, you'll get a StackOverflowException.
Edit to answer question:
OK, when you do something like this:
public class Person {
String name = null;
}
You are saying, that for every Person we create (via new), they have a name that is for them, and them only. They don't share it with anybody.
So when you do something like this:
public class A {
A a = new A();
}
You are saying that for every A we create (via new) it has another A that is for that instance and that instance only. See where this is going? You end up infiniately creating A objects until java runs out of room on the stack for them. The first A is created, and tries to create its internal A, which tries to create its internal A and so on and so on.
Yes, this is an academic question, I know people will complain that I'm not posting any code
but I'm genuinely struck with this question, really don't know where to begin. I would really appreciate an explanation and maybe some code example.
If an object constructor starts a new thread that executes the method
run of an anonymous inner class object, it is possible that this new
thread can access its surrounding outer object before it has been
fully constructed and its fields fully initialized. How would you
prevent this from happening?
This is called "leaking this". Here you have the code
public class Test {
// this is guaranteed to be initialized after the constructor
private final int val;
public Test(int v) {
new Thread(new Runnable() {
#Override public void run() {
System.out.println("Val is " + val);
}
}).start();
this.val = v;
}
}
Guess what it will (may, since it's a thread) print. I used a final field to stress that the object is accessed before it has been fully initialized (final fields must be definitely assigned after the last line of every constructor)
How do you recover
You don't want to pass this around when you are in a constructor. This also mean you don't want to call non-final virtual methods in the very same class (non-static, non-private), and not using inner classes (anonymous classes are inner classes), that are implicitely linked to the enclosing instance, thus it's as they could access this.
Think about the single-threaded situation first:
Whenever you create an object via new, its constructor is called which (hopefully) initializes the fields of the new object before a reference to this object is returned. That is, from the point of view of the caller, this new is almost like an atomic operation:
Before calling new, there is no object. After returning from new, the object exists fully initialized.
So all is good.
The situation changes slightly when multiple threads come into play. But we have to read your quote carefully:
...has been fully constructed and its fields fully initialized.
The crucial point is fully. The subject line of your question says "before created", but what is meant here is not before the object has been created, but between object creation and initialization. In a multi-threaded situation, new can no longer be considered (pseudo-)atomic because of this (time flows from left to right):
Thread1 --> create object --> initialize object --> return from `new`
^
|
| (messing with the object)
Thread2 ------------------/
So how can Thread2 mess with the object? It would need a reference to that object but since new will only return the object after is both been created and initialized, this should be impossible, right?
Well, no - there is one way where it's still possible -- namely if Thread 2 is created inside the object's constructor. Then the situation would be like this:
Thread1 --> create object --> create Thread2 --> initialize object --> return from `new`
| ^
| |
| | (messing with the object)
\-----/
Since Thread2 is created after the object has been created (but before it has been fully initialized), there is already a reference to the object that Thread2 could get a hold of. One way is simply if the constructor of Thread2 explicitly takes a reference to the object as a parameter. Another way is by using a non-static inner class of the object for Thread2's run method.
I would change the title of the question, as threads are not accessing themselves, but the second one to the first one. I mean:
You have one thread, creating an object.
Inside the constructor for this object, you declare an anonymous inner class that implements Runnable.
In the same constructor of the first thread, you start a new thread to run your anonymous inner class.
Thus, you're having two threads. If you want to assure that the new thread doesn't do anything before the constructor is "fully ended", I would use some locks in the constructor. This way, the 2nd thread can be started but will wait until the first thread ends.
public class A {
int final number;
A() {
new Thread(
new Runnable() {
public void run() {
System.out.pritnln("Number: " + number);
}
}).start();
number = 2;
}
}
I do not fully agree with Pablos answer because it heavily depends on your initialization method.
public class ThreadQuestion {
public volatile int number = 0;
public static void main(String[] args) {
ThreadQuestion q = new ThreadQuestion();
}
public ThreadQuestion() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(number);
}
});
try {
Thread.sleep(500);
} catch(Exception e) {
e.printStackTrace();
}
number = 1;
t.start();
}
}
When you
place t.start() at the end, the correct data is printed.
place t.start() before the sleep command, it will print 0
remove the sleep command and place t.start() before the assignment it can print 1 (not determinable)
Play a mind game on 3.) you can say a "tiny" assignment of 1 simple data type will work as expected but if you create a database connection it will not achieve a reliable result.
Do not hesitate to raise any question.
So a situation like this?
public class MyClass {
private Object something;
public MyClass() {
new Thread() {
public void run() {
something = new Object();
}
}.start();
}
}
Depending on the actual code used, the behaviour could vary. This is why constructors should be carefully made so that they don't for example call non-private methods (a subclass could override it, allowing the superclass this to be accessed from a subclass before the superclass is fully initialized). Although this particular example deals with a single class and a thread, it's related to the reference leaking problem.
What is the difference between a static and instance variable. The following sentence is what I cant get:
In certain cases, only one copy of a particular variable should be shared by all objects of a class- here a static variable is used.
A static variable represents class wide info.All objects of a class share the same data.
I thought that instance vars were used class wide whereas static variables only had scope within their own methods?
In the context of class attributes, static has a different meaning. If you have a field like:
private static int sharedAttribute;
then, each and every instance of the class will share the same variable, so that if you change it in one instance, the change will reflect in all instances, created either before or after the change.
Thus said, you might understand that this is bad in many cases, because it can easiy turn into an undesired side-effect: changing object a also affects b and you might end up wondering why b changed with no apparent reasons. Anyway, there are cases where this behaviour is absolutely desirable:
class constants: since they are const, having all the classes access the same value will do no harm, because no one can change that. They can save memory too, if you have a lot of instances of that class. Not sure about concurrent access, though.
variables that are intended to be shared, such as reference counters &co.
static vars are instantiated before your program starts, so if you have too many of them, you could slow down startup.
A static method can only access static attributes, but think twice before trying this.
Rule of thumb: don't use static, unless it is necessary and you know what you are doing or you are declaring a class constant.
Say there is a test class:
class Test{
public static int a = 5;
public int b = 10;
}
// here t1 and t2 will have a separate copy of b
// while they will have same copy of a.
Test t1 = new test();
Test t2 = new test();
You can access a static variable with it's class Name like this
Test.a = 1//some value But you can not access instance variable like this
System.out.println(t1.a);
System.out.println(t2.a);
In both cases output will be 1 as a is share by all instances of the test class.
while the instance variable will each have separate copy of b (instance variable)
So
t1.b = 15 // will not be reflected in t2.
System.out.println(t1.b); // this will print 15
System.out.println(t2.b); / this will still print 10;
Hope that explains your query.
Suppose we create a static variable K and in the main function we create three objects:
ob1
ob2
ob3;
All these objects can have the same value for variable K. In contrast if the variable K was an instance variable then it could have different values as:
ob1.k
ob2.k
ob3.k
I think you are thinking about the C/C++ definition of the static keyword. There, the static keyword has many uses. In Java, the static keyword's functionality is described in your post. Anyhow, you can try it for yourself:
public class Test_Static{
static int x;
public static void main(String[] argv){
Test_Static a = new Test_Static();
Test_Static b = new Test_Static();
a.x = 1; // This will give an error, but still compile.
b.x = 2;
System.out.println(a.x); // Should print 2
}
}
and similarly for non static variables:
public class Test_NonStatic{
int x;
public static void main(String [] argv){
Test_NonStatic a = new Test_NonStatic();
Test_NonStatic b = new Test_NonStatic();
a.x = 1;
b.x = 2;
System.out.println(a.x); // Should print 1.
}
}
Consider a class MyClass, having one static and one non-static member:
public class MyClass {
public static int STATICVARIABLE = 0;
public int nonStaticVariable = 0;
}
Now, let's create a main() to create a couple of instances:
public class AnotherClass{
public static void main(String[] args) {
// Create two instances of MyClass
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.nonStaticVariable = 30; // Setting value for nonstatic varibale
obj1.STATICVARIABLE = 40; //Setting value for static variable
obj2.nonStaticVariable = 50;
obj2.STATICVARIABLE = 60;
// Print the values actually set for static and non-static variables.
System.out.println(obj1.STATICVARIABLE);
System.out.println(obj1.nonStaticVariable);
System.out.println(obj2.STATICVARIABLE);
System.out.println(obj2.nonStaticVariable);
}
}
Result:
60
30
60
50
Now you can see value of the static variable printed 60 both the times, as both obj1 and obj2 were referring to the same variable. With the non-static variable, the outputs differ, as each object when created keeps its own copy of non-static variable; changes made to them do not impact on the other copy of the variable created by another object.
Instance Variables
Any variable that is defined in class body and outside bodies of
methods; and it should not be declared static, abstract, stricftp,
synchronized, and native modifier.
An instance variable cannot live without its object, and it is a part of
the object.
Every object has their own copies of instance variables.
Static Variables (class variables)
Use static modifier
Belong to the class (not to an object of the class)
One copy of a static variable
Initialize only once at the start of the execution.
Enjoy the program’s lifetime
a can only be final here. Why? How can I reassign a in onClick() 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
}
});
}
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 :)
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]);
// ...
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)
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.)
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.
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.
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.
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.
(http://en.wikipedia.org/wiki/Final_%28Java%29)
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.
private void f(Button b, final int a[]) {
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
a[0] = a[0] * 5;
}
});
}
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.
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;
}
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.
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
}
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);