Java Enum return Int

75

Ich habe Probleme, eine Aufzählung zu deklarieren. Was ich versuche zu erstellen, ist eine Aufzählung für einen 'DownloadType', bei dem es 3 Download-Typen gibt (AUDIO, VIDEO, AUDIO_AND_VIDEO).

Ich habe den Code wie folgt implementiert:

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

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

Das funktioniert gut, wenn ich es dann so benutze:

DownloadType.AUDIO_AND_VIDEO.value;

Ich möchte es jedoch, damit ich nicht nach dem 'Wert' fragen muss. Ich kann mich irren, aber auf diese Weise arbeiten mehrere Klassen in Java, z. B. Schriftart, um beispielsweise einen Schriftstil festzulegen, den Sie verwenden:

Font.PLAIN

Was einen int-Wert zurückgibt, verwenden wir nicht:

Font.PLAIN.value
Cristian
quelle
1
Sie können DownloadType.AUDIO_AND_VIDEO auch einfach verwenden, es sei denn, Sie benötigen einen Wert. Fehlt mir etwas?
kosa
@Nambari Wenn ich System.out.println (DownloadType.AUDIO_AND_VIDEO), gibt es "AUDIO_AND_VIDEO" zurück, das anscheinend vom Typ 'DownloadType' ist, nicht int.
Cristian
3
Ich denke, Sie verwirren den Zweck von Aufzählungen. Warum brauchen Sie auch die ganze Zahl?
Jivings
Weil ich dachte, wenn ich dann den Typ bekommen möchte, den ich verwenden könnte 'if (downloadType == DownloadType.AUDIO) {}', ist das nicht richtig?
Cristian
1
Diese toString()Methode wird aufgerufen, wenn Sie Ihr Objekt drucken. Außerdem ist PLAIN eine Konstante in der FontKlasse, keine Aufzählung.
Andrew Logvinov

Antworten:

102

Font.PLAIN ist keine Aufzählung. Es ist nur ein int. Wenn Sie den Wert aus einer Aufzählung entfernen müssen, können Sie es nicht vermeiden, eine Methode aufzurufen oder eine zu verwenden .value, da Aufzählungen tatsächlich Objekte ihres eigenen Typs und keine Grundelemente sind.

Wenn Sie wirklich nur ein benötigen int, und Sie sind bereits , dass Typsicherheit zu übernehmen, um den Benutzer verloren möglicherweise ungültige Werte zu Ihrem API übergeben, Sie können diese Konstanten definieren intauch:

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() {}
}

Übrigens ist das valueFeld tatsächlich redundant, da es auch eine .ordinal()Methode gibt, sodass Sie Folgendes definieren können enum:

enum DownloadType { AUDIO, VIDEO, AUDIO_AND_VIDEO }

und erhalten Sie den "Wert" mit

DownloadType.AUDIO_AND_VIDEO.ordinal()

Bearbeiten : Der Code wurde korrigiert. static classIst in Java nicht zulässig. In dieser SO-Antwort finden Sie Erläuterungen und Details zum Definieren statischer Klassen in Java.

kennytm
quelle
Vielen Dank für die Klarstellung, das macht jetzt Sinn. Anstatt eine Aufzählung zu erstellen, erstelle ich einen öffentlichen DownloadType {private static final int AUDIO = 0; } ... Sollte dies eine InnerClass sein? Danke für deine Antwort.
Cristian
@Cristian: Es hängt hauptsächlich davon ab, wie Sie darauf zugreifen möchten.
Kennytm
Vielen Dank für Ihre Antworten, war genau das, wonach ich gesucht habe - 3 Minuten warten, um zu akzeptieren
Cristian
Meinen Sie public static final int AUDIO = 0;. Soweit ich weiß, constist dies kein gültiges Java-Schlüsselwort.
Benjamin
2
Ordnungszahl kann zu einem weniger stabilen System führen
Hychou
59

Wenn Sie den int-Wert erhalten müssen, haben Sie einfach einen Getter für den Wert in Ihrem 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
}

Oder Sie können einfach die ordinal()Methode verwenden, die die Position der Aufzählungskonstante in der Aufzählung zurückgibt.

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
PermGenError
quelle
3
Warum benötigen Sie eine zusätzliche Methode, wenn Sie einfach .value aufrufen können und bereits eine Methode ordinal () zum Abrufen der Ganzzahl vorhanden ist?
kosa
@Nambari umm, nicht wissen, Enum hat Ordnungszahl .. wie dumm von mir: P
PermGenError
@ GanGnaMStYleOverFlowErroR Danke für die Antwort, aber ich wollte eigentlich vermeiden, .value aufzurufen, geschweige denn eine andere Methode zu erstellen und getValue () aufzurufen :)
Cristian
@GanGnaMStYleOverFlowErroR: Das ist richtig, das hätte ich in meinem Kommentar klarstellen können.
kosa
@Nambari kein Problem, danke, dass Sie mich über ordinal ()
informiert haben
15

Zuerst sollten Sie sich folgende Frage stellen: Benötigen Sie wirklich einen Int?

