Ссылка на не финальные поля включающего класса внутри анонимного внутреннего класса в Java - PullRequest
3 голосов
/ 12 февраля 2010

В Java я знаю, что можно сделать что-то вроде этого:

public class Greeter {
    public void greetEventually() {
        final String greeting = "Hello!";
        Job j = new Job() {
            public void run() {
                System.out.println(greeting);
            }
        };
        j.schedule();
    }
}

Это выполнит анонимный Job в какой-то момент в будущем. Это работает, потому что анонимным классам разрешено ссылаться на конечные переменные во вложенной области видимости.

В чем я не уверен, так это в следующем случае:

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

В этом случае мой аноним Job относится к неконечному полю включающего класса. Когда задание будет выполнено, увижу ли я значение поля greeting, как оно было при создании задания или как при его выполнении? Я думаю, что знаю ответ, но я подумал, что это интересный вопрос, и сначала он оставил меня и пару коллег на несколько минут в догадках.

Ответы [ 3 ]

9 голосов
/ 12 февраля 2010

Вы увидите значение greeting, как оно есть, когда анонимный Job выполняется.

Модификатор final требуется только для локальных переменных, а не переменных-членов.

1 голос
/ 12 февраля 2010

Вы получаете доступ к полю через (внешнее) this).Вы можете думать о this как о локальной переменной final.Только local является final, указанный объект не является (обязательно) постоянным.Представьте себе локальную переменную с тем же значением, что и this, и она должна быть чистой.

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();
    }
}
0 голосов
/ 12 февраля 2010

Последний модификатор применяется к локальным переменным только для предоставления переменных для каждого экземпляра внутреннего класса, поэтому мы используем: окончательное приветствие в виде строки;

Когда вам нужен только один экземпляр переменной (как в случае констант или общих ресурсов), используйте: личное приветствие String;

...