[Java] Почему локальные переменные должны быть final в этой ситуации?
Final переменные доступны из анонимного класса как примере. Не final нельзя было бы использовать в run. Хотя я в этом не уверен, сам никогда такой фишкой не пользовался.
Java Language Specification
...
8.1.2 Inner Classes and Enclosing Instances
...
Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final, and must be definitely assigned (§16) before the body of the inner class.
Я только не могу понять, зачем такое правило. Типа, яйца курицу не учат?
А ты попробуй представить как это все дело реализуют (ведь это все синтаксические фокусы). Тогда станет понятно
Ну посуди сам. У экземпляра внутреннего класса всегда есть ссылка на экземпляр внешнего - того, кто его создал. Он может читать внешние данные. Так почему он не может их писать?
ae - локальная переменная и не является частью внешнего класса
потому что тело внешней функции может завершиться и уничтожить переменную ae раньше, чем будет происходить запись в эту переменную.
В некоторых других языках это ничему не мешает.
ps
> пошли по самому простому пути реализации
Именно, такого рода проблемы я имею ввиду, когда говорю, что Java-у sun почти не развивает.
(...я и сам ищу, но пока ничего не нашёл...)
Поэтому переменную можно раскопировать по всем контекстам.
Речь идёт о локальных переменных (спасибо -у, что обратил внимание). А они даже в Java создаются в стеке. После первой же } стек, надо думать, возвращается в то состояние, в каком он был до соответствующей {. Вот я и не пойму: а причём тут final?
Что произойдет, если внутренняя функция в этот момент запишет по адресу разрушенной переменной какое-либо значение?
или прочитает из разрушенной переменной значение еще раз?
Извини, я, наверно, туплю. Но я не вижу здесь принципиальной разницы между записью и чтением. И то, и другое - ошибка (если переменная разрушена).
Поможет ли нам, если мы скопируем значение оригинальной переменной в какое-нибудь другое место при старте внутренней фукнции, и дальше уже внутренняя фукнция будет лазить в это другое место?
Какие при этом возникают проблемы?
Помогает ли эти проблемы решить слово final?
Речь идёт лишь о локальных переменных. "Другие места" (например, элемент данных внешнего класса) проблем не вызывают.
public class Parcel8 {Дальше такой текст-пояснение:
// Argument must be final to use inside
// anonymous inner class:
public Destination dest(final String dest) {
return new Destination {
private String label = dest;
public String readLabel { return label; }
};
}
public static void main(String[] args) {
Parcel8 p = new Parcel8;
Destination d = p.dest("Tanzania");
}
}
If you’re defining an anonymous inner class and want to use an object that’s defined outside the anonymous inner class, the compiler requires that the argument reference be final, like the argument to dest( ). If you forget, you’ll get a compile-time error message.
Типа, объяснил.....
ты на него ответил?
Это можешь решить только ты. Я лишь решил, что "другое место" - это не локальные переменные, а что-то другое (был пример).
1. Есть внешняя и внутренняя функция
2. Есть локальная переменная во внешней функции
3. Есть проблема - внешняя функция может закончится, и уничтожить локальную переменную еще до того, как внутренняя функция закончит работу с этой переменной.
4. Есть решение: компилятор копирует значение этой локальной переменной в "другое место" (в область кучи)
Проблема решена?
Хочешь сказать, локальные переменные final размещаются в куче?
Путаешь причину и следствие.
final означает, что переменная больше меняться не будет.
если переменная финал, то компилятор, когда встречает внутренную функцию, которая использует эту же переменную, может скопировать переменную в кучу: и обеспечить, чтобы
внешняя функция работала с копией в стеке, а внутренняя с копией в куче.
если финала - не будет, то получится, что копии смогут иметь разные значения.
afaik, final гарантирует, что переменная больше меняться не будет.Darkgray прав. Они создают копию в куче.
Поэтому переменную можно раскопировать по всем контекстам.
т.е ae становится членом внутреннего класса, как и this внешнего класса.
Всё ясно. Всем спасибо!
"Вот когда мне так по-человечески объясняют..." (Криминальное чтиво)
P.S. (Но осадок в душе остался) Почему-то это нигде (Thinking in Java, The Java Language Specification) не объясняется.
Какого this? main вроде статическая.
Короче, буду считать, что ae на всякий пожарный копируется в кучу, когда выясняется, что он упоминается во внутреннем классе.
А ну да, в этом примере нет this
Оставить комментарий
enochka1145
У Б. Экеля в его "Thinking in Java" приводится такой код - ещё один пример, чтобы читатель проникнулся необходимостью использовать ключевое слово synchronized.Одного я не понимаю - зачем нужно слово final (в 6-й строке сверху)?