Der Zweck von Aufzählungen besteht darin, eine Sammlung von Elementen (Konstanten) zu haben, die im Code eine Bedeutung haben, ohne sich auf einen externen Wert (wie ein int) zu verlassen. Aufzählungen in Java können als Argument für Switch-Anweisungen verwendet und mit dem Gleichheitsoperator "==" (unter anderem) sicher verglichen werden.

Vorschlag 1 (kein int erforderlich):

Oft ist keine Ganzzahl dahinter erforderlich. Verwenden Sie dann einfach Folgendes:

private enum DownloadType{
    AUDIO, VIDEO, AUDIO_AND_VIDEO
}

Verwendung:

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

Vorschlag 2 (int benötigt):

Trotzdem kann es manchmal nützlich sein, eine Aufzählung in eine int zu konvertieren (zum Beispiel, wenn eine externe API int-Werte erwartet). In diesem Fall würde ich empfehlen, die Methoden mit dem toXxx()-Style als Konvertierungsmethoden zu markieren . Zum Drucken überschreiben 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

Zusammenfassung

  • Verwenden Sie keine Ganzzahl zusammen mit einer Aufzählung, wenn Sie nicht müssen.
  • Verlassen Sie sich nicht darauf ordinal(), eine Ganzzahl einer Aufzählung zu verwenden, da sich dieser Wert ändern kann, wenn Sie die Reihenfolge ändern (z. B. durch Einfügen eines Werts). Wenn Sie die Verwendung in Betracht ziehen, ist ordinal()es möglicherweise besser, Vorschlag 1 zu verwenden.
  • Verwenden Sie normalerweise keine int-Konstanten anstelle von Aufzählungen (wie in der akzeptierten Antwort), da Sie die Typensicherheit verlieren.
yonojoy
quelle
+1 für das Zeigen, toString()obwohl das int ein String wird und ich es deswegen nicht verwenden werde :)
António Almeida
... dann verwenden ordinal(). Aber toInt()ist meiner Meinung nach besser
yonojoy
10

Rufen Sie die ordinal()Methode einfach für einen Enum-Wert auf, um die entsprechende Nummer abzurufen. Es ist nicht erforderlich, ein Additionsattribut mit seinem Wert zu deklarieren. Jeder aufgezählte Wert erhält standardmäßig eine eigene Nummer, die ab Null zugewiesen wird und für jeden Wert in derselben Reihenfolge, in der er deklariert wurde, um eins erhöht wird.

Sie sollten sich nicht auf den intWert von a verlassen enum, sondern nur auf den tatsächlichen Wert. Aufzählungen in Java sind eine andere Art von Monster und nicht wie Aufzählungen in C, bei denen Sie von ihrem ganzzahligen Code abhängen.

In Bezug auf das Beispiel, das Sie in der Frage angegeben haben, Font.PLAINfunktioniert dies, da dies nur eine ganzzahlige Konstante der Font-Klasse ist. Wenn Sie unbedingt einen (möglicherweise sich ändernden) numerischen Code benötigen, ist ein enumnicht das richtige Werkzeug für den Job. Halten Sie sich besser an numerische Konstanten.

Óscar López
quelle
1
Mir ist ordinal () bekannt, aber wenn ich dann in Zukunft eine andere Reihenfolge ändern oder angeben möchte, führt dies zu Problemen. Ich möchte den int-Wert angeben
Cristian
1
@Cristian Sie sollten nicht vom int-Wert einer Aufzählung abhängen, sondern nur vom tatsächlichen Wert. Aufzählungen in Java sind nicht wie Aufzählungen in C, bei denen Sie von ihrem Ganzzahlcode abhängen.
Óscar López
@Cristian und in Bezug auf das Beispiel, das Sie in der Frage angegeben haben, Font.PLAINfunktionieren, da dies nur eine ganzzahlige Konstante der FontKlasse ist. Wenn Sie unbedingt einen (möglicherweise sich ändernden) numerischen Code benötigen, ist ein enumnicht das richtige Werkzeug für den Job. Halten Sie sich besser an numerische Konstanten.
Óscar López
5

Sie können diesen Code ausprobieren.

private enum DownloadType {
    AUDIO , VIDEO , AUDIO_AND_VIDEO ;

}

Sie können diese Aufzählung wie folgt verwenden : DownloadType.AUDIO.ordinal(). Hoffe, dieses Code-Snippet wird Ihnen helfen.

Osimer Pothe
quelle
3

Wenn Sie die Aufzählung mit einer Zeichenfolge verketten, können Sie die toString-Methode überschreiben, um int:

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

Dann könnten Sie einfach verwenden:

String something = "foo" + DownloadType.AUDIO;

und die toString () -Methode wird aufgerufen.


Beachten Sie, dass die programmgesteuerte Verwendung von toString () im Allgemeinen als schlechte Praxis angesehen wird. Sie ist nur für menschliche Augen gedacht. Dies ist jedoch der einzige Weg, um das zu erreichen, was Sie verlangen.

Böhmisch
quelle
3

Möchten Sie diesen Code?

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());
}
Seyeon
quelle
2

Meiner Meinung nach die am besten lesbare Version

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();
}
Ladislav Havlik
quelle