Cannot refer to a non-final variable inside an inner class defined in a different method
Java doesn't support true closures, even though using an anonymous class like you are using here (new TimerTask() { ... }
) looks like a kind of closure.
edit - See the comments below - the following is not a correct explanation, as KeeperOfTheSoul points out.
This is why it doesn't work:
The variables lastPrice
and price are local variables in the main() method. The object that you create with the anonymous class might last until after the main()
method returns.
When the main()
method returns, local variables (such as lastPrice
and price
) will be cleaned up from the stack, so they won't exist anymore after main()
returns.
But the anonymous class object references these variables. Things would go horribly wrong if the anonymous class object tries to access the variables after they have been cleaned up.
By making lastPrice
and price
final
, they are not really variables anymore, but constants. The compiler can then just replace the use of lastPrice
and price
in the anonymous class with the values of the constants (at compile time, of course), and you won't have the problem with accessing non-existent variables anymore.
Other programming languages that do support closures do it by treating those variables specially - by making sure they don't get destroyed when the method ends, so that the closure can still access the variables.
@Ankur: You could do this:
public static void main(String args[]) {
int period = 2000;
int delay = 2000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// Variables as member variables instead of local variables in main()
private double lastPrice = 0;
private Price priceObject = new Price();
private double price = 0;
public void run() {
price = priceObject.getNextPrice(lastPrice);
System.out.println();
lastPrice = price;
}
}, delay, period);
}
Java: cannot refer to non-final variable
Probably you are using java 8 and the other computer is using java 7. Java requires references to variables from inner classes to be final variables. Java 8 will make them effectively final if you don't reassign.
Add final to:
final GridPane root = new GridPane();
final TextField usernameTextField = new TextField();
final TextField portTextField = new TextField();
final Button button = new Button("Login!");
Cannot refer to a non-final variable inside an inner class defined in a different method issue
You can declare a final
variable p
which will take the value of i
at each iteration.
for( int i = 0; i < N; i++) {
final int p = i;
new Thread(new Runnable() {
public void run() {
for(int a = p*(M/N);a < (p+1)*(M/N); a++)
System.out.println("Thread "+p+":"+array[a]);
}
}).start();
}
Why I need to have a final declaration ?
Cannot refer to non-final variable inside an inner class
This should work:
final ViewHolder holder;
ie don't assign it to null initially.
Why a non-final local variable cannot be used inside an inner class, and instead a non-final field of the enclosing class can?
The difference is between local (method) variables vs class member variables. A member variable exists during the lifetime of the enclosing object, so it can be referenced by the inner class instance. A local variable, however, exists only during the method invocation, and is handled differently by the compiler, in that an implicit copy of it is generated as the member of the inner class. Without declaring the local variable final, one could change it, leading to subtle errors due to the inner class still referring to the original value of that variable.
Update: The Java Specialists' Newsletter #25 discusses this in more detail.
Even the compiler error is misleading to me.
Cannot refer to a non-final variable message inside an inner class defined in a different method
: Different from what?
From the inner class' run
method I believe.
Java - Cannot refer to a non-final variable
Change to this..
final Button button1 = (Button)findViewById(R.id.button2);
//Listeneři
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
button1.setText("ok");
or
you can declare the button variable reference as global..
Bypassing 'Cannot refer to a non-final variable inside an inner class defined'
Change line
to be a StringBuilder
and declare it as final
. Then change the run()
method to append to the StringBuilder
.
Provided that you join()
the child thread before you attempt to read line
in the main thread, you don't need to use a StringBuffer
.
Related Topics
Android Permission Doesn't Work Even If I Have Declared It
Why Does My Function That Calls an API or Launches a Coroutine Return an Empty or Null Value
Nullpointerexception Accessing Views in Oncreate()
Android - Get Real Path of a .Txt File Selected from the File Explorer
How to Get Url from Firebase Storage Getdownloadurl
What's the Best Way to Share Data Between Activities
Why Doesn't Recyclerview Have Onitemclicklistener()
Android, Getting Resource Id from String
Firebase Ui Authentication With Google Fails With Message (Code:10 Message:10)
Gson Throwing "Expected Begin_Object But Was Begin_Array"
Unfortunately Myapp Has Stopped. How to Solve This
How to Efficiently Parse HTML With Java