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