In der Aufzählung gibt es eine Wertemethode, mit der ein Array in der durch die Aufzählung definierten Reihenfolge generiert wird, das zum Durchlaufen verwendet werden kann. Unsere benutzerdefinierten Aufzählungsklassen erben alle von java.lang.Enum und haben in Beispielen die folgenden Funktionen:
Kopieren Sie den Codecode wie folgt:
//: enumerated/EnumClass.java
// Fähigkeiten der Enum-Klasse
import static net.mindview.util.Print.*;
Enum Shrubbery { BODEN, KRABBELN, HÄNGEND }
öffentliche Klasse EnumClass {
public static void main(String[] args) {
for(Shrubbery s : Shrubbery.values()) {
print(s + " ordinal: " + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Shrubbery.CRAWLING);
print(s.getDeclaringClass());
print(s.name());
drucken("----------------------");
}
// Erzeuge einen Enum-Wert aus einem String-Namen:
for(String s : "HANGING CRAWLING GROUND".split(" ")) {
Strauchstrauch = Enum.valueOf(Shrubbery.class, s);
drucken(Strauch);
}
}
} /* Ausgabe:
GROUND-Ordinalzahl: 0
-1 falsch falsch
Klasse Strauchbeere
Joshua Bloch war bei der Entwicklung dieses Kapitels äußerst hilfreich.
BODEN
---------
CRAWLING-Ordinalzahl: 1
wahr wahr
Klasse Strauchbeere
KRABBELN
---------
HÄNGENDE Ordnungszahl: 2
falsch falsch
Klasse Strauchbeere
HÄNGEND
---------
HÄNGEND
KRABBELN
BODEN
*///:~
Wir können auch statische Aufzählungsreferenzen verwenden:
Kopieren Sie den Codecode wie folgt:
//: enumerated/Spiciness.java
Paket aufgezählt;
public enum Spiciness {NOT, MILD, MEDIUM, HOT, FLAMING} ///:~
//: enumerated/Burrito.java
Paket aufgezählt;
import static enumerated.Spiciness.*;
öffentliche Klasse Burrito {
Schärfegrad;
öffentlicher Burrito(Schärfgrad) { this.degree = Degree;}
public String toString() { return „Burrito ist „+ Grad;}“
public static void main(String[] args) {
System.out.println(new Burrito(NOT));
System.out.println(new Burrito(MEDIUM));
System.out.println(new Burrito(HOT));
}
} /* Ausgabe:
Burrito ist NICHT
Burrito ist MITTEL
Burrito ist HEISS
*///:~
Zusätzlich zum Hinzufügen von Methoden zu einer Aufzählung, die nicht vererbt werden können, kann die Aufzählung als allgemeine Klasse behandelt werden, was bedeutet, dass Sie der Aufzählung Methoden hinzufügen und auch die Hauptmethode in der Aufzählung definieren können:
Kopieren Sie den Codecode wie folgt:
//: enumerated/OzWitch.java
// Die Hexen im Land Oz.
import static net.mindview.util.Print.*;
öffentliche Aufzählung OzWitch {
// Instanzen müssen zuerst definiert werden, bevor Methoden:
WEST("Miss Gulch, auch bekannt als die böse Hexe des Westens"),NORTH("Glinda, die gute Hexe des Nordens"),EAST("Böse Hexe des Ostens, Trägerin des Rubins" + "Hausschuhe, zerquetscht von Dorothys Haus"),SOUTH("Infolgedessen gut, aber fehlt");
private String-Beschreibung;
// Konstruktor muss Paket- oder Privatzugriff sein:
private OzWitch(Stringbeschreibung) {
this.description = Beschreibung;
}
public String getDescription() { returnbeschreibung;
public static void main(String[] args) {
for(OzWitch-Hexe: OzWitch.values())
print(witch + ": " + Witch.getDescription());
}
} /* Ausgabe:
WEST: Miss Gulch, auch bekannt als die böse Hexe des Westens
NORDEN: Glinda, die gute Hexe des Nordens
OSTEN: Böse Hexe des Ostens, Trägerin der Rubinpantoffeln, von Dorothys Haus niedergeschlagen
SÜDEN: Schliesslich gut, aber fehlt
*///:~
Kopieren Sie den Codecode wie folgt:
//: enumerated/SpaceShip.java
öffentliche Aufzählung SpaceShip {
Scout, Fracht, Transport, Kreuzer, Schlachtschiff, Mutterschiff;
öffentlicher String toString() {
String-ID = name();
String Lower = id.substring(1).toLowerCase();
return id.charAt(0) + low;
}
public static void main(String[] args) {
for(SpaceShip s :values()) {
System.out.println(s);
}
}
} /* Ausgabe:
Erkunden
Ladung
Transport
Kreuzer
Schlachtschiff
Mutterschiff
*///:~
Aufzählungen in Switch-Anweisungen Eine wichtige Rolle spielen Switch-Anweisungen in Switch-Anweisungen. In Aufzählungen gibt es jedoch eine integrierte Reihenfolge, sodass die Reihenfolge der Instanzen durch eine bestimmte Methode bestimmt werden kann. Daher können Aufzählungen in Switch-Anweisungen verwendet werden:
Kopieren Sie den Codecode wie folgt:
//: enumerated/TrafficLight.java
// Aufzählungen in Switch-Anweisungen.
import static net.mindview.util.Print.*;
// Definiere einen Aufzählungstyp:
Enum-Signal { GRÜN, GELB, ROT, }
öffentliche Klasse TrafficLight {
Signalfarbe = Signal.ROT;
public void change() {
Schalter(Farbe) {
// Beachten Sie, dass Sie Signal.RED nicht sagen müssen
// in der case-Anweisung:
Gehäuse ROT: Farbe = Signal.GRÜN;
brechen;
Fall GRÜN: Farbe = Signal.GELB;
brechen;
Fall GELB: Farbe = Signal.ROT;
brechen;
}
}
öffentlicher String toString() {
return „Die Ampel steht“ + Farbe;
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
for(int i = 0; i < 7; i++) {
print(t);
t.change();
}
}
} /* Ausgabe:
Die Ampel ist ROT
Die Ampel ist GRÜN
Die Ampel ist GELB
Die Ampel ist ROT
Die Ampel ist GRÜN
Die Ampel ist GELB
Die Ampel ist ROT
*///:~
Das Geheimnis von Values() Obwohl wir zuvor die Values-Methode verwendet haben, finden wir die Values-Methode nicht, wenn wir uns Enum ansehen. Gibt es also andere versteckte Methoden? Wir können es mit einem einfachen Reflexionscode überprüfen:
Kopieren Sie den Codecode wie folgt:
//: enumerated/Reflection.java
// Aufzählungen mithilfe von Reflektion analysieren.
import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
enum Entdecken { HIER, DORT }
öffentliche Klasse Reflexion {
public static Set<String>analys(Class<?> enumClass) {
print("----- Analysieren " + enumClass + " -----");
print("Schnittstellen:");
for(Typ t: enumClass.getGenericInterfaces())
print(t);
print("Base: " + enumClass.getSuperclass());
print("Methoden: ");
Set<String>-Methoden = new TreeSet<String>();
for(Methode m: enumClass.getMethods())
methoden.add(m.getName());
print(Methoden);
Rückgabemethoden;
}
public static void main(String[] args) {
Set<String> exploreMethods =analys(Explore.class);
Set<String> enumMethods =analysieren(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(exploreMethods);
// Den Code für die Aufzählung dekompilieren:
OSExecute.command("javap Explore");
}
} /* Ausgabe:
----- Analysekurs Explore -----
Schnittstellen:
Basis: Klasse java.lang.Enum
Methoden:
[compareTo, equal, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, Values, wait]
----- Analysierende Klasse java.lang.Enum -----
Schnittstellen:
java.lang.Comparable<E>
Schnittstelle java.io.Serializable
Basis: Klasse java.lang.Object
Methoden:
[compareTo, equal, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum)? wahr
Explore.removeAll(Enum): [Werte]
Zusammengestellt aus „Reflection.java“
Die letzte Klasse Explore erweitert java.lang.Enum{
öffentliches statisches Finale Entdecken Sie HIER;
öffentliches statisches Finale Entdecken Sie DORT;
öffentliche statische endgültige Explore[]-Werte();
public static Explore valueOf(java.lang.String);
static {};
}
*///:~
Wir können sehen, dass die Wertemethode vom Compiler hinzugefügt wird. Die valueOf-Methode wird vom Compiler beim Erstellen der Aufzählung ebenfalls hinzugefügt. Es gibt jedoch auch eine valueOf-Methode in der Enum-Klasse. Diese Methode verfügt jedoch über zwei Parameter, während die vom Compiler hinzugefügte valueOf-Methode nur einen Parameter hat. Aufzählungen werden vom Compiler als endgültig interpretiert, sodass Aufzählungen nicht vererbt werden können. Da es sich bei der Wertemethode um eine vom Compiler hinzugefügte statische Methode handelt, ist die Wertemethode nicht verfügbar, wenn Sie die Aufzählung in Enum umwandeln. Es gibt jedoch eine getEnumConstants-Methode in der Klasse, obwohl die Wertemethode vorhanden ist nicht verfügbar in Enum , aber Sie können die Enumerationsinstanz trotzdem über das Class-Objekt abrufen:
Kopieren Sie den Codecode wie folgt:
//: enumerated/UpcastEnum.java
// Keine Werte()-Methode, wenn Sie eine Aufzählung hochladen
Enum-Suche { HITHER, YON }
öffentliche Klasse UpcastEnum {
public static void main(String[] args) {
Search[] vals = Search.values();
Enum e = Search.HITHER; // Upcast
// e.values(); // Keine Werte() in Enum
for(Enum en : e.getClass().getEnumConstants())
System.out.println(en);
}
} /* Ausgabe:
HIERHER
YON
*///:~
Implementierung ohne Vererbung Da die von uns definierten Aufzählungstypen alle von java.lang.Enum erben und Java keine Mehrfachvererbung unterstützt, werden Aufzählungen nicht durch Vererbung erstellt, sondern Aufzählungen können durch Erben einer oder mehrerer Schnittstellen erstellt werden:
Kopieren Sie den Codecode wie folgt:
//: enumerated/cartoons/EnumImplementation.java
// Eine Aufzählung kann eine Schnittstelle implementieren
Paket enumerated.cartoons;
import java.util.*;
import net.mindview.util.*;
enum CartoonCharacter implementiert Generator<CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;
private Random rand = new Random(47);
öffentlicher CartoonCharacter next() {
Rückgabewerte()[rand.nextInt(values().length)];
}
}
öffentliche Klasse EnumImplementation {
public static <T> void printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
public static void main(String[] args) {
// Wählen Sie eine beliebige Instanz:
CartoonCharacter cc = CartoonCharacter.BOB;
for(int i = 0; i < 10; i++)
printNext(cc);
}
} /* Ausgabe:
BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, NUTTY, SLAPPY,
*///:~
Zufällige Auswahl In vielen unserer späteren Beispiele werden wir Objekte aus Aufzählungsinstanzen zufällig auswählen. Wir erstellen eine öffentliche Klasse, um dies zu implementieren:
Kopieren Sie den Codecode wie folgt:
//: net/mindview/util/Enums.java
Paket net.mindview.util;
import java.util.*;
Aufzählungen der öffentlichen Klasse {
private static Random rand = new Random(47);
public static <T erweitert Enum<T>> T random(Class<T> ec) {
return random(ec.getEnumConstants());
}
public static <T> T random(T[]-Werte) {
Rückgabewerte[rand.nextInt(values.length)];
}
} ///:~
Kopieren Sie den Codecode wie folgt:
//: enumerated/RandomTest.java
import net.mindview.util.*;
Enum-Aktivität { SITZEN, LIEGEN, STEHEN, HÜPFEN, LAUFEN, AUSWEICHEN, SPRINGEN, FALLEN, FLIEGEN }
öffentliche Klasse RandomTest {
public static void main(String[] args) {
for(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* Ausgabe:
STEHEN, FLIEGEN, LAUFEN, STEHEN, LAUFEN, STEHEN, LIEGEN, AUSWEICHEN, SITZEN, LAUFEN, HÜPFEN, HÜPFEN, HÜPFEN, LAUFEN, STEHEN, LIEGEN, FALLEN, LAUFEN, FLIEGEN, LIEGEN
*///:~
Die Verwendung von Schnittstellen zum Organisieren von Aufzählungen kann nicht vererbt werden, was manchmal zu Unannehmlichkeiten führt, da wir manchmal die Anzahl der Aufzählungen durch Vererbung erweitern möchten und manchmal Aufzählungen gruppieren müssen. Für Letzteres können wir gruppierte Aufzählungen innerhalb der Schnittstelle definieren und dann die Aufzählung durch Erben von dieser Schnittstelle erstellen. Im Folgenden müssen wir verschiedene Lebensmittelkategorien als Aufzählungen erstellen, aber wir müssen jede Kategorie als Typen definieren von Lebensmitteln sind wie folgt:
Kopieren Sie den Codecode wie folgt:
//: enumerated/menu/Food.java
// Unterkategorisierung von Enumerationen innerhalb von Schnittstellen.
Paket enumerated.menu;
öffentliche Schnittstelle Food {enum Appetizer implementiert Food {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implementiert Food {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
Enum Dessert implementiert Essen {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
Aufzählung Kaffee implementiert Lebensmittel {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
Da jede Aufzählung als Implementierung einer Schnittstelle definiert ist, ist jede Aufzählung wie folgt vom Typ Food:
Kopieren Sie den Codecode wie folgt:
//: enumerated/menu/TypeOfFood.java
Paket enumerated.menu;
import static enumerated.menu.Food.*;
öffentliche Klasse TypeOfFood {
public static void main(String[] args) {
Essen Essen = Vorspeise.SALAT;
food = MainCourse.LASAGNE;
Essen = Dessert.GELATO;
Essen = Kaffee.CAPPUCCINO;
}
} ///:~
Schnittstellen können jedoch nicht wie Aufzählungen mit mehreren Typen arbeiten. Wenn Sie also eine Aufzählung von Aufzählungen benötigen, können Sie eine Instanz jedes Aufzählungstyps in einer Aufzählung kapseln:
Kopieren Sie den Codecode wie folgt:
//: enumerated/menu/Course.java
Paket enumerated.menu;
import net.mindview.util.*;
öffentlicher Enum-Kurs {
APPETIZER(Food.Appetizer.class),MAINCOURSE(Food.MainCourse.class),DESSERT(Food.Dessert.class),COFFEE(Food.Coffee.class);
private Food[]-Werte;
Privatkurs (Klasse<? erweitert Essen> Art) {
Werte = kind.getEnumConstants();
}
öffentliches Essen randomSelection() {
return Enums.random(values);
}
} ///:~
Jede Enumeration verwendet das Class-Objekt als entsprechenden Konstruktorparameter. Wir können getEnumConstants aus diesem Parameter verwenden, um die Enumerationsinstanz zu erhalten. Diese Instanz kann in der randomSelection-Methode verwendet werden, um zufällige Mahlzeiten zu generieren.
Kopieren Sie den Codecode wie folgt:
//: enumerated/menu/Meal.java
Paket enumerated.menu;
öffentliche Unterrichtsmahlzeit {
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Kurs course : Course.values()) {
Essen food = course.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Ausgabe:
SPRING_ROLLS
VINDALOO
OBST
DECAF_COFFEE
---
SUPPE
VINDALOO
OBST
TEE
---
SALAT
BURRITO
OBST
TEE
---
SALAT
BURRITO
CREME_KARAMELL
LATTE
---
SUPPE
BURRITO
TIRAMISU
ESPRESSO
---
*///:~
Hier ist eine kompaktere Implementierung:
Kopieren Sie den Codecode wie folgt:
//: enumerated/SecurityCategory.java
// Prägnantere Unterkategorisierung von Aufzählungen.
import net.mindview.util.*;
enum SecurityCategory {
STOCK(Security.Stock.class), BOND(Security.Bond.class);
Security[]-Werte;
SecurityCategory(Class<? erweitert Sicherheit> kind) {
Werte = kind.getEnumConstants();
}
Schnittstellensicherheit {
enum Stock implementiert Sicherheit { SHORT, LONG, MARGIN }
enum Bond implementiert Sicherheit { MUNICIPAL, JUNK }
}
öffentliche Sicherheit randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
SecurityCategory-Kategorie = Enums.random(SecurityCategory.class);
System.out.println(category + ": " +
Kategorie.randomSelection());
}
}
} /* Ausgabe:
BINDUNG: KOMMUNAL
BINDUNG: KOMMUNAL
LAGER: MARGE
LAGER: MARGE
Bindung: Schrott
LAGER: KURZ
LAGER: LANG
LAGER: LANG
BINDUNG: KOMMUNAL
Bindung: Schrott
*///:~
Kopieren Sie den Codecode wie folgt:
//: enumerated/menu/Meal2.java
Paket enumerated.menu;
import net.mindview.util.*;
öffentliche Aufzählung Meal2 {
APPETIZER(Food.Appetizer.class),MAINCOURSE(Food.MainCourse.class),DESSERT(Food.Dessert.class),COFFEE(Food.Coffee.class);
private Food[]-Werte;
private Meal2(Class<? erweitert Food> art) {
Werte = kind.getEnumConstants();
}
öffentliche Schnittstelle Essen {
enum Appetizer implementiert Essen {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implementiert Food {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}
Enum Dessert implementiert Essen {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
Aufzählung Kaffee implementiert Lebensmittel {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
öffentliches Essen randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Meal2 Mahlzeit : Meal2.values()) {
Essen food = food.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Gleiche Ausgabe wie Meal.java *///:~
Verwenden Sie EnumSet anstelle von Flags. EnumSet wurde in Java SE5 hinzugefügt, um Enums und Sets zu kombinieren und ganzzahlbasierte Bit-Flags zu ersetzen. Bit-Flags werden normalerweise verwendet, um den Wechsel einer Art von Information anzuzeigen, aber im Code werden Bits und nicht sinnvolle Konzepte verarbeitet, sodass sie nicht leicht zu verstehen sind. EnumSet ist schneller als Bit-Flags. Es verwendet intern long, um einen Bitvektor darzustellen, und dann können Sie eine konzeptionellere Sprache verwenden, um den Wechsel eines bestimmten Bits darzustellen, ohne sich Gedanken über die Effizienz machen zu müssen. Die Elemente in EnumSet müssen aus derselben Enumeration stammen. Folgendes definiert eine Enumeration der Alarmposition:
Kopieren Sie den Codecode wie folgt:
//: enumerated/AlarmPoints.java
Paket aufgezählt;
öffentliche Aufzählung AlarmPoints {STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY, KITCHEN} ///:~
Verwenden Sie dann die EnumSet-Klasse, um den Status des Alarms zu verfolgen:
Kopieren Sie den Codecode wie folgt:
//: enumerated/EnumSets.java
// Operationen auf EnumSets
Paket aufgezählt;
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
öffentliche Klasse EnumSets {
public static void main(String[] args) {
EnumSet<AlarmPoints> point = EnumSet.noneOf(AlarmPoints.class); // Leere Menge
point.add(BADEZIMMER);
print(points);
point.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
point = EnumSet.allOf(AlarmPoints.class);
point.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
print(points);
point.removeAll(EnumSet.range(OFFICE1, OFFICE4));
print(points);
Punkte = EnumSet.complementOf(points);
print(points);
}
} /* Ausgabe:
[BADEZIMMER]
[TREPPE1, TREPPE2, BADEZIMMER, KÜCHE]
[LOBBY, BÜRO1, BÜRO2, BÜRO3, BÜRO4, BADEZIMMER, UTILITY]
[LOBBY, BADEZIMMER, UTILITY]
[TREPPE1, TREPPE2, BÜRO1, BÜRO2, BÜRO3, BÜRO4, KÜCHE]
*///:~
EnumSet basiert auf einem langen Typ und hat 64 Bit. Was passiert also, wenn unser Aufzählungstyp diese Zahl überschreitet?
Kopieren Sie den Codecode wie folgt:
//: enumerated/BigEnumSet.java
import java.util.*;
öffentliche Klasse BigEnumSet {
Aufzählung Big { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23 , A24, A25, A26, A27, A28, A29, A30, A31, A32,
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65,
A66, A67, A68, A69, A70, A71, A72, A73, A74, A75}
public static void main(String[] args) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
} /* Ausgabe:
[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24 , A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75]
*///:~
Wir können sehen, dass das Programm normal läuft, daher ist es sehr wahrscheinlich, dass intern ein langer Typ hinzugefügt wurde, um den Aufzählungstyp mit EnumMap zu unterstützen.
EnumMap ist ein besonderer Map-Typ. Der Wert seines Schlüssels kann nur vom Typ in derselben Aufzählung sein. Aus diesem Grund kann EnumMap intern über ein Array implementiert werden, was sehr effizient ist.
Kopieren Sie den Codecode wie folgt:
//: enumerated/EnumMaps.java
// Grundlagen von EnumMaps.
Paket aufgezählt;
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
Schnittstelle Befehl { void action();
öffentliche Klasse EnumMaps {
public static void main(String[] args) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(KITCHEN, neuer Befehl() {
public void action() { print("Küchenfeuer!" }
});
em.put(BATHROOM, new Command() {
public void action() { print("Badezimmeralarm!" }
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // Wenn für einen bestimmten Schlüssel kein Wert vorhanden ist:
em.get(UTILITY).action();
} Catch(Ausnahme e) {
print(e);
}
}
} /* Ausgabe:
BADEZIMMER: Badezimmeralarm!
KÜCHE: Küchenfeuer!
java.lang.NullPointerException
*///:~
Spezifische konstante Methoden Java-Aufzählungen haben eine sehr interessante Funktion: Für jede Aufzählungsinstanz können unterschiedliche Verhaltensweisen definiert werden. Um dies zu erreichen, definieren wir eine oder mehrere abstrakte Methoden als Teil der Aufzählung und definieren dann für jede unterschiedliche Verhaltensweisen Eine Aufzählungsinstanz-Definitionsmethode:
Kopieren Sie den Codecode wie folgt:
//: enumerated/ConstantSpecificMethod.java
import java.util.*;
java.text.* importieren;
öffentliche Aufzählung ConstantSpecificMethod {
DATE_TIME {String getInfo() {return DateFormat.getDateInstance().format(new Date());}},
CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},
VERSION {String getInfo() {return System.getProperty("java.version");}};
abstrakter String getInfo();
public static void main(String[] args) {
for(ConstantSpecificMethod csm: Werte())
System.out.println(csm.getInfo());
}
} /* (Ausführen, um die Ausgabe anzuzeigen) *///:~
Der obige Code scheint festzuhalten, dass jedes Aufzählungselement ein anderes Element ist und alle Elemente von der Basisklasse „ConstantSpecificMethod“ erben, aber wir können es auf diese Weise nicht wirklich verstehen, da wir die Aufzählungselemente nicht als Typen behandeln können:
Kopieren Sie den Codecode wie folgt:
//: enumerated/NotClasses.java
// {Exec: javap -c LikeClasses}
import static net.mindview.util.Print.*;
enum LikeClasses {WINKEN { void behavior() { print("Behavior1" } },BLINKEN { void behavior() { print("Behavior2" } },NOD { void behavior() { print("Behavior3") ; } };
abstraktes leeres Verhalten();
}
öffentliche Klasse NotClasses {
// void f1(LikeClasses.WINKEN-Instanz) {} // Nein
} /* Ausgabe:
Zusammengestellt aus „NotClasses.java“
abstrakte Klasse LikeClasses erweitert java.lang.Enum{
öffentliches statisches Finale LikeClasses WINKEN;
public static final LikeClasses BLINKEN;
öffentliche statische finale LikeClasses NOD;
...
*///:~
Betrachten Sie ein weiteres Beispiel: Kunden wählen verschiedene Dienste auf der Grundlage unterschiedlicher Menüs aus. Sie können das Menü wie folgt mit den Diensten verknüpfen und EnumSet verwenden.
Kopieren Sie den Codecode wie folgt:
//: enumerated/CarWash.java
import java.util.*;
import static net.mindview.util.Print.*;
öffentliche Klasse CarWash {
public enum Cycle {UNDERBODY {void action() { print("Sprühen des Unterbodens" }},
WHEELWASH {void action() { print("Waschen der Räder" }},
PREWASH {void action() { print("Den Schmutz lösen" }},
BASIC {void action() { print("The basic washing" }},
HOTWAX {void action() { print("Heißwachs auftragen" }},
RINSE {void action() { print("Spülen" }},
Föhnen {void action() { print("Föhnen" }};
abstrakte leere Aktion();
}
EnumSet<Cycle> Cycles = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Cyclecycle) {cycles.add(cycle);
public void washingCar() {
for(Zyklus c: Zyklen)
c.action();
}
public String toString() { returncycles.toString(}
public static void main(String[] args) {
CarWash washing = new CarWash();
drucken (waschen);
washing.washCar();
// Reihenfolge der Addition ist unwichtig:
washing.add(Cycle.BLOWDRY);
washing.add(Cycle.BLOWDRY); // Duplikate ignoriert
washing.add(Cycle.RINSE);
washing.add(Cycle.HOTWAX);
drucken (waschen);
washing.washCar();
}
} /* Ausgabe:
[BASIC, SPÜLEN]
Die Grundwäsche
Spülung
[BASIC, HEISSWACHS, SPÜLEN, Föhnen]
Die Grundwäsche
Heißwachs auftragen
Spülung
Trocken föhnen
*///:~
Wir können auch die standardmäßigen spezifischen Konstantenmethoden überschreiben, anstatt geerbte abstrakte Methoden zu verwenden, wie folgt:
Kopieren Sie den Codecode wie folgt:
//: enumerated/OverrideConstantSpecific.java
import static net.mindview.util.Print.*;
öffentliche Aufzählung OverrideConstantSpecific {
NUT, BOLT,WASHER {void f() { print("Overridden method" }};
void f() { print("Standardverhalten" }
public static void main(String[] args) {
for(OverrideConstantSpecific ocs : Values()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* Ausgabe:
NUT: Standardverhalten
BOLT: Standardverhalten
WASHER: Überschriebene Methode
*///:~
Manchmal möchten wir bestimmte Anfragen in der Kette weitergeben. Das Wissen, dass ein Objekt in der Kette die Anfrage verarbeiten kann, kann durch die Verwendung bestimmter konstanter Methoden leicht erreicht werden.
Kopieren Sie den Codecode wie folgt:
//: enumerated/PostOffice.java
// Modellierung eines Postamtes.
Aufzählungstypen 743
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
Klasse Mail {
// Die NEINs verringern die Wahrscheinlichkeit einer Zufallsauswahl:
Aufzählung GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}
Enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
Enum-Lesbarkeit {ILLEGIBLE,YES1,YES2,YES3,YES4}
Enum-Adresse {FALSCH,OK1,OK2,OK3,OK4,OK5,OK6}
enum ReturnAddress {MISSING,OK1,OK2,OK3,OK4,OK5}
AllgemeinLieferung allgemeinLieferung;
Scanbarkeit; Scanbarkeit;
Lesbarkeit; Lesbarkeit;
Adressadresse;
ReturnAddress returnAddress;
statischer langer Zähler = 0;
lange ID = Zähler++;
public String toString() { return „Mail“ + id;
public String details() {
return toString() + ", General Delivery: " + generalDelivery + ", Address Scanability: " + scannability + ", Address Readability: " + readability +
", Adressadresse: " + Adresse + ", Rücksendeadresse: " + returnAddress;
}
//Test-Mail generieren:
öffentliche statische Mail randomMail() {
Mail m = new Mail();
m.generalDelivery= Enums.random(GeneralDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.address = Enums.random(Address.class);
m.returnAddress = Enums.random(ReturnAddress.class);
Rückkehr m;
}
öffentlicher statischer Iterable<Mail>-Generator(final int count) {
return new Iterable<Mail>() {
int n = count;
public Iterator<Mail> iterator() {
return new Iterator<Mail>() {
public boolean hasNext() { return n-- > 0 }
public Mail next() { return randomMail( }
public void remove() { // Nicht implementiert
throw new UnsupportedOperationException();
}
};
}
};
}
}
öffentliche Klasse PostOffice {
Enumeration MailHandler {
GENERAL_DELIVERY {
boolescher Handle(Mail m) {
switch(m.generalDelivery) {
Fall JA:
print("Allgemeine Zustellung verwenden für " + m);
return true;
Standard: false zurückgeben;
}
}
},
MACHINE_SCAN {
boolescher Handle(Mail m) {
switch(m.scannability) {
case UNSCANNABLE: false zurückgeben;
Standard:
switch(m.address) {
Fall FALSCH: Rückgabe falsch;
Standard:
print("Automatische Zustellung von "+ m + "");
return true;
}
}
}
},
VISUAL_INSPECTION {
boolescher Handle(Mail m) {
switch(m.readability) {
case ILLEGIBLE: return false;
Standard:
switch(m.address) {
Fall FALSCH: Rückgabe falsch;
Standard:
print("Lieferung " + m + " normal");
return true;
}
}
}
},
RETURN_TO_SENDER {
boolescher Handle(Mail m) {
switch(m.returnAddress) {
case MISSING: return false;
Standard:
print("Rückgabe von " + m + " an den Absender");
return true;
}
}
};
abstraktes boolesches Handle(Mail m);
}
static void handle(Mail m) {
for(MailHandler-Handler: MailHandler.values())
if(handler.handle(m))
zurückkehren;
print(m + " ist ein toter Buchstabe");
}
public static void main(String[] args) {
for(Mail mail : Mail.generator(10)) {
print(mail.details());
handle(mail);
drucken("*****");
}
}
} /* Ausgabe:
Post 0, Allgemeine Zustellung: NEIN2, Scanfähigkeit der Adresse: NICHT SCANBAR, Lesbarkeit der Adresse: JA3, Adressadresse: OK1, Rücksendeadresse: OK1
Post 0 wird normal zugestellt
*****
Post 1, Allgemeine Zustellung: NEIN5, Scanfähigkeit der Adresse: JA3, Lesbarkeit der Adresse: UNLESBAR, Adressadresse: OK5, Rücksendeadresse: OK1
Automatische Zustellung von Post 1
*****
Post 2, Allgemeine Zustellung: JA, Scanfähigkeit der Adresse: JA3, Lesbarkeit der Adresse: JA1, Adressadresse: OK1, Rücksendeadresse: OK5
Verwendung der allgemeinen Zustellung für Post 2
*****
Post 3, Allgemeine Zustellung: NEIN4, Scanfähigkeit der Adresse: JA3, Lesbarkeit der Adresse: JA1, Adressadresse: FALSCH, Rücksendeadresse: OK4
Rücksendung von Mail 3 an den Absender
*****
Post 4, Allgemeine Zustellung: NEIN4, Scanfähigkeit der Adresse: NICHT SCANBAR, Lesbarkeit der Adresse: JA1, Adressadresse: FALSCH, Rücksendeadresse: OK2
Rücksendung von Mail 4 an den Absender
*****
Post 5, Allgemeine Zustellung: NEIN3, Scanbarkeit der Adresse: JA1, Lesbarkeit der Adresse: UNLESBAR, Adressadresse: OK4, Rücksendeadresse: OK2
Automatische Zustellung von Mail 5
*****
Post 6, Allgemeine Zustellung: JA, Scanfähigkeit der Adresse: JA4, Lesbarkeit der Adresse: UNLESBAR, Adressadresse: OK4, Rücksendeadresse: OK4
Verwendung der allgemeinen Zustellung für Post 6
*****
Post 7, Allgemeine Zustellung: JA, Scanfähigkeit der Adresse: JA3, Lesbarkeit der Adresse: JA4, Adressadresse: OK2, Rücksendeadresse: FEHLT
Verwendung der allgemeinen Zustellung für Mail 7
*****
Post 8, Allgemeine Zustellung: NEIN3, Scanfähigkeit der Adresse: JA1, Lesbarkeit der Adresse: JA3, Adressadresse: FALSCH, Rücksendeadresse: FEHLT
Mail 8 ist ein toter Brief
*****
Post 9, Allgemeine Zustellung: NEIN1, Scanfähigkeit der Adresse: NICHT SCANBAR, Lesbarkeit der Adresse: JA2, Adressadresse: OK1, Rücksendeadresse: OK4
Post 9 wird normal zugestellt
*****
*///:~
Der Aufzählungstyp ist auch ein idealer Typ zum Erstellen einer Zustandsmaschine. Eine Zustandsmaschine kann je nach Eingabe zwischen einer begrenzten Anzahl von Zuständen wechseln und die Arbeit dann beenden, nachdem ein bestimmter Zustand erfüllt ist Die entsprechende Ausgabe ist ein Beispiel für eine typische Zustandsmaschine, bei der wir verschiedene Eingaben innerhalb einer Aufzählung definieren:
Kopieren Sie den Codecode wie folgt:
//: enumerated/Input.java
Paket aufgezählt;
import java.util.*;
öffentliche Enum-Eingabe {
NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100),ZAHNPASTA(200), CHIPS(75), SODA(100), SOAP(50),ABORT_TRANSACTION {
public int amount() { // Nicht zulassen
throw new RuntimeException("ABORT.amount()");
}
},
STOP { // Dies muss die letzte Instanz sein.
public int amount() { // Nicht zulassen
throw new RuntimeException("SHUT_DOWN.amount()");
}
};
int value; // In Cent
Input(int value) { this.value = value;
Eingabe() {}
int amount() { return value }; // In Cent
static Random rand = new Random(47);
öffentliche statische Eingabe randomSelection() {
// STOP nicht einschließen:
Rückgabewerte()[rand.nextInt(values().length - 1)];
}
} ///:~
VendingMachine wird verwendet, um auf die Eingabe zu reagieren. Zuerst wird die Eingabe durch Kategorieaufzählung klassifiziert und dann wird die switch-Anweisung verwendet:
Kopieren Sie den Codecode wie folgt:
//: enumerated/VendingMachine.java
// {Args: VendingMachineInput.txt}
Paket aufgezählt;
import java.util.*;
import net.mindview.util.*;
import static enumerated.Input.*;
import static net.mindview.util.Print.*;
Aufzählung Kategorie {
MONEY(NICKEL, DIME, QUARTER, DOLLAR),ITEM_SELECTION(ZAHNPASTA, CHIPS, SODA, SEIFE),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
private Input[]-Werte;
Kategorie(Eingabe... Typen) { Werte = Typen }
private static EnumMap<Input,Category> classifications = new EnumMap<Input,Category>(Input.class);
statisch {
for(Kategorie c: Category.class.getEnumConstants())
for(Eingabetyp: c.values)
Kategorien.put(Typ, c);
}
öffentliche statische Kategorie kategorisieren(Eingabeeingabe) {
Rückkehrkategorien.get(input);
}
}
öffentliche Klasse VendingMachine {
privater statischer Zustand state = State.RESTING;
privater statischer int-Betrag = 0;
private statische Eingabeauswahl = null;
enum StateDuration {TRANSIENT} //Tagging enum
Enum-Status {
RUHE {
void next(Input input) {
switch(Category.categorize(input)) {
Fall GELD:
Menge += input.amount();
state = ADDING_MONEY;
brechen;
Fall SHUT_DOWN:
state = TERMINAL;
Standard:
}
}
},
ADDING_MONEY {
void next(Input input) {
switch(Category.categorize(input)) {
Fall GELD:
Menge += input.amount();
brechen;
Fall ITEM_SELECTION:
Auswahl = Eingabe;
if(amount <selection.amount())
print("Nicht genügend Geld für " + Auswahl);
sonst state = DISPENSING;
brechen;
Fall QUIT_TRANSACTION:
state = GIVING_CHANGE;
brechen;
Fall SHUT_DOWN:
state = TERMINAL;
Standard:
}
}
},
DISPENSING(StateDuration.TRANSIENT) {
void next() {
print("hier ist Ihr " + Auswahl);
Betrag -= Auswahl.Betrag();
state = GIVING_CHANGE;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
void next() {
if(Betrag > 0) {
print("Ihr Wechselgeld: " + Betrag);
Betrag = 0;
}
state = RUHE;
}
},
TERMINAL { void output() { print("Angehalten" } };
privater boolescher Wert isTransient = false;
Zustand() {}
State(StateDuration trans) { isTransient = true;
void next(Input input) {
throw new RuntimeException("Nur Aufruf " + "next(Input input) für nicht-transiente Zustände");
}
void next() {
throw new RuntimeException("Next() nur für " + "StateDuration.TRANSIENT-Zustände aufrufen");
}
void Output() { print(amount);
}
static void run(Generator<Input> gen) {
while(state != State.TERMINAL) {
state.next(gen.next());
while(state.isTransient)
state.next();
state.output();
}
}
public static void main(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
if(arg. Länge == 1)
gen = new FileInputGenerator(args[0]);
run(gen);
}
}
// Für eine grundlegende Überprüfung der geistigen Gesundheit:
Klasse RandomInputGenerator implementiert Generator<Input> {
public Input next() { return Input.randomSelection(}
}
// Eingaben aus einer Datei mit durch „;“ getrennten Zeichenfolgen erstellen:
Klasse FileInputGenerator implementiert Generator<Input> {
private Iterator<String> input;
public FileInputGenerator(String fileName) {
input = new TextFile(fileName, ";").iterator();
}
öffentliche Eingabe next() {
if(!input.hasNext())
null zurückgeben;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* Ausgabe:
Hier sind deine CHIPS
Hier ist deine ZAHNPASTA
Ihr Wechselgeld: 35
Zu wenig Geld für SODA
Zu wenig Geld für SODA
Ihr Wechselgeld: 75
Angehalten
*///:~
Hier sind die Testdaten, die zum Generieren der obigen Ausgabe verwendet wurden:
Kopieren Sie den Codecode wie folgt:
QUARTAL; QUARTAL;
DOLLAR; ZAHNPASTA;
QUARTER; ABORT_TRANSACTION;
QUARTAL; SODA;
QUARTAL; NICKEL;
ABORT_TRANSACTION;
STOPPEN;
///:~
Mehrfaches Entpacken Bei Interaktionen zwischen mehreren Typen wird der Code wahrscheinlich unübersichtlich, z. B. Number.plush(Number), Number.mutiply(Number) usw. Number ist nur eine Basisklasse der Familie, also wenn Sie anrufen Bei a.plus(b) kennen Sie weder den Typ von a noch den Typ von b. Wie kann also sichergestellt werden, dass die Interaktion zwischen ihnen korrekt ist? Java kann nur ein einzelnes Entpacken durchführen, das heißt, wenn eine oder mehrere Operationen mehrerer unbekannter Typen ausgeführt werden, kann Java nur einen dynamischen Bindungsmechanismus für einen der Typen ausführen, was das oben besprochene Problem nicht lösen kann um den dynamischen Bindungscode manuell zu schreiben.
Die Lösung besteht darin, Multibinding zu verwenden. Polymorphismus kann nur beim Aufrufen einer Methode auftreten. Wenn Sie also mehrere Entpackvorgänge benötigen, müssen Sie mehrere Methoden aufrufen. Beim mehrfachen Entpacken benötigen Sie eine virtuelle Methode, die die Methode jedes Typs zum Entpacken aufruft. Das folgende Beispiel ist ein Stein-Schere-Papier-Beispiel:
Kopieren Sie den Codecode wie folgt:
//: enumerated/Outcome.java
Paket aufgezählt;
öffentliches Enum Ergebnis { GEWINNEN, VERLIEREN, ZEICHNEN } ///:~
//: enumerated/RoShamBo1.java
// Demonstration des Mehrfachversands.
Paket aufgezählt;
import java.util.*;
import static enumerated.Outcome.*;
Schnittstellenelement {
Ergebnis konkurrieren(Item it);
Ergebnisbewertung (Aufsatz p);
Ergebnisbewertung (Schere);
Ergebnisbewertung(Rock r);
}
Klasse Papiergeräte Artikel {
öffentliches Ergebnis konkurrieren(Item it) { return it.eval(this }
public Outcome eval(Paper p) { return DRAW }
public Outcome eval(Scissors) { return WIN;
public Outcome eval(Rock r) { return LOSE }
public String toString() { return "Paper" }
}
Klasse Scissors implementiert Item {
öffentliches Ergebnis konkurrieren(Item it) { return it.eval(this }
public Outcome eval(Paper p) { return LOSE }
public Outcome eval(Scissors) { return DRAW }
public Outcome eval(Rock r) { return WIN;
public String toString() { return "Scissors" }
}
Klasse Rock implementiert Item {
öffentliches Ergebnis konkurrieren(Item it) { return it.eval(this }
public Outcome eval(Paper p) { return WIN;
public Outcome eval(Scissors s) { return LOSE }
public Outcome eval(Rock r) { return DRAW }
public String toString() { return "Rock" }
}
öffentliche Klasse Roshambo1 {
statische endgültige int Größe = 20;
private statische zufällige Rand = neuer zufälliger (47);
public static item newItem () {
Switch (Rand.Nextint (3)) {
Standard:
Fall 0: Neue Schere zurückgeben ();
Fall 1: Neues Papier zurückgeben ();
Fall 2: Return New Rock ();
}
}
public static void Match (Punkt A, Punkt B) {
System.out.println (a + "vs." + b + ":" + a.compete (b));
}
public static void main(String[] args) {
für (int i = 0; i <size; i ++)
Match (newItem (), newItem ());
}
} /* Ausgabe:
Rock vs. Rock: Zeichnen
Papier vs. Rock: Gewinnen Sie gewinnen
Papier vs. Rock: Gewinnen Sie gewinnen
Papier vs. Rock: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
Schere vs. Schere: Zeichnen
Schere vs. Papier: Gewinnen Sie gewinnen
Rock vs. Paper: Verlieren Sie
Papier vs. Papier: Zeichnen
Rock vs. Paper: Verlieren Sie
Papier vs. Schere: verlieren
Papier vs. Schere: verlieren
Rock vs. Scissors: Gewinn
Rock vs. Paper: Verlieren Sie
Papier vs. Rock: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
Papier vs. Schere: verlieren
Papier vs. Schere: verlieren
Papier vs. Schere: verlieren
Papier vs. Schere: verlieren
*///: ~
Wir haben viele Methoden verwendet, um mehrere Auspacken zu erreichen, aber was wir erhalten haben, war eine gute Codestruktur. Das größte Problem bei der Verwendung einer Aufzählungslösung zur Implementierung des obigen Code ist, dass die Aufzählungsinstanz kein Typ ist, sodass die Aufzählungsinstanz nicht als Parametertyp verwendet werden kann. Wir können jedoch noch andere Möglichkeiten haben, um dieses Hindernis umzugehen.
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo2.java
// Einen Auflauf auf einen anderen wechseln.
Paket aufgezählt;
statische Aufzählung importieren.outcome.*;
public enum roshambo2 implementiert Wettbewerber <Roshambo2> {
Papier (ziehen, verlieren, gewinnen), Schere (gewinnen, zeichnen, verlieren), Rock (verlieren, gewinnen, zeichnen);
Private Outcome Vpaper, Vscissors, Vrock;
Roshambo2 (Outcome Paper, Outcome Scissors, Outcome Rock) {
this.vpaper = Paper;
this.vscissors = scissors;
this.vrock = rock;
}
Öffentliches Ergebnis konkurrieren (Roshambo2 it) {
Switch (it) {
Standard:
Fallpapier: Return Vpaper;
Fallschere: return vscissors;
Case Rock: Return Vrock;
}
}
public static void main(String[] args) {
Roshambo.play (Roshambo2.Class, 20);
}
} /* Ausgabe:
Rock vs. Rock: Zeichnen
Schere vs. Rock: Verlieren Sie
Schere vs. Rock: Verlieren Sie
Aufzählte Typen 753
Schere vs. Rock: Verlieren Sie
Papier vs. Schere: verlieren
Papier vs. Papier: Zeichnen
Papier vs. Schere: verlieren
Rock vs. Scissors: Gewinn
Schere vs. Schere: Zeichnen
Rock vs. Scissors: Gewinn
Schere vs. Papier: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
Rock vs. Paper: Verlieren Sie
Rock vs. Scissors: Gewinn
Schere vs. Rock: Verlieren Sie
Papier vs. Schere: verlieren
Schere vs. Papier: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
Schere vs. Papier: Gewinnen Sie gewinnen
*///: ~
Kopieren Sie den Codecode wie folgt:
//: Aufzählter/Wettbewerber.java
// Einen Auflauf auf einen anderen wechseln.
Paket aufgezählt;
Der Wettbewerber der öffentlichen Schnittstelle <T erweitert Wettbewerber <T >> {
Ergebnis konkurrieren (T -Wettbewerber);
} ///: ~
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo.java
// Häufige Werkzeuge für Roshambo -Beispiele.
Paket aufgezählt;
net.mindView.util.*;
öffentliche Klasse Roshambo {
public static <t erweitert Konkurrent <T >> void Match (t a, t b) {
System.out.println (a + "vs." + b + ":" + a.compete (b));
}
public static <t erweitert Enum <T> & Wettbewerber <T >> void Play (Klasse <T> rsbClass, int Größe) {
für (int i = 0; i <size; i ++)
Match (enums.random (rsbClass), enums.random (rsbClass));
}
} ///: ~
Da die Formulierung statischer Methoden unterschiedliche Methoden für jeden Aufzählungstyp bereitstellen kann, scheint es eine gute Lösung zu sein, um mehrfach Auspacken zu erreichen, aber wir stehen dennoch dem Problem, dass die Aufzählungsinstanz kein Typ ist. Wir können also nur eine Switch -Anweisung hinzufügen :
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo3.java
// mit konstantspezifischen Methoden.
Paket aufgezählt;
statische Aufzählung importieren.outcome.*;
public enum roshambo3 implementiert Wettbewerber <Roshambo3> {
PAPIER {
Öffentliches Ergebnis konkurrieren (Roshambo3 It) {
Switch (it) {
Standard: //, um den Compiler zu platzieren
Fallpapier: Rückzug;
Fallschere: Rückkehr verlieren;
Case Rock: Return Win;
}
}
},
SCHERE {
Öffentliches Ergebnis konkurrieren (Roshambo3 It) {
Switch (it) {
Standard:
Fallpapier: Return Win;
Fallschere: Return Draw;
Case Rock: Rückkehr verlieren;
}
}
},
FELSEN {
Öffentliches Ergebnis konkurrieren (Roshambo3 It) {
Switch (it) {
Standard:
Fallpapier: Rückkehr verlieren;
Fallschere: Return Win;
Case Rock: Return Draw;
}
}
};
öffentliches abstraktes Ergebnis konkurrieren (Roshambo3 IT);
public static void main(String[] args) {
Roshambo.play (Roshambo3.Class, 20);
}
}/ * Gleiche Ausgabe wie Roshambo2.java * ///: ~
Der folgende Code ist eine prägnantere Implementierungsmethode:
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo4.java
Paket aufgezählt;
public enum roshambo4 implementiert Wettbewerber <Roshambo4> {
FELSEN {
Öffentliches Ergebnis konkurrieren (Roshambo4 -Gegner) {
Rückkehr konkurrieren (Schere, Gegner);
}
},
SCHERE {
Öffentliches Ergebnis konkurrieren (Roshambo4 -Gegner) {
Rückkehr konkurrieren (Papier, Gegner);
}
},
PAPIER {
Öffentliches Ergebnis konkurrieren (Roshambo4 -Gegner) {
Rückkehr konkurrieren (Rock, Gegner);
}
};
Ergebnis konkurrieren (Roshambo4 -Verlierer, Roshambo4 -Gegner) {
return ((opponent == this)? outcome
}
public static void main(String[] args) {
Roshambo.play (Roshambo4.Class, 20);
}
}/ * Gleiche Ausgabe wie Roshambo2.java * ///: ~
Die ENUMMAP -Klasse scheint eine gute Möglichkeit zu sein, mehrere Entpackungen tatsächlich zu implementieren:
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo5.java
// Mehrfaches Versenden mit einem Enummap von Enummaps.
Paket aufgezählt;
import java.util.*;
statische Aufzählung importieren.outcome.*;
Enum roshambo5 implementiert den Wettbewerber <Roshambo5> {
Papier, Schere, Stein;
static echap <roshambo5, enummap <roshambo5, Ergebnis >> table = neumnump <roshambo5, enummap <roshambo5, Ergebnis >> (Roshambo5.CLASS);
statisch {
für (Roshambo5 It: Roshambo5.Values ())
table.put (it, neuer Enummap <roshambo5, Ergebnis> (Roshambo5.class));
initrow (Papier, Zeichnen, verlieren, gewinnen);
initrow (schere, gewinnen, zeichnen, verlieren);
initrow (Rock, verlieren, gewinnen, zeichnen);
}
static void Initrow (Roshambo5 IT, Outcome Vpaper, Outcome VScissors, Outcome Vrock) {
ENUMMAP <ROSHAMBO5, OUCTECE> row = roshambo5.table.get (It);
Row.put (Roshambo5.paper, Vpaper);
row.put (Roshambo5.Scissors, VScissors);
Row.put (Roshambo5.Rock, Vrock);
}
Öffentliches Ergebnis konkurrieren (Roshambo5 It) {
return table.get (this) .get (it);
}
public static void main(String[] args) {
Roshambo.play (Roshambo5.Class, 20);
}
}/ * Gleiche Ausgabe wie Roshambo2.java * ///: ~
Wir können auch die Funktion von Aufzählungsinstanzen mit festen Werten verwenden, um Daten für die einfachste Implementierungsmethode zu verwenden.
Kopieren Sie den Codecode wie folgt:
//: aufgezählt/roshambo6.java
// Aufzüge mit "Tabellen" anstelle von mehreren Versand.
Paket aufgezählt;
statische Aufzählung importieren.outcome.*;
Enum roshambo6 implementiert den Wettbewerb <Roshambo6> {
Papier, Schere, Stein;
privates statisches Ergebnis [] [] table = {
{Zeichnen, verlieren, gewinnen}, // Papier
{Gewinnen, zeichnen, verlieren}, // Schere
{Verlieren, gewinnen, zeichnen}, // Rock
};
Öffentliches Ergebnis konkurrieren (Roshambo6 andere) {
Rückgabe Tabelle [this.ordinal ()] [other.ordinal ()];
}
public static void main(String[] args) {
Roshambo.play (Roshambo6.Class, 20);
}
} ///: ~