Внутренний класс и локальные переменные
Почему я должен объявить 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
должна быть конечная константа? Как это влияет?
6 ответов
Ответ два в разных сферах. Таким образом, эта переменная может измениться до того, как внутренний класс получит к ней доступ. Окончательное это предотвращает.
Локальные переменные всегда живут в стеке, метод момента, когда все локальные переменные исчезли.
Но ваши объекты внутреннего класса могут быть в куче даже после того, как метод завершится (скажем, переменная экземпляра удерживает ссылку), поэтому в этом случае он не может получить доступ к вашим локальным переменным, поскольку они пропали, если вы не пометите их как final
Это потому, что внутренний класс внутри функции фактически создает копию локальной переменной, потому что локальная переменная может быть уничтожена после вызова функции, пока экземпляр локального класса еще существует. Чтобы две копии локальной переменной всегда имели одно и то же значение (чтобы они казались идентичными), вы должны объявить переменную как final.
Я думаю, что это сделано для того, чтобы программист не допустил ошибок. Таким образом, компилятор напоминает программисту, что переменная больше не будет доступна после выхода из этого метода. Это важно с циклом. Представьте себе этот код:
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
изменилось во время зацикливания. Чтобы избежать этой путаницы, вы должны скопировать переменную в локальную переменную или создать переменную final, но тогда вы не сможете выполнить цикл.
Ваш внутренний класс является окончательным, и поэтому вы не сможете изменить что-либо изнутри вашей конечной сущности.
Согласно модели памяти Java использование конечной переменной гарантирует, что конечная переменная всегда инициализируется. Мы получаем ошибку, когда пытаемся использовать локальную переменную без инициализации. использование final гарантирует внутреннему классу, что используемая локальная переменная инициализируется.