Почему 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.