开发者

Referring to non-final fields of an enclosing class inside an anonymous inner class in Java

开发者 https://www.devze.com 2022-12-19 19:12 出处:网络
In Java, I know that it is possible to do something like this: public class Greeter { public void greetEventually() {

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;

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号