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()