Почему Android не использует больше перечислений?


79

Мне очень нравится использовать перечисления C # и Java в моем коде по нескольким причинам:

  • Они намного более безопасны в отношении типов, чем целые числа, строки или наборы логических флагов.
  • Они приводят к более читаемому коду.
  • Установить недопустимое значение для перечисления труднее, чем для int или строки.
  • Они позволяют легко обнаружить допустимые значения переменной или параметра.
  • Все, что я прочитал, указывает на то, что они работают так же хорошо, как целые числа в C # и большинстве JVM.

Однако в платформе Android есть множество случаев, когда необходимо передавать флаги различных типов, но ни один из них, похоже, не использует перечисления. Вот несколько примеров, когда я думаю, что их использование было бы полезным: Toast.LENGTH_SHORT/ Toast.LENGTH_LONGи View.GONE, View.VISIBLEи т. Д.

Почему это? Перечисления работают хуже, чем простые целочисленные значения в Dalvik? Есть ли еще какой-то недостаток, о котором я не знаю?


10
Теперь можно использовать enum. См. Stackoverflow.com/questions/5143256/…
Тьерри-Димитри Рой

1
Большой! Мне нравятся перечисления, и я еще не успел их вынуть.
We All Monica

Ответы:


66

Этот ответ устарел по состоянию на март 2011 года.

Enums можно использовать на Froyo и выше - согласно этому ответу ( почему из советов по производительности Android было удалено «Avoid Enums Where You Only Need Ints»? ) От члена команды Android VM (и его блога ).


Предыдущий ответ:

Официальная рекомендация команды Android - избегать перечислений всякий раз, когда можно этого избежать:

Перечисления очень удобны, но, к сожалению, могут быть неприятными, когда имеют значение размер и скорость. Например, это:

public enum Shrubbery { GROUND, CRAWLING, HANGING }

добавляет 740 байт в ваш файл .dex по сравнению с эквивалентным классом с тремя общедоступными статическими конечными int. При первом использовании инициализатор класса вызывает метод для объектов, представляющих каждое из перечисленных значений. Каждый объект получает собственное статическое поле, а полный набор хранится в массиве (статическое поле с именем «$ VALUES»). Это много кода и данных, всего для трех целых чисел. Дополнительно это:

Shrubbery shrub = Shrubbery.GROUND;

вызывает поиск статического поля. Если бы "GROUND" было статическим конечным int, компилятор рассматривал бы его как известную константу и вставлял бы его.

Источник: Избегайте перечислений, где вам нужны только интенты


4
Таким образом , в то время как C # перечислений действительно выполняют очень хорошо, Java перечислений не так как они являются более сложными. Поэтому мой последний пункт на самом деле не соответствует действительности. Верный?
We All Monica

25
Вероятно, это больше не действует, см. Stackoverflow.com/questions/5143256/…
Виктор Даль

2
В документации Android по-прежнему рекомендуется не использовать перечисления: «Перечисления часто требуют вдвое больше памяти, чем статические константы. Вы должны строго избегать использования перечислений на Android». developer.android.com/training/articles/memory.html#Overhead
ThomasW 01

1
@ SebastianPaaskeTørholm По предоставленной вами ссылке (это: developer.android.com/guide/practices/design/… ) подсказка больше не отображается.
разработчик Android

14

Целые числа меньше и требуют меньше накладных расходов, что по-прежнему имеет значение на мобильных устройствах.


Вдобавок теперь у нас есть хороший инструмент для Android Studio и Lint. Я имею в виду аннотации IntDefи StringDef, которые позволяют объявить какой-то typedef , поэтому использование констант int очень удобно. blog.shamanland.com/2016/02/int-string-enum.html
Алексей К.

да, но как насчет моделей Retrofit? (и для других сетевых библиотек, я полагаю) Как бы вы определили статусный ответ (например, успешно, неудачно, token_expired) для непосредственного сопоставления с POJO?
Мицест

5

Мой коллега провел небольшой тест относительно этой ситуации. Он автоматически сгенерировал a classи an enumс одинаковым количеством «перечислений». Я считаю, что он создал 30000 записей.

Результаты были:

  • .classдля classпримерно 1200 КБ
  • .classдля enumпримерно 800 КБ

Надеюсь, это кому-то поможет.


Я не думаю, что это верный тест. Наличие 30000 перечислений / статических полей в одном месте - нереальный сценарий. Вам нужно будет сравнить размер большого количества небольших классов / перечислений, например, 1000 классов / перечислений по 30 свойств каждый. Готов поспорить, что общий размер будет совсем другим.
Iwo Banas

7
@Iwo Banas Любой тест - это действительный тест. Не сказал, что ответит на вопрос. Просто предлагал это как дополнительную информацию для всех, кто может быть заинтересован. И голос "против" кажется очень заслуженным, так что спасибо. -_-
prolink007

Разве не обратное? Это перечисление использует меньше? И это память или хранилище размером 1200 КБ или 800 КБ?
разработчик Android
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.