Повернення Java Enum Int


76

У мене проблеми з оголошенням переліку. Те, що я намагаюся створити, це перелік для типу "DownloadType", де є 3 типи завантаження (AUDIO, VIDEO, AUDIO_AND_VIDEO).

Я реалізував код наступним чином:

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    private final int value;

    private DownloadType(int value) {
        this.value = value;
    }
}

Це чудово працює, якщо я потім використовую його так:

DownloadType.AUDIO_AND_VIDEO.value;

Однак я хотів би, щоб мені не довелося просити "значення". Я можу помилятися, але це спосіб роботи декількох класів на Java, таких як Шрифт, наприклад, щоб встановити стиль шрифту, який Ви використовуєте:

Font.PLAIN

Що повертає значення int, ми не використовуємо:

Font.PLAIN.value

1
Ви можете просто використовувати DownloadType.AUDIO_AND_VIDEO також, якщо вам не потрібне значення, я чогось не впускаю?
kosa

@Nambari Якщо я System.out.println (DownloadType.AUDIO_AND_VIDEO), він повертає "AUDIO_AND_VIDEO", який, мабуть, має тип "DownloadType", а не int.
Крістіан

3
Я думаю, ви плутаєте мету перелічень. Навіщо вам також ціле число?
Живінгс

Оскільки я думав, чи хочу я тоді отримати тип, який я міг би використовувати 'if (downloadType == DownloadType.AUDIO) {}', це не так?
Крістіан

1
Це toString()метод, який викликається під час друку об’єкта. Крім того, PLAIN - це константа в Fontкласі, а не перелік.
Андрій Логвінов,

Відповіді:


102

Font.PLAIN це НЕ перерахування. Це просто int. Якщо вам потрібно вивести значення з переліку, ви не можете уникнути виклику методу або використання a .value, оскільки перелічення насправді є об'єктами власного типу, а не примітивами.

Якщо вам справді потрібне лише int, і ви вже погоджуєтесь з тим, що типова безпека втрачена, користувач може передавати недійсні значення вашому API, ви можете визначити ці константи intтакож:

public final class DownloadType {
    public static final int AUDIO = 0;
    public static final int VIDEO = 1;
    public static final int AUDIO_AND_VIDEO = 2;

    // If you have only static members and want to simulate a static
    // class in Java, then you can make the constructor private.
    private DownloadType() {}
}

До речі, valueполе насправді надлишкове, оскільки існує також .ordinal()метод, тому ви можете визначити enumяк:

enum DownloadType { AUDIO, VIDEO, AUDIO_AND_VIDEO }

і отримати "значення" за допомогою

DownloadType.AUDIO_AND_VIDEO.ordinal()

Редагувати : Виправлений код .. static classне дозволено в Java. Дивіться цю відповідь SO із поясненнями та подробицями щодо визначення статичних класів у Java.


Дякую за роз'яснення, зараз це має сенс. Замість того, щоб створювати перерахування, я зроблю загальнодоступний тип завантаження {private static final int AUDIO = 0; } ... Це має бути InnerClass? Дякую за вашу відповідь.
Крістіан

@Cristian: Це головним чином залежить від того, як ви хочете отримати до нього доступ.
kennytm

Дякую за відповіді, саме те, що я шукав - чекаю 3 хв, щоб прийняти
Крістіан

Ви мали на увазі public static final int AUDIO = 0;. Наскільки я знаю, constце не дійсне ключове слово Java.
Бенджамін

2
порядковий може призвести до менш стабільної системи
hychou

60

Якщо вам потрібно отримати значення int, просто знайдіть значення для цього значення у вашому ENUM:

private enum DownloadType {
    AUDIO(1), VIDEO(2), AUDIO_AND_VIDEO(3);
    private final int value;

    private DownloadType(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public static void main(String[] args) {
    System.out.println(DownloadType.AUDIO.getValue());           //returns 1
    System.out.println(DownloadType.VIDEO.getValue());           //returns 2
    System.out.println(DownloadType.AUDIO_AND_VIDEO.getValue()); //returns 3
}

Або ви можете просто використати ordinal()метод, який поверне позицію константи перерахування в переліку.

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    //rest of the code
}

System.out.println(DownloadType.AUDIO.ordinal());            //returns 0
System.out.println(DownloadType.VIDEO.ordinal());            //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.ordinal()); //returns 2

3
Навіщо потрібен додатковий метод, коли ви можете просто викликати .value, і вже існує метод ordinal () для отримання цілого числа.
kosa

@Nambari umm, dint know enum має порядковий номер ... як
дурно

@GanGnaMStYleOverFlowErroR Дякую за відповідь, але я насправді прагнув уникнути виклику .value, не кажучи вже про створення іншого методу та виклик getValue () :)
Крістіан

@GanGnaMStYleOverFlowErroR: Це правильно, я міг би це пояснити у своєму коментарі.
kosa

@Nambari no problomo, дякую, що повідомили мене про ordinal () :)
PermGenError

16

Спочатку вам слід задати собі таке запитання: чи вам справді потрібен int?

Призначення перелічень - це колекція елементів (констант), які мають значення в коді, не покладаючись на зовнішнє значення (наприклад, int). Перерахування на Java можуть бути використані як аргумент для статусів перемикачів, і їх можна безпечно порівнювати, використовуючи оператор рівності "==" (серед інших).

