views:

133

answers:

3

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 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.

+8  A: 

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.

erickson
This is how I suspected it worked.By the way, the only reason I explicitly mentioned **non-final** fields is because if the field is final the behavior is clear.
Mike Daniels
Yup. We thought it would be a good question to have on record in SO. Mike you should accept this one.
Tim Bender
A: 

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;

MostafaEweda
+1  A: 

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();
    }
}
Tom Hawtin - tackline