2017-01-02 10 views
0

Ich möchte C++ wie Enums in Java implementieren, also möchte ich statische Feld als ein Zähler verwenden. Dies ist meine aktuelle Lösung:Java - Enum mit statischen Zähler

public enum ETest 
{ 
    Test1(2), 
    Test2, 
    Test3, 
    Test4(7), 
    Test5; 

    private static class CounterHolder 
    { 
     private static int mCount = 0; 
    } 

    ETest() 
    { 
     mValue = CounterHolder.mCount; 
     CounterHolder.mCount++; 
    } 

    ETest(int pValue) 
    { 
     CounterHolder.mCount = pValue; 
     mValue = CounterHolder.mCount; 
     CounterHolder.mCount++; 
    } 

    public int toInt() 
    { 
     return mValue; 
    } 

    private final int mValue; 
} 

Aus dem obigen Code soll ich: Test1.toInt() -> 2, Test2.toInt() -> 3, Test3.toInt() -> 4, Test4 .toInt() -> 7, Test5.toInt() -> 8

Dieser Code funktioniert gut mit getesteten Android Java VM, aber ich bin mir nicht sicher, ob es ein gültiger Java-Code ist und ob es auf allen ordnungsgemäß funktioniert Gültige Java-VM, weil AFAIK-Enum vor statischen Feldern initialisiert wird, aber es sieht so aus als ob die Initialisierung bei Bedarf für verschachtelte Klassen mit statischem Feld in diesem Fall funktioniert (ohne geschachtelte Klasse funktioniert das einfache statische Feld nicht).

Mit freundlichen Grüßen, Patryk

+0

Don‘ t versuchen, C++ - Strukturen in Java zu übersetzen. Java enumiert zu mächtig, um als einfache C++ - Wertcontainer missbraucht zu werden. –

+0

Ich bin mir ziemlich sicher, dass dieser Code wird nicht kompilieren - bitte verwenden Sie echten Code in Fragen ... –

+0

@GyroGearless Nun, dieser Code kompiliert, weil ich Initialisierung auf Anfrage verwendet habe, bin ich nur nicht sicher, ob es nicht verursachen wird Probleme zur Laufzeit auf anderen JVM. – nadro

Antwort

0

CounterHolder wird immer geladen und vor ETest initialisiert werden initialisiert, damit Ihr Code sollte wie bei allen konformen JVMs erwartet. Sie können mehr über Klasseninitialisierung in der JLS lesen (nicht sicher, was das entsprechende Dokument für Android ist, aber ich würde erwarten, dass sie eine sehr ähnliche Formulierung haben). Insbesondere:

eine Klasse oder Schnittstellentyp T wird unmittelbar vor dem ersten Auftreten von einem der folgenden Schritte initialisiert werden:

  • [...]
  • ein statisches Feld von T erklärt wird verwendet und das Feld ist keine konstante Variable.

So spätestens die CounterHolder Klasse geladen und vor dem ersten Konstruktor ETest läuft initialisiert werden.

ist jedoch zu beachten, dass aus einem Stil Sicht wäre es wahrscheinlich sauberer sein, schreiben einfach:

enum ETest { 
    Test1(2), 
    Test2(3), 
    Test3(4), 
    Test4(7), 
    Test5(8); 
} 
0

Eigentlich können Sie das tun einfach eine Map innerhalb des ENUM verwenden wie so

public enum TestEnum { 
    Test1(2), 
    Test2, 
    Test3, 
    Test4(7), 
    Test5; 

    private static Map<TestEnum, Integer> map = new HashMap<>(); 

    static { 
     int counter = 0; 
     for (TestEnum enun : TestEnum.values()) { 

      counter = Math.max(counter, enun.value); 
      if (enun.value == 0) { 
       counter++; 
      } 
      map.put(enun, counter); 
     } 
    } 

    private int value; 

    TestEnum() { 
     value = 0; 
    } 

    TestEnum(int pValue) { 
     value = pValue; 
    } 

    public int toInt() { 
     return map.get(this); 
    } 
} 

und Hier ist die Funktion zum Ausdrucken der Ergebnisse

for (TestEnum anEnum : TestEnum.values()) { 
    System.out.println(anEnum.name() +" = "+ String.valueOf(anEnum.toInt())); 
} 

und die ou tput ist:

Test1 = 2 
Test2 = 3 
Test3 = 4 
Test4 = 7 
Test5 = 8 

TIPP: prüfen etwas ordinal genannt, es ist eine Ordnungs der Enumerationskonstante (seine Position in seiner Enum Erklärung, wo die anfängliche konstant eine Ordnungs von Null zugewiesen).

+0

Danke, Ich möchte jedoch keinen Overhead in Bezug auf HashMap für diese einfache Aufgabe. – nadro

+0

Nun, es gibt 'EnumMap', genau um den" Overhead in Bezug auf HashMap "zu vermeiden, wenn der Schlüsseltyp ein' enum' Typ ist. Da "Wert" nicht "final" ist, könnte der statische Initialisierer die Nullwerte einfach überschreiben, anstatt eine Karte zu füllen, und 'toInt' kann wie zuvor funktionieren ... – Holger

0

In android, das beste Praxis vermeiden Enum zu verwenden, für den Hauptgrund ist anti-optimize Leistung, auf Basis von Android Dokumentation:

Aufzählungen erfordern oft mehr als doppelt so viel Speicher wie statische Konstanten. Sie sollten strikt vermeiden, Enums auf Android zu verwenden.

In anderen Seite android Zweck der Lösung der Typ def Anmerkung:

Die @IntDef Anmerkung lässt Sie im Grunde eine „typedef“ schaffen, wo Sie eine andere Anmerkung erstellen, die Konstanten der gültige ganze Zahl darstellt, dass Sie erwarten, und dann schmücken Sie Ihre API mit dieser typedef Annotation. Hier

ist ein Beispiel Beispiel, wie es zu benutzen (checker Tage ...): https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

Und für mehr erkennende Funktionen können Sie die offizielle Dokumentation lesen: https://developer.android.com/studio/write/annotations.html#enum-annotations