Referring to non-final fields of an enclosing class inside an anonymous inner class in Java
In Java, I know that it is possible to do something like this:
public class Greeter {
public void greetEventually() {
final String greeting = "Hello!";
Job j = new Job() {
public void run() {
System.out.println(greeting);
}
};
j.schedule();
}
}
This would execute the anonymous Job
at some point in the future. This works because anonymous classes are allowed to refer to final variables in the enclosing scope.
What I'm not sure about开发者_C百科 is the following case:
public class Greeter {
private String greeting;
// ... Other methods that might mutate greeting ...
public void greetEventually() {
Job j = new Job() {
public void run() {
System.out.println(greeting);
}
};
j.schedule();
}
}
In this case my anonymous Job
is referring to a non-final field of the enclosing class. When the Job runs, will I see the value of the greeting
field as it was when the Job was created, or as it is when it is executing? I think I know the answer, but I thought it was an interesting question, and at first it left me and a couple of coworkers second-guessing ourselves for a few minutes.
You'll see the value of greeting
as it is when the anonymous Job
executes.
The final
modifier is required only for local variables, not member variables.
You are accessing the field through (the outer) this
). You can think of this
as effectively a final
local variable. Only the local is final
, the object pointed to is not (necessarily) constant. Imagine a local variable with the same value as this
and it should be clear.
public class Greeter {
private String greeting;
// ... Other methods that might mutate greeting ...
public void greetEventually() {
private final Greeter greeter = this; // <---
Job j = new Job() {
public void run() {
System.out.println( greeter.greeting ); // <---
}
};
j.schedule();
}
}
The final modifier is applied to the local variables only to provide variables for each instance of the inner class, so we use: final String greeting;
When you need only one instance of the variable (like the case of constants or common resources), use: private String greeting;
精彩评论