Enum и метод values
Если вы новичок и мало знаете про enum, то лучше начать с этого лонгрида. Сегодня обсудим итерацию через метод values и как его оптимизировать.
Итак, enums — это синтаксический сахар, который при компиляции превращается в обычный класс. Класс из примера выше превратится в
Если цикл с values используется в высоконагруженном коде, то разумно сохранить массив в отдельную переменную и переиспользовать её:
Пример из жизни
В Spring Web 5.2 в классе HttpStatus есть такой код:
Теперь код выглядит так:
Будет создано 3 массива: один внутри класса Number и два клона при вызове values()
Если вы новичок и мало знаете про enum, то лучше начать с этого лонгрида. Сегодня обсудим итерацию через метод values и как его оптимизировать.
Итак, enums — это синтаксический сахар, который при компиляции превращается в обычный класс. Класс из примера выше превратится в
public final class Number extends Enum<Number
>
Элементы енума станут статическими полями: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()) {Этот цикл вызывается почти в каждом запросе, но только в этом году завели баг. К описанию прилагался бенчмарк: при нагрузке 600 запросов/сек код производил мегабайт мусора каждую секунду.
if (status.value == statusCode) {
return status;
}
}
Теперь код выглядит так:
private static final HttpStatus[] VALUES;Ответ на вопрос перед постом
static {
VALUES = values();
}
for (HttpStatus status : VALUES) {
if (status.value == statusCode) {
return status;
}
}
Будет создано 3 массива: один внутри класса Number и два клона при вызове values()