Внутренний класс и локальные переменные

Почему мне нужно объявить local variable как final, если мой Inner class, определенный в методе, должен его использовать?

Пример:

class MyOuter2 {

private String x = "Outer2";

void doStuff() {
    final String y = "Hello World";

    final class MyInner {

        String z = y;

        public void seeOuter() {
            System.out.println("Outer x is "+x);
            System.out.println("Local variable is "+y);
            MyInner mi = new MyInner();
            mi.seeOuter();
        }
    }
}

}

Почему строка y должна быть конечной константой? Как это влияет?

Ответ 1

Ответ: два находятся в разных областях. Таким образом, переменная может измениться до того, как внутренний класс обратится к ней. Это окончательное исключение.

Ответ 2

Локальные переменные всегда живут в стеке, метод момента находится над всеми локальными переменными.

Но ваши внутренние объекты класса могут находиться в куче даже после завершения метода (скажем, что переменная экземпляра хранится в ссылке), поэтому в этом случае она не может получить доступ к вашим локальным переменным, так как они исчезли, если вы не отметите их как Окончательный

Ответ 3

Это потому, что внутренний класс внутри функции фактически создает копию локальной переменной, потому что локальная переменная может быть уничтожена после вызова функции, пока экземпляр локального класса все еще существует. Чтобы две копии локальной переменной всегда имели одинаковое значение (чтобы они выглядели одинаково), вы должны объявить эту переменную окончательной.

Ответ 4

Я думаю, это должно предотвратить ошибки программиста. Таким образом, компилятор напоминает программисту, что эта переменная больше не будет доступна, когда вы покинете этот метод. Это имеет решающее значение при циклировании. Представьте себе этот код:

public void doStuff()
{
    InnerClass cls[] = new InnerClass[100];
    for (int i = 0; i < 100; ++i)
    {
        cls[i] = new InnerClass()
        {
            void doIt()
            {
                System.out.println(i);
            }
        };
    }
}

Когда вызывается метод doIt(), что будет напечатано? i изменен во время цикла. Чтобы предотвратить эту путаницу, вам нужно скопировать переменную в локальную переменную или создать окончательную переменную, но тогда вам не удастся выполнить цикл.

Ответ 5

Ваш внутренний класс является окончательным, поэтому вы не должны ничего изменять изнутри вашего конечного объекта.

Ответ 6

В соответствии с моделью памяти Java использование конечной переменной гарантирует, что конечная переменная всегда инициализируется. Мы получаем ошибку, когда пытаемся использовать локальную переменную без инициализации. используя окончательные гарантии, внутренний класс использует локальную переменную, которая была использована.