Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage
 <<    <     >    >>   API  Kapitel 11 - OOP IV: Verschiedenes

11.3 Aufzählungstypen



11.3.1 Grundlagen

In der Praxis hat man es häufig mit Datentypen zu tun, deren Werte aus einem kleinen, konstanten Wertevorrat entnommen werden. Beispiele sind die booleschen Werte TRUE und FALSE, die Jahreszeiten FRUEHLING, SOMMER, HERBST und WINTER oder die Anredekennzeichen HERR, FRAU, FRÄULEIN und FIRMA.

Um mit solchen Daten arbeiten zu können, gibt es in vielen Programmiersprachen Aufzählungstypen, die es erlauben, einen solchen Datentyp zu definieren und seine möglichen Wert-Ausprägungen explizit festzulegen. Variablen oder Parameter dieses Typs können dann jeweils nur die vereinbarten Werte enthalten. In Sprachen, die das nicht vorsehen, behilft man sich meist mit kleinen Ganzzahlen, die auf Konstanten gelegt werden, hat dann aber keine Typsicherheit mehr. Der Compiler kann bei dieser Technik nicht unterscheiden, ob etwa an einen Methodenparameter einer der zulässigen Aufzählungswerte übergeben wurde oder ein unzulässiger Wert aus dem übrigen Wertebereich der Ganzzahlen.

In der Java-Community gab es seit ca. 2004 einige Ideen, wie man einen Aufzählungstyp in Java realisieren könnte. Joshua Bloch hat in seinem Buch »Effective Java« einen sehr ausgefeilten Vorschlag zu dessen Realisierung gemacht. Mit der J2SE 5.0 hat er sich ein Denkmal gesetzt und diesen Vorschlag in den Kern der Sprache eingebaut. Neu eingeführt wurde dazu das Schlüsselwort enum, mit dessen Hilfe ein Aufzählungstyp definiert werden kann. In seiner einfachsten Form hat er folgende Syntax:

enum Typname ( Wert1, Wert2, Wert3, ...)

Durch diese Deklaration wird ein Datentyp Typname vereinbart, der als möglichen Inhalt die Werte Typname.Wert1, Typname.Wert2, Typname.Wert3 usw. annehmen kann. Unter Verwendung des Typnamens können Variablen oder Parameter deklariert werden und die Werte können diesen zugewiesen oder in Ausdrücken zur Abfrage verwendet werden. Aufzählungen sind als Klassen und ihre Werte als Objekte realisiert und neben den beschriebenen besitzen Aufzählungstypen noch eine Reihe weiterer nützlicher Eigenschaften:

Das folgende Beispiel zeigt diese Eigenschaften in der praktischen Anwendung:

001 /* Listing1108.java */
002 
003 public class Listing1108
004 {
005   enum Farbe {ROT, GRUEN, BLAU, GELB};
006 
007   public static void farbVergleich(Farbe f1, Farbe f2)
008   {
009     System.out.print(f1);
010     System.out.print(f1.equals(f2) ? " = " : " != ");
011     System.out.println(f2);
012   }
013 
014   public static String toRGB(Farbe f)
015   {
016     String ret = "?";
017     switch (f) {
018       case ROT:   ret = "(255,0,0)"; break;
019       case GRUEN: ret = "(0,255,0)"; break;
020       case BLAU:  ret = "(0,0,255)"; break;
021       case GELB:  ret = "(255,255,0)"; break;
022     }
023     return ret;
024   }
025 
026   public static void main(String[] args)
027   {
028     //Aufzählungsvariablen
029     Farbe f1 = Farbe.ROT;
030     Farbe f2 = Farbe.BLAU;
031     Farbe f3 = Farbe.ROT;
032     //toString() liefert den Namen
033     System.out.println("--");
034     System.out.println(f1);
035     System.out.println(f2);
036     System.out.println(f3);
037     //equals funktioniert auch
038     System.out.println("--");
039     farbVergleich(f1, f2);
040     farbVergleich(f1, f3);
041     farbVergleich(f2, f3);
042     farbVergleich(f1, f1);
043     //Die Methode values()
044     System.out.println("--");
045     for (Farbe f : Farbe.values()) {
046       System.out.println(f + "=" + toRGB(f));
047     }
048   }
049 }
Listing1108.java
Listing 11.8: Anwendung von Aufzählungstypen

Das Programm erzeugt folgende Ausgabe:

--
ROT
BLAU
ROT
--
ROT != BLAU
ROT = ROT
BLAU != ROT
ROT = ROT
--
ROT=(255,0,0)
GRUEN=(0,255,0)
BLAU=(0,0,255)
GELB=(255,255,0)

Zunächst wird ein Aufzählungstyp Farbe vereinbart, mit den Werten ROT, GRUEN, BLAU und GELB. In main werden dann einige Variablen deklariert, ihnen Werte zugewiesen und diese mit toString auf der Konsole ausgegeben. Der Aufruf von farbVergleich zeigt, wie man Farben als Parameter an eine Methode übergibt. In der Methode wird mit Hilfe von equals verglichen, ob die beiden Werte übereinstimmen. Die Methode toRGB zeigt schließlich die Anwendung der switch-Anweisung auf Aufzählungstypen. Sie wird in einer values-Schleife auf alle Farbwerte angewendet.

11.3.2 Erweiterung der Aufzählungsklasse

Wie schon erwähnt, werden Aufzählungstypen in (lokale) Klassen übersetzt (siehe Abschnitt 11.1) und ihre Werte werden zu Instanzen dieser Klasse. Konsequenterweise bietet der Aufzählungstyp die Möglichkeit, diese Klasse direkt bei der Deklaration zu erweitern, etwa um eigene Membervariablen oder Methoden und damit zusätzliche »Intelligenz« in den Aufzählungstyp oder seine Werte zu packen. Wir wollen dazu eine Klasse Farbe2 vorstellen, die einige der zusätzlichen Möglichkeiten demonstriert:

001 /* Farbe2.java */
002 
003 public enum Farbe2
004 {
005   ROT(255, 0 , 0),
006   GRUEN(0, 255, 0),
007   BLAU(0, 0, 255),
008   GELB(255, 255, 0);
009 
010   private final int r;
011   private final int g;
012   private final int b;
013 
014   Farbe2(int r, int g, int b)
015   {
016     this.r = r;
017     this.g = g;
018     this.b = b;
019   }
020 
021   public String toRGB()
022   {
023     return "(" + r + "," + g + "," + b + ")";
024   }
025 
026   public static void main(String[] args)
027   {
028     for (Farbe2 f : Farbe2.values()) {
029       System.out.println(f + ":" + f.toRGB());
030     }
031   }
032 }
Farbe2.java
Listing 11.9: Erweiterung von Aufzählungstypen

Im Vergleich zum vorigen Beispiel fallen einige Unterschiede auf:

Die Ausgabe des Programms ist:

ROT:(255,0,0)
GRUEN:(0,255,0)
BLAU:(0,0,255)
GELB:(255,255,0)

Wir haben nun Farbkonstanten, die nicht nur ihren Namen kennen, sondern zusätzlich ihren RGB-Wert und diesen auch ausgeben können. Dieses Beispiel deutet nur einige der Möglichkeiten an, die diese Art der Implementierung mit sich bringt. Grundsätzlich ist ein Aufzählungstyp eine gewöhnliche Klasse und kann wie diese ausgebaut werden. So könnten beispielsweise auch nichtkonstante Member verwendet und durch Methodenaufrufe verändert werden. Ob das im Einzelfall sinnvoll ist, muss abgewogen werden.


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de