Получи случайную криптовалюту за регистрацию!

Enum и метод values Если вы новичок и мало знаете про enum, т | Java: fill the gaps

Enum и метод values

Если вы новичок и мало знаете про enum, то лучше начать с этого лонгрида. Сегодня обсудим итерацию через метод values и как его оптимизировать.

Итак, enums — это синтаксический сахар, который при компиляции превращается в обычный класс. Класс из примера выше превратится в

public final class Number extends Enum

Элементы енума станут статическими полями:

public static final Number ONE;
public static final Number TWO;
public static final Number THREE;

Внутри нового класса появится массив:

Number[] VALUES = { ONE, TWO, THREE};

И его копия будет возвращаться в методе values:

return VALUES.clone();

При каждом вызове values возвращается новая копия массива. Дело в том, что массивы — это изменяемый объект. Если возвращать ссылку на VALUES напрямую, любой желающий сможет поменять исходный массив:

Number.values()[2] = ONE;

Это небезопасно, поэтому каждый раз возвращается копия.

Если цикл с values используется в высоконагруженном коде, то разумно сохранить массив в отдельную переменную и переиспользовать её:

static Number[] numbers = Number.values();

for (Number n : numbers) {…}

Если код вызывается редко, то смысла в отдельной переменной нет.

Пример из жизни

В Spring Web 5.2 в классе HttpStatus есть такой код:

for (HttpStatus status : values()) {
if (status.value == statusCode) {
return status;
}
}

Этот цикл вызывается почти в каждом запросе, но только в этом году завели баг. К описанию прилагался бенчмарк: при нагрузке 600 запросов/сек код производил мегабайт мусора каждую секунду.

Теперь код выглядит так:

private static final HttpStatus[] VALUES;

static {
VALUES = values();
}

for (HttpStatus status : VALUES) {
if (status.value == statusCode) {
return status;
}
}

Ответ на вопрос перед постом

Будет создано 3 массива: один внутри класса Number и два клона при вызове values()