Нужно ли инициализировать массив внутри метода или вне метода
Что проверяют
Понимаете ли вы разницу между локальной переменной и полем на уровне памяти и времени жизни, а не только видимости. Вопрос школьный, но по ответу быстро видно, кто пересказывает заученное про стек и кучу.
Как отвечать
Правило простое: область видимости минимальная из возможных. Массив нужен только внутри вычисления, значит создаётся в методе. Массив это часть состояния объекта, значит поле. Дальше стоит назвать реальные различия.
- Локальная переменная не имеет значения по умолчанию: компилятор не даст прочитать её до присваивания. Поле инициализируется автоматически нулём,
nullилиfalse. - Сам объект массива в обоих случаях лежит в куче, на стеке только ссылка. JIT иногда убирает аллокацию скалярной заменой, но закладываться на это в ответе не стоит.
- Поле живёт столько же, сколько объект, и потому удерживает память и делится между вызовами метода. Статическое поле живёт ещё дольше и разделяется между всеми потоками.
private final int[] state = new int[SIZE]; // часть состояния объекта
void process(int n) {
int[] buf = new int[n]; // временный, свой на каждый вызов
}Если метод горячий, а буфер большой, переиспользование обсуждается отдельно, но тогда это осознанное решение с ответом на вопрос о потокобезопасности.
Где спотыкаются
Говорят, что локальный массив создаётся на стеке и потому быстрее. На стеке лежит ссылка, данные в куче, а сборка молодого поколения дешёвая, так что выигрыш обычно воображаемый.
Делают поле статическим, чтобы не создавать массив каждый раз. Получают общее состояние на все экземпляры и гонку, как только метод вызовут из двух потоков.
Считают final признаком неизменяемости. Он запрещает переприсвоить ссылку, а элементы меняются свободно, поэтому массив, отданный наружу геттером, копируют через Arrays.copyOf или заменяют неизменяемым списком.