Мы все знаем, вы не можете сделать что-то вроде этого:Зачем требовать, чтобы локальные переменные были окончательными при доступе от анонимных внутренних классов?
int a = 7;
new Runnable() {
public void run() {
System.out.println(a);
}
}.run();
...
... без a
окончательного. Я получаю техническую причину, потому что это связано с тем, что локальные переменные живут в стеке, и вы не можете безопасно сделать копию, если не знаете, что она не изменится.
Что я борюсь, чтобы увидеть, однако, почему компилятор не имеет хак реализации, так что, когда он видит вышеуказанную ситуацию, компилирует вниз к чему-то вроде:
int[] a = {7};
new Runnable() {
public void run() {
System.out.println(a[0]);
}
}.run();
...
Тогда мы в где безопасно получить доступ к анонимному внутреннему классу и действительно изменить его, если мы пожелаем. Конечно, это может сделать только этот взлом, когда мы фактически меняем a
. Насколько я мог видеть, это было бы относительно простой вещью, чтобы работать, будет работать для всех типов и позволит a
быть измененным из любого контекста. Конечно, вышеупомянутое предложение может быть изменено на использование синтетических классов-оболочек для нескольких значений или другого подхода, который немного эффективнее, но идея такая же. Я думаю, что есть небольшой удар производительности, но я сомневаюсь, что это было бы чрезмерно, особенно с возможностью большего оптимизма под капотом. Помимо, возможно, определенных рефлексивных вызовов, которые полагаются на синтетические поля, которые могут быть нарушены, я не вижу многих недостатков, но я никогда не слышал, чтобы это серьезно предлагалось! Есть ли причина, почему?
«конечные» переменные являются фактически экземплярами внутреннего класса (нет внутренних классов pe SE, только компиляция генерирует что-то похожее на них). Зачем нужно использовать массив - он не будет совместим с сериализацией и многими другими вещами. – bestsss
Еще одна проблема, которая у вас есть (и может иметь в groovy, которая не имеет этого ограничения) заключается в том, что не конечные переменные могут меняться (в противном случае у вас не было бы проблем с окончанием) int a = 1; // использовать a в другом потоке. a = 2; Если нить всегда видит a = 1 или может иногда видеть a = 2. –
Не ненавидите ли вы, когда кто-то закрывает вопрос, находящийся посредине ответа. :( –