Я использую перечисления для замены String
константы в моем приложении Java (JRE 1.5).
Существует ли хит производительности, когда я рассматриваю перечисление как статический массив имен в методе, который постоянно называют (например, при рендеринге UI)?
Мой код немного походит на это:
public String getValue(int col) {
return ColumnValues.values()[col].toString();
}
values()
неоднократно (например, в краске () методы).int
=> enum
преобразование - который не является путем Java.Какова фактическая цена извлечения values()
массив? Это - даже проблема?
Ответ Read Simon Langhoff ниже, который указал ранее Фанатами На Объятиях в комментариях принятого ответа. Enum.values()
должен сделать защитную копию
Enum.values ()
дает вам ссылку на массив, и итерация по массиву перечислений стоит так же, как итерация по массиву струны. Между тем, сравнение значений перечисления с другими значениями перечисления может быть на быстрее , чем сравнение строк со строками.
Между тем, если вас беспокоит стоимость вызова метода values ()
по сравнению с уже имеющейся ссылкой на массив, не беспокойтесь. Вызов методов в Java (сейчас) невероятно быстр, и каждый раз, когда это действительно имеет значение для производительности, вызов метода все равно будет встроен компилятором.
Итак, серьезно, не беспокойтесь об этом. Вместо этого сконцентрируйтесь на удобочитаемости кода и используйте Enum
, чтобы компилятор уловил его, если вы когда-нибудь попытаетесь использовать постоянное значение, которое ваш код не ожидал обрабатывать.
Если вам интересно, почему сравнение enum может быть быстрее, чем сравнение строк, вот подробности:
Это зависит от того, были ли строки интернированы или нет. Для объектов Enum
в системе всегда есть только один экземпляр каждого значения перечисления, поэтому каждый вызов Enum.equals ()
может выполняться очень быстро, как если бы вы использовали оператор ==
вместо метода equals ()
. Фактически, с объектами Enum
безопасно использовать ==
вместо equals ()
, тогда как с небезопасно делать с струны.
Для строк, если строки были интернированы, то сравнение выполняется так же быстро, как и с Enum
. Однако, если строки не были интернированы, тогда метод String.equals ()
фактически должен пройти по списку символов в обеих строках, пока не закончится одна из строк или не будет обнаружен другой символ. между двумя струнами.
Но опять же, это, вероятно, не имеет значения, даже в коде рендеринга Swing, который должен выполняться быстро. : -)
@Ben Lings указывает, что Enum.values ()
должен выполнять защитную копию, поскольку массивы изменяемы, и вы можете заменить значение в массиве, возвращаемое ] Enum.values ()
. Это означает, что вам нужно учитывать стоимость этой защитной копии.Однако копирование одного непрерывного массива, как правило, является быстрой операцией, если предположить, что оно реализовано «под капотом» с использованием какого-либо вызова копирования из памяти, а не наивного перебора элементов в массиве. Так что я не думаю, что это меняет окончательный ответ.
Как эмпирическое правило: прежде чем думать об оптимизации, догадываетесь ли вы, что этот код может замедлить работу вашего приложения?
Теперь факты.
enum - это, по большей части, синтаксический сахар, рассыпающийся в процессе компиляции. Как следствие, метод values, определенный для класса enum, возвращает статическую коллекцию (то есть загруженную при инициализации класса) с характеристиками, которые можно считать примерно эквивалентными массиву.
Если вас беспокоит производительность, измерьте.
От кода я не ожидал никаких сюрпризов, но 90% всех предположений о производительности неверны. Если вы хотите быть в безопасности, подумайте о том, чтобы переместить перечисления в вызывающий код (например, public String getValue (ColumnValues value) {return value.toString ();}
).