Пропозиція 1 (не потрібно):

Часто за цим не потрібно ціле число, тоді просто використовуйте це:

private enum DownloadType{
    AUDIO, VIDEO, AUDIO_AND_VIDEO
}

Використання:

DownloadType downloadType = MyObj.getDownloadType();
if (downloadType == DownloadType.AUDIO) {
    //...
}
//or
switch (downloadType) {
  case AUDIO:  //...
          break;
  case VIDEO: //...
          break;
  case AUDIO_AND_VIDEO: //...
          break;
}

Пропозиція 2 (потрібна int):

Тим не менше, іноді може бути корисно перетворити перерахування на int (наприклад, якщо зовнішній API очікує значень int). У цьому випадку я б порадив позначити методи як методи перетворення за допомогою toXxx()-Style. Для заміни друку toString().

private enum DownloadType {
    AUDIO(2), VIDEO(5), AUDIO_AND_VIDEO(11);
    private final int code;

    private DownloadType(int code) {
        this.code = code;
    }

    public int toInt() {
        return code;
    }

    public String toString() {
        //only override toString, if the returned value has a meaning for the
        //human viewing this value 
        return String.valueOf(code);
    }
}

System.out.println(DownloadType.AUDIO.toInt());           //returns 2
System.out.println(DownloadType.AUDIO);                   //returns 2 via `toString/code`
System.out.println(DownloadType.AUDIO.ordinal());         //returns 0
System.out.println(DownloadType.AUDIO.name());            //returns AUDIO
System.out.println(DownloadType.VIDEO.toInt());           //returns 5
System.out.println(DownloadType.VIDEO.ordinal());         //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.toInt()); //returns 11

Резюме

  • Не використовуйте ціле число разом із переліченням, якщо вам не потрібно.
  • Не покладайтесь на використання ordinal()для отримання цілого числа переліку, оскільки це значення може змінитися, якщо ви зміните порядок (наприклад, вставивши значення). Якщо ви розглядаєте можливість використання, ordinal()можливо, краще скористатися пропозицією 1.
  • Зазвичай не використовуйте int-константи замість перелічень (як у прийнятій відповіді), оскільки ви втратите тип-безпеки.

+1 за вказівку, toString()хоча int стає String, і я не буду використовувати його через це :)
António Almeida

... потім використовуйте ordinal(). Але toInt()краще, на мій погляд
yonojoy

10

Просто викличте ordinal()метод із значенням переліку, щоб отримати відповідний номер. Не потрібно оголошувати атрибут додавання з його значенням, кожне перераховане значення отримує власний номер за замовчуванням, присвоєний починаючи з нуля, збільшуючи на одиницю для кожного значення в тому самому порядку, в якому вони були оголошені.

Ви не повинні залежати від intзначення an enum, лише від його фактичного значення. Enum в Java - це інший тип чудовиська і не схожий на enum в C, де ви залежате від їх цілочислового коду.

Щодо прикладу, який ви навели у питанні, це Font.PLAINпрацює, оскільки це лише ціла константа класу Font. Якщо вам абсолютно потрібен (можливо, змінюється) числовий код, тоді an enumне є правильним інструментом для роботи, краще дотримуйтесь числових констант.


1
Мені відомо про ordinal (), але якщо тоді я хочу змінити або вказати інший порядок у майбутньому, це спричинить проблеми. Я хотів би вказати значення int
Крістіан

1
@Cristian, ти не повинен залежати від значення int переліку, лише від його фактичного значення. Перелічення в Java не схожі на перелічення в C, де ви залежате від їх цілочисельного коду.
Оскар Лопес

@Cristian, а щодо прикладу, який ви навели у питанні, Font.PLAINпрацює, оскільки це просто ціла константа Fontкласу. Якщо вам абсолютно потрібен (можливо, змінюється) числовий код, тоді an enumне є правильним інструментом для роботи, краще дотримуйтесь числових констант.
Оскар Лопес

5

Ви можете спробувати цей код.

private enum DownloadType {
    AUDIO , VIDEO , AUDIO_AND_VIDEO ;

}

Ви можете використовувати це перерахування , як наприклад: DownloadType.AUDIO.ordinal(). Сподіваюся, цей фрагмент коду вам допоможе.


3

Якщо ви об'єднуєте перерахування за допомогою рядка, ви можете замінити метод toString, щоб повернути int:

public String toString() {
    return value + "";
}

Тоді ви можете просто використовувати:

String something = "foo" + DownloadType.AUDIO;

і буде викликано метод toString ().


Зауважте, що програмне використання toString () зазвичай вважається поганою практикою - воно призначене лише для людських очей, однак це єдиний спосіб досягти того, про що ви просите.


3

Ви хочете отримати цей код?

public static enum FieldIndex {
    HDB_TRX_ID,     //TRX ID
    HDB_SYS_ID      //SYSTEM ID
}

public String print(ArrayList<String> itemName){
    return itemName.get(FieldIndex.HDB_TRX_ID.ordinal());
}

2

На мій погляд найбільш читабельна версія

public enum PIN_PULL_RESISTANCE {
    PULL_UP {
        @Override
        public int getValue() {
            return 1;
        }
    },
    PULL_DOWN {
        @Override
        public int getValue() {
            return 0;
        }
    };

    public abstract int getValue();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.