This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Cannot refer to a non-final variable inside an inner class defined in a different method
(20 answers)
Closed 7 years ago.
final JTextField jtfContent = new JTextField();
btnOK.addActionListener(new java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent event){
jtfContent.setText("I am OK");
}
} );
If I omit final, I see the error "Cannot refer to a non-final variable jtfContent inside an inner class defined in a different method".
Why must an anonymous inner class require the outer classes instance variable to be final in order to access it?
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.
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. [1]
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.
[1] http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm
The variables around the definition of the class live on the stack, so they are probably gone when the code inside the inner class runs (if you want to know why, search stack and heap). That's why inner classes don't actually use the variables in the containing method, but are constructed with copies of them.
This means that if you change the variable in the containing method after constructing the inner class, its value won't change in the inner class, even though you'd expect it to. To prevent confusion there, Java requires them to be final, so you expect not to be able to modify them.
The reason is that Java do not fully support so-called "Closures" - in which case the final would not be necessary - but instead have found a trick by letting the compiler generate some hidden variables which is used to give the functionality you see.
If you disassemble the generated byte code you can see how the compiler does it, including the strangely named hidden variables containing copies of the final variables.
It is an elegant solution to give functionality without bending the language backwards to do so.
Edit: For Java 8 lambdas give a more concise way to do what was previously done with anonymous classes. The restrictions on variables have also loosened from "final" to "essentially final" - you do not have to declare it final, but if it is treated like it is final (you could add the final keyword and your code would still compile) it can be used. This is a really nice change.
Since Java 8 final modifier is optional for outer instance variables. Value should be 'effectively final'. See answer Difference between final and effectively final.
Related
This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Cannot refer to a non-final variable inside an inner class defined in a different method
(20 answers)
Closed 7 years ago.
final JTextField jtfContent = new JTextField();
btnOK.addActionListener(new java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent event){
jtfContent.setText("I am OK");
}
} );
If I omit final, I see the error "Cannot refer to a non-final variable jtfContent inside an inner class defined in a different method".
Why must an anonymous inner class require the outer classes instance variable to be final in order to access it?
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.
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. [1]
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.
[1] http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm
The variables around the definition of the class live on the stack, so they are probably gone when the code inside the inner class runs (if you want to know why, search stack and heap). That's why inner classes don't actually use the variables in the containing method, but are constructed with copies of them.
This means that if you change the variable in the containing method after constructing the inner class, its value won't change in the inner class, even though you'd expect it to. To prevent confusion there, Java requires them to be final, so you expect not to be able to modify them.
The reason is that Java do not fully support so-called "Closures" - in which case the final would not be necessary - but instead have found a trick by letting the compiler generate some hidden variables which is used to give the functionality you see.
If you disassemble the generated byte code you can see how the compiler does it, including the strangely named hidden variables containing copies of the final variables.
It is an elegant solution to give functionality without bending the language backwards to do so.
Edit: For Java 8 lambdas give a more concise way to do what was previously done with anonymous classes. The restrictions on variables have also loosened from "final" to "essentially final" - you do not have to declare it final, but if it is treated like it is final (you could add the final keyword and your code would still compile) it can be used. This is a really nice change.
Since Java 8 final modifier is optional for outer instance variables. Value should be 'effectively final'. See answer Difference between final and effectively final.
Does an instance of an anonymous inner class store all the accesible final variables or does it store only the variables that are being used inside the said inner class? (i.e. does it perform some kind of analysis? As far as I know the reference to the parent instance is being stored no matter what.)
The reference to the enclosing class is stored no matter what.
Final variables are stored as a copy, but only if you actually reference them somewhere in your inner class. This does not really required any extra "analysis" but can be done in the normal compile step (the compiler has to resolve the variable anyway, so it can output the code to set up the copy, too).
This question already has answers here:
What does the 'static' keyword do in a class?
(22 answers)
Closed 8 years ago.
I'm quite new to Java and I'm trying to understand static variables and methods. Could someone give me a brief explanation of why I'd use the static method over the instance method and also what would be the ideal situation to use static variables? I know that static variables and methods are part of the class and not an instance of said class but I'm having trouble understanding when I'd use it.
Thanks!
These are the main differences
1.Static variables take memory only 1 time during the lifetime of program.
2.You can call static variables or methods. without creating the object of that class by classname only.
3.Static variables can be called in static and non-static context.
Mainly static variables are used to save memory because every object takes memory .
Static members relate to a type not a concrete instance. So instance methods and variables concern the identity of the instance, e.g. an instance method can alter the state of the object.
To some extend this is a religious question. Some people prefer to create static methods in a class when they do not access any instance variable. Other people do not like this approach. Another usual usage is creating factory methods, able to create an instance of an object while itself being called statically.
Often there are utility classes that contain static methods to serve clients with some functionality that is not bound to any type context. But all too often these utility classes get abused by using them as a trash bin for all sorts of methods a programmer did not find a fitting class for. This may be a result of poor design.
A popular use of static variables is the definition of an logger instance (e.g. SLF4J) for a class because loggers are thread safe and can be used by all instances and static methods alike. One advantage is (see a comparison) that only one instance has to be created for all instances of the containing class.
For static variable or method, you can think of that there is only one copy of the variable or method during the whole life time of the program.
So if you there is variable whose value should be shared across all the processes or thread, you can declare a static variable. For example, when you want to use a singleton pattern, you will need a static variable to indicate if there is instance of the class already.
For static methods, I would use them when state of the class is not important. I think the best example is java.lang.Math, they are all static methods, and returns the expected values to you no matter what you called before.
This question already has answers here:
Cannot refer to a non-final variable inside an inner class defined in a different method
(20 answers)
Closed 8 years ago.
Why I cannot refer to a non-final variable inside an inner class defined in a different method?I've seen topics about this and in most of them people say that your component should be final and ... . But nobody says why?!! and I don't know what's the philosophy behind this limitation.What makes me confused more is that the following code is erroneous :
JButton removeJBtn = new JButton("Remove");
JButton addJBtn = new JButton("Add");
//...
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeJBtn.disable();//Error here,Cannot ...
}
});
while if I define
JButton removeJBtn
as a member field (in the body of the class,not the method) it's not required to be defined as final!
I'll really appreciate any logical answer to this daily limit that I (and probably many others) always face.
Dear users that marked this question as a duplicate, please at least give a reference to the original question (that has been answered for sure!), there is a link in added above my question that I read it throughly but it's full of contradictions, some one (with 88 up votes) says java captures the value of final variables and it's completely rejected by a comment (with 16 votes) below it.
The local variables of the method live on the stack, and exist only for
the lifetime of the method. You already know that the scope of a local variable is
limited to the method the variable is declared in. When the method ends, the stack
frame is blown away and the variable is history. But even after the method
completes, the inner class object created within it might still be alive on the heap if,
for example, a reference to it was passed into some other code and then stored in an
instance variable. Because the local variables aren't guaranteed to be alive as long
as the method-local inner class object, the inner class object can't use them. Unless
the local variables are marked final!
Source: Kathy Sierra SCJP
Because a normal variable only resides on the stack (the pointer to the object in your case). Since the inner class can (and usually does) live longer than the defining method, the variable would not be present anymore.
By making the variable final, the compiler can create optimizations (in this case: include the final variable as "secret" member in the inner class. This would not be valid, if the variable were not final, because it could change afterwards.
Extending the other answers, you should keep in mind that anonymous classes are syntactic Java sugar to keep you from creating concrete classes and instantiating them every time you for example have to provide a button listener - if you want to do this (you can easily skip anonymous classes and replace them by concrete classes without a problem), you had to pass the values (here: the removeJBtn) into the objects by constructor to use them internally and you had created a new object explicitly, which lives on the heap and therefore longer then the method where you register the listeners.
I have a question about local and member variables in Java. The situation is: Sometimes if I define a local variable, that variable has to be passed around into several levels of method calls. I often think, why should I just define a member variable for the class so that the variable is available everywhere in the class. A member variable of a class is like a global variable accessible everywhere in the class.
What's the best practice for this scenario? OR what's the right thing to do?
If I define it as a member variable, should it be a static or non-static variable?
Member variables hold characteristics -- attributes is another term -- for the 'thing' in your program represented by the class. If your variable holds something like that, make it a member variable; if it doesn't, don't.
Static variables hold characteristics of the class itself, as opposed to characteristics of objects of that class.
Don't make the decision based on whether you "pass ... into several levels of method calls.
Thinking about your general question, I came up with these guidelines from my experience:
Use the smallest poosible scope. If a local variable is fine, then why use a member variable?
Model the class according to the domain. If you have a value and it is part of the class responsibility, then modeling it as a class member seems to be appropiate.
To your second question: I do generally define static variables as final which make them constants. Non-final static members in a multi-threaded environment may easily introduce race conditions. It is easier to make access to non-static member thread-safe if needed.
It's behavioral. If your variable is part of your class attribute i.e. characterizes the class behavior then define it as the class member variable otherwise define a local variable inside the method.
In my opinion, passing the argument doesn't contribute in the attribute type definition.
It depends.
If you want all (or several), of your methods to access the same member variable, then declare it in the class.
Static or not depends on wether that information belongs to the Class (static), or to an instance of the class (non-static).
1.) If you are going to use it in multiple methods and need to pass it around make its member variable. If it is just for that method make it local.
2.) static means their is only one instance of that variable that is shared among everything. So for example I have a totalGameScore variable that will keep my score for the whole game no matter what. You'd want to make that variable static. Other than that lets say I have a health variable for my enemy. Each enemy will have its own health so I would NOT make that variable static.
You can also declare member variables private so that other classes cannot access them.
Constants should normally always be member variables.
If you decide to declare a member variable then you should consider the variables scope. If you are just reducing the number of parameters on internal method calls I would consider declaring the variable as private.
You should be careful of using Static because every instance of the class will use the same copy of the variable.