Работа с перечислениями в android

120

Я почти закончил расчетную деятельность, с которой работаю в Android для своего приложения. Я пытаюсь создать Gender Enum, но по какой-то причине получаю синтаксическую ошибку, вставляю EnumBody для завершения EnumDeclaration.

public static enum Gender
{
    static
    {
        Female = new Gender("Female", 1);
        Gender[] arrayOfGender = new Gender[2];
        arrayOfGender[0] = Male;
        arrayOfGender[1] = Female;
        ENUM$VALUES = arrayOfGender;
    }
}

Я также пробовал использовать его без статического {}, но получаю ту же синтаксическую ошибку.

JMSDEV
источник
Перечисления не рекомендуются из-за проблем с производительностью, вместо этого используйте примитивные константы. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
ОБНОВЛЕНИЕ 2019: перечисления можно использовать в Android, поскольку ART заменил DALVIK в качестве среды выполнения stackoverflow.com/a/56296746/4213436 . Поэтому я думаю, что большинство ответов в этой теме неуместны.
JDenais
@JDenais, конечно, вы имеете в виду ветку 'вы', на которую только что ссылались
YoussefDir

Ответы:

343

Где, черт возьми, вы нашли этот синтаксис? Java Enums очень проста, вы просто указываете значения.

public enum Gender {
   MALE,
   FEMALE
}

Если вы хотите, чтобы они были более сложными, вы можете добавить к ним следующие значения.

public enum Gender {
    MALE("Male", 0),
    FEMALE("Female", 1);

    private String stringValue;
    private int intValue;
    private Gender(String toString, int value) {
        stringValue = toString;
        intValue = value;
    }

    @Override
    public String toString() {
        return stringValue;
    }
}

Затем, чтобы использовать перечисление, вы должны сделать что-то вроде этого:

Gender me = Gender.MALE
Паучок
источник
12
Я попробую, я сказал, что был абсолютным новичком
JMSDEV
87
Извините, я не имел в виду это отрицательно. Самый странный синтаксис, который я когда-либо видел для Enum
Spidy,
4
Также полезно упомянуть, что перечисления являются последовательными, поэтому вы можете использовать .ordinal () в перечислении, чтобы получить значение int.
Kalel Wade
1
Синтаксис в вопросе может возникнуть при использовании декомпилятора.
Дэн Гетц
9
Я так смеялся над тем, «Где ты нашел этот синтаксис». Как учитель говорит своему ученику
Зар Э Ахмер
50

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

Я цитирую:

Помните о накладных расходах памяти

Будьте осведомлены о стоимости и накладных расходах на язык и библиотеки, которые вы используете, и помните об этом при разработке приложения от начала до конца. Часто вещи на поверхности, которые выглядят безобидными, на самом деле могут иметь большой объем накладных расходов. Примеры включают:

  • Перечислениям часто требуется вдвое больше памяти, чем статическим константам. Вы должны строго избегать использования перечислений на Android.

  • Каждый класс в Java (включая анонимные внутренние классы) использует около 500 байт кода.

  • Каждый экземпляр класса имеет 12-16 байтов служебной памяти.

  • Ввод одной записи в HashMap требует выделения дополнительного объекта записи, который занимает 32 байта (см. Предыдущий раздел об оптимизированных контейнерах данных).

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

Были некоторые места, где они говорят, что эти советы устарели и больше не имеют ценности, но причина, по которой они продолжают их повторять, должна быть в том, что в этом есть доля правды. Написание приложения для Android - это то, что вам следует сделать как можно более легким для удобства пользователей. И каждый маленький дюйм производительности на счету!

Крис
источник
Были места - не могли бы вы добавить их, если знаете их? потому что я не могу найти ни одного
Кшиштоф Скшинецкий
9
Здесь кто-то заметил, что информация об использовании целых чисел вместо перечислений была удалена из Советов по производительности в официальной документации. Более того, я провел исследование и опубликовал сводку на Reddit
Кшиштоф Скшинецкий
1
Шаблоны производительности Android: цена ENUM (100 дней разработки Google)
Африза Н. Краткое описание
Ребята, у меня вопрос, если Enum - «плохая» практика, почему Google до сих пор поддерживает эту функцию Java с Android? :(
Хесус Кастро
5
@ JesúsCastro Потому что Google хочет гарантировать, что компании с большим количеством существующей бизнес-логики Java (которые могут использовать перечисления) могут просто перетащить свою библиотеку в проект Android и начать.
Дэвид Браун
22

Как прокомментировал Крис, перечисления требуют гораздо больше памяти на Android, которая складывается, поскольку они продолжают использоваться повсюду. Вместо этого вам следует попробовать IntDef или StringDef , которые используют аннотации, чтобы компилятор проверял переданные значения.

public abstract class ActionBar {
...
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

Его также можно использовать в качестве флагов, позволяющих выполнять бинарную композицию (операции ИЛИ / И).

РЕДАКТИРОВАТЬ : Кажется, что преобразование перечислений в целые числа является одной из оптимизаций по умолчанию в Proguard .

Начо Колома
источник
3
Мне нравится помещать константы int непосредственно в класс аннотации. Таким образом, это выглядит как обычное перечисление. Я описал это здесь: blog.shamanland.com/2016/02/int-string-enum.html
Алексей К.
17
public enum Gender {
    MALE,
    FEMALE
}
Габриэль Негут
источник
9

Согласно этому видео, если вы используете ProGuard, вам даже не нужно думать о проблемах с производительностью Enums !!

Proguard может во многих ситуациях оптимизировать Enums до значений INT от вашего имени, поэтому вам не нужно думать об этом или выполнять какую-либо работу.

Хани
источник
4

Предпочтительный подход Android - это константы типа int, применяемые с помощью @IntDef:

public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;

@Retention(RetentionPolicy.SOURCE)
@IntDef ({GENDER_MALE, GENDER_FEMALE})
public @interface Gender{}

// Example usage...
void exampleFunc(@Gender int gender) {
  switch(gender) {
  case GENDER_MALE:

     break;
  case GENDER_FEMALE:
     // TODO
     break;
  }
}

Документы: https://developer.android.com/studio/write/annotations.html#enum-annotations

Апт
источник