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).
Related
I need to access an ArrayList through multiple functions in my main Java class file (the class file that contains main()).
To save myself having to pass the array list between functions, can I declare it outside of the methods? Is this bad practise? I understand this is okay with class files that are initialised as objects (private instance variables for example) - but what about the Main class file?
EDIT: It will be the only class variable declared and available to all functions in that class.
If you declare it as private it's okay. What it would be a very bad practice is to declare it as public.
You are good as long as you keep it private, since that way you'll make sure it is accessible only from within that class. On the other hand, if you do require it to be accessed from other classes, use getter setter methods while still keeping it private within the class itself.
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.
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.
If I have a variable of type SomeClass and one of its public members, say public int counter will be accessed by multiple threads, how can I declare volatility on that member field if I'm unable to modify SomeClass? Ideally, I'm guessing that counter would be declared volatile, but I'm unable to do that.
What you are trying to achieve is incompatible with separate compiling, and is therefore not possible. The volatile qualifier directs the compiler to treat a variable differently on each access, so every access to that variable from the module to the source of which you have no access would need to change as well. Since that module is compiled already, changing the way it treats some of its variables is not possible.
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.