2010-01-29 14 views
7

Ich habe tagelang gesucht, um eine Antwort auf dieses Performance-Problem zu finden.
Nach dem Graben des Internets habe ich gelernt, dass es mehrere Möglichkeiten gibt, die Enums in Java zu verwenden, gut dokumentiert in here. Nun, definitiv als Starter möchte man Enums in einem Switch-Case Anweisung verwenden, die Klarheit und besseres Verständnis des Codes bietet. Aber auf der anderen Seite haben wir eine Visitor Muster Stil-Implementierung der Enums als auch, die Typ Sicherheit und Erweiterbarkeit, Discussed here.Java Enums - Switch Statements vs Besuchermuster auf Enums - Leistungsvorteile?

Nachdem ich das gesagt habe und zurück zur ursprünglichen Idee hinter dieser Frage komme, habe ich bisher gelernt, dass ein Switch-Case-Konstrukt unter Verwendung von Enums richtig entworfen wurde, was sicherstellt, dass Case-Werte nicht spärlich sind und dass die Enum-Deklaration in der gleichen Kompilierungseinheit wie die switch-case-Anweisung, führt der Java-Compiler eine Optimierung des erzeugten Byte-Codes durch, indem er ein solches Konstrukt als Sprungtabelle (diskutiert in here und anderswo auch auf der Sun-Website, auf die ich die Verbindung verloren). Nun, das gibt definitiv einen Schub für die Leistung im Vergleich zu mehreren/verschachtelten If-Else-Konstrukt.

Meine Frage ist, wie implementiert Java die Besucher Muster basierte Implementierung von Enums in den resultierenden Byte-Code und was ist der Leistungsschub im Vergleich zu Switch-Fall basierte Implementierung, wenn überhaupt?

Und welche Art von Implementierung sollte ich bevorzugen, wenn man bedenkt, dass meine Enums in Zukunft wachsen können und ich bin auch sehr an der Leistung interessiert. Momentan habe ich 19 und ungerade Konstanten in meinem Enum.


EDIT
Ich habe eine Klasse, die einige Informationen über Variablen eines Spiels speichert. Eine der Variablen ist ein Enum Typ.

public class GameObject { 
    private Shape mShape; 

    public Shape getShape() { 
     return mShape; 
    } 
    . 
    . 
    . 

    public static enum Shape { 
     SHAPE1, SHAPE2, SHAPE3, SHAPE4, ..., SHAPE20 
    }; 

    public void drawShape() { 
     switch (this.mShape) { 
     case SHAPE1: 
      drawShape1(); 
      break; 
     case SHAPE2: 
      drawShape2(); 
      break; 
     case SHAPE3: 
      drawShape3(); 
      break; 
     case SHAPE4: 
      drawShape4(); 
      break; 
     . 
     . 
     . 
     . 
     . 
     case SHAPE20: 
      drawShape20(); 
      break; 
     default: 
      drawUnknown(); 
      break; 
     } 
    } 

}

Später erkannte ich die Informationen aus der Logik der Trennung, und schuf damit eine andere Klasse und bewegt die Enum Form von Gameobject zu dieser neuen Klasse GraphicModel, und anstatt Switch-Fall dort zu haben, implementierte ich konstant-spezifische Methoden. Und ja, ich habe nach dieser Modifikation richtige Importanweisungen in jede Klasse geschrieben.

public class GraphicModel { 
    public void drawGraphicFromObject(GameObject gameObject) { 
     gameObject.getShape().draw(); 
    } 

    public static enum Shape { 
     // This method is not public, instead is only called by GraphicModel 
     abstract void draw(); 

     SHAPE1 { 
      @Override 
      void draw() { 
       // some transformations 
      } 
     }, 
     SHAPE2 { 
      @Override 
      void draw() { 
       // Some different transformation 
      } 
     }, 
     SHAPE3 { 
      @Override 
      void draw() { 
       // Yet another transform 
      } 
     }, 
     . 
     . 
     . 
     . 
     UNKNOWN { 
      @Override 
      void draw() { 
       // 
      } 
     }; 
    } 
} 

Später ich dieses Muster basiert auf Besucher selbst implementiert als here vorgeschlagen

Also, was ich wissen muss, ist die, die Art und Weise der Umsetzung effizienter ist?Auf jeden Fall, für switch-case zu Sprungtabellen auf Kompilierung umgewandelt werden, erfordert Java sowohl Enum Erklärung und Schalter Anweisungen in derselben Kompilierungseinheit. Sollte ich verwenden Schalter basierte Implementierung oder Konstante-spezifische Methode Implementierung in meinem GraphicModel Klasse? Um klar zu sein, was ist der Unterschied in der Leistung?

+0

Bitte korrigieren Sie die Links –

+2

Haben Sie ein Beispiel für die am deutlichsten geschriebenen Code und eine Spezifikation und Testergebnisse, die zeigen, wie es die Spezifikation nicht Fleisch? Wenn nicht, sollten Sie noch nicht in diese Richtung denken. Wenn ja, poste den klar geschriebenen Code und ich wette, wir könnten einige wesentlichere Optimierungen finden. –

+0

Die verknüpfte SO-Frage sagt, wie Enums mit Besucher-Muster und nicht "Besucher Muster-Implementierung von Enums" verwendet werden kann. Ich denke, es wäre besser, wenn Sie sagen, was das Problem ist, das Sie versuchen zu lösen. Einmal, wenn Sie die Enums sehen können Als Lösung für Ihr Problem können Sie dann sehen, ob es optimiert werden muss – sateesh

Antwort

4

Aufzählungen sind, allgemein gesprochen, in vergleichbarer Leistung zu int Konstanten, verwendet, wenn in einer Schalter Anweisung (1).

Vielleicht sollten Sie lieber etwas in Richtung der Konstante spezifische Methode Implementierungen betrachten? z.B.

public enum Mode { 

    ON { Color color() {return Color.GREEN;}}, 
    OFF { Color color() {return Color.RED;}}, 
    STANDBY { Color color() {return Color.YELLOW;}}, 
    DEFAULT { Color color() {return Color.BLACK;}}; 

    abstract Color color(); 

}//enum Mode 

Und dann

getMode().color(); 

anstelle eines Schalter Anweisung verwenden ?!

Ich denke jedoch, dass für einen "Get a Color only case" vielleicht überhaupt keine Methoden benötigt werden.

Im Allgemeinen empfehle ich Ihnen Effective Java für Ihr Bücherregal. Kapitel 6 wäre derjenige, der Enums und Annotationen diskutiert.

+0

Danke für den Vorschlag, aber das war genau das, was ich das zweite Mal gemacht habe. Ich werde mir das Buch auch ansehen. – Darkfish