Где хранятся финальные локальные переменные Java? - PullRequest
18 голосов
/ 22 декабря 2009

Возьмите следующий пример:

public void init() {
    final Environment env = new Environment();
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
             env.close();
        }
     });
}

Во-первых, где хранится env? Это:

  • скопировано компилятором в скрытую переменную-член внутреннего класса, которая ссылается на него
  • скопировал и сослался на кучу
  • оставил в стеке и как-то там ссылался
  • что-то еще

Мой думаю, является первым вариантом.

Во-вторых, любые проблемы с производительностью, возникающие из-за этого (вместо простого создания env в качестве переменной-члена класса и ссылки на нее как таковой), особенно если вы создаете большое количество таких внутренних конструкций класса, которые ссылаются на final локальные переменные.

1 Ответ

18 голосов
/ 22 декабря 2009

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

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

private Environment env;  // a field does not have to be final

public void init() {
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
             env.close();
        }
     });
}

Во-вторых, возникают ли какие-либо проблемы с производительностью, возникающие при этом?

По сравнению с чем? Вам нужно иметь поле или переменную вокруг, чтобы ваш внутренний класс работал, и копия является очень эффективным способом. В любом случае, это только «мелкая» копия: копируется только ссылка на (в вашем примере) Среде, а не сама Среда.

...