열거형에는 열거형에 정의된 순서대로 배열을 생성하는 데 사용되는 값 메서드가 있으며, 이를 순회하는 데 사용할 수 있습니다. 우리의 사용자 정의 열거형 클래스는 모두 java.lang.Enum에서 상속되며 예제에는 다음과 같은 기능이 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/EnumClass.java
// Enum 클래스의 기능
import static net.mindview.util.Print.*;
enum 관목 { 땅바닥, 기어 다니기, 매달기 }
공개 클래스 EnumClass {
공개 정적 무효 메인(String[] args) {
for(Shrubbery s : Shrubbery.values()) {
print(s + " 서수: " + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Shrubbery.CRAWLING);
print(s.getDeclaringClass());
print(s.name());
인쇄("----------------------");
}
// 문자열 이름에서 열거형 값을 생성합니다.
for(String s : "HANGING CRAWLING GROUND".split(" ")) {
관목 관목 = Enum.valueOf(Shrubbery.class, s);
인쇄(관목);
}
}
} /* 출력:
GROUND 서수: 0
-1 거짓 거짓
클래스 관목
Joshua Bloch는 이 장을 개발하는 데 큰 도움을 주었습니다.
지면
----------
크롤링 서수: 1
사실 사실
클래스 관목
크롤링
----------
행잉 서수: 2
거짓 거짓
클래스 관목
교수형
----------
교수형
크롤링
지면
*///:~
정적 열거 참조를 사용할 수도 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/Spiciness.java
패키지가 열거되었습니다.
공개 열거형 매운맛 {NOT, MILD, MEDIUM, HOT, FLAMING} ///:~
//: 열거됨/Burrito.java
패키지가 열거되었습니다.
import static enumerated.Spiciness.*;
공개 클래스 부리토 {
매운 정도;
public Burrito(매운 정도) { this.degree = 학위;}
public String toString() { return "부리토는 "+ 정도;}
공개 정적 무효 메인(String[] args) {
System.out.println(새 부리또(NOT));
System.out.println(새 부리또(MEDIUM));
System.out.println(새 부리토(HOT));
}
} /* 출력:
부리또는 아니다
부리또는 중간 정도
부리또가 핫해요
*///:~
상속될 수 없는 열거형에 메서드를 추가하는 것 외에도 열거형은 일반 클래스로 처리될 수 있습니다. 즉, 열거형에 메서드를 추가할 수 있고 열거형에 기본 메서드를 정의할 수도 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/OzWitch.java
// 오즈 나라의 마녀들.
import static net.mindview.util.Print.*;
공개 열거형 OzWitch {
// 메소드보다 먼저 인스턴스를 정의해야 합니다.
WEST("미스 걸치, 일명 서쪽의 사악한 마녀"),NORTH("선한 북쪽 마녀 글린다"),EAST("동쪽의 사악한 마녀, 루비를 입은 자 " + "슬리퍼, 짓눌린 도로시의 집"),SOUTH("추론적으로는 좋지만 누락되었습니다.");
개인 문자열 설명;
// 생성자는 패키지 또는 비공개 액세스여야 합니다.
private OzWitch(문자열 설명) {
this.description = 설명;
}
공개 문자열 getDescription() { 설명 반환 }
공개 정적 무효 메인(String[] args) {
for(오즈마녀 마녀 : OzWitch.values())
print(마녀 + ": " + 마녀.getDescription());
}
} /* 출력:
WEST: 서쪽의 사악한 마녀라고도 알려진 Miss Gulch
북쪽: 북쪽의 착한 마녀 글린다
EAST: 루비 슬리퍼를 신은 동쪽의 사악한 마녀, 도로시의 집에 짓눌려 죽다
남쪽: 추론으로는 양호하지만 누락됨
*///:~
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/SpaceShip.java
공개 열거형 SpaceShip {
정찰, 화물, 수송, 순양함, 전함, 모선;
공개 문자열 toString() {
문자열 ID = 이름();
문자열 lower = id.substring(1).toLowerCase();
return id.charAt(0) + lower;
}
공개 정적 무효 메인(String[] args) {
for(SpaceShip s : 값()) {
System.out.println(s);
}
}
} /* 출력:
스카우트
뱃짐
수송
순양함
전함
모선
*///:~
스위치 문에서의 열거 열거의 중요한 역할은 스위치 문에 있습니다. 일반적으로 스위치 문은 정수 값에만 작동하지만 열거에는 내장된 정수 순서가 있으므로 인스턴스의 순서는 어떤 방법으로 결정될 수 있습니다. 따라서 스위치 문에서 열거형을 사용할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/TrafficLight.java
// 스위치 문의 열거형입니다.
import static net.mindview.util.Print.*;
// 열거형 유형을 정의합니다.
열거형 신호 { GREEN, YELLOW, RED, }
공개 클래스 신호등 {
신호 색상 = Signal.RED;
공개 무효 변경() {
스위치(색상) {
// Signal.RED라고 말할 필요는 없습니다.
// 케이스 문에서:
케이스 RED: 색상 = Signal.GREEN;
부서지다;
케이스 GREEN: 색상 = Signal.YELLOW;
부서지다;
케이스 노란색: 색상 = Signal.RED;
부서지다;
}
}
공개 문자열 toString() {
return "신호등은 " + 색상입니다.
}
공개 정적 무효 메인(String[] args) {
TrafficLight t = new TrafficLight();
for(int i = 0; i < 7; i++) {
인쇄(티);
t.변경();
}
}
} /* 출력:
신호등이 빨간색이에요
신호등이 녹색입니다
신호등이 노란색입니다
신호등이 빨간색이에요
신호등이 녹색입니다
신호등이 노란색입니다
신호등이 빨간색이에요
*///:~
값의 비밀() 이전에는 value 메소드를 사용했지만 Enum을 보면 값 메소드를 찾을 수 없습니다. 그러면 다른 숨겨진 메소드가 있습니까? 간단한 반영 코드로 이를 확인할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거/Reflection.java
// 리플렉션을 사용하여 열거형을 분석합니다.
import java.lang.reflect.*;
import java.util.*;
수입 net.mindview.util.*;
import static net.mindview.util.Print.*;
enum 탐색 { 여기, 거기 }
공개 클래스 반사 {
공개 정적 Set<String> analyze(Class<?> enumClass) {
print("----- 분석 중 " + enumClass + " -----");
print("인터페이스:");
for(유형 t : enumClass.getGenericInterfaces())
인쇄(티);
print("기본: " + enumClass.getSuperclass());
print("메소드: ");
Set<String> 메소드 = new TreeSet<String>();
for(메소드 m : enumClass.getMethods())
메소드.추가(m.getName());
print(메소드);
반환 방법;
}
공개 정적 무효 메인(String[] args) {
Set<String> exploreMethods = analyze(Explore.class);
Set<String> enumMethods = analyze(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(탐색메소드);
// 열거형에 대한 코드를 디컴파일합니다.
OSExecute.command("javap 탐색");
}
} /* 출력:
----- 수업 분석 탐색 -----
인터페이스:
기본: 클래스 java.lang.Enum
행동 양식:
[compareTo, 같음, getClass, getDeclaringClass, hashCode, 이름, 알림, informAll, 서수, toString, valueOf, 값, 대기]
----- 클래스 java.lang.Enum 분석 -----
인터페이스:
java.lang.Comparable<E>
인터페이스 java.io.Serialized
기본: 클래스 java.lang.Object
행동 양식:
[compareTo, 같음, getClass, getDeclaringClass, hashCode, 이름, 알림, informAll, 서수, toString, valueOf, 대기]
Explore.containsAll(Enum)이 사실인가요?
Explore.removeAll(Enum): [값]
"Reflection.java"에서 컴파일됨
최종 클래스 Explore는 java.lang.Enum을 확장합니다.
public static final 여기에서 살펴보세요.
public static final 거기를 탐험해 보세요;
공개 정적 최종 Explore[] 값();
공개 정적 탐색 valueOf(java.lang.String);
정적 {};
}
*///:~
컴파일러에 의해 value 메소드가 추가된 것을 볼 수 있습니다. valueOf 메서드는 열거형을 생성할 때 컴파일러에 의해 추가되기도 하는데 Enum 클래스에도 valueOf 메서드가 있는데 이 메서드에는 두 개의 매개변수가 있는 반면 컴파일러에 의해 추가된 valueOf 메서드에는 하나의 매개변수만 있습니다. 열거형은 컴파일러에 의해 최종으로 해석되므로 열거형을 상속할 수 없습니다. 값 메소드는 컴파일러가 추가한 정적 메소드이기 때문에 열거형을 Enum으로 캐스팅하면 값 메소드를 사용할 수 없지만 Class에는 getEnumConstants 메소드가 있으므로 값 메소드는 Enum 에서는 사용할 수 없지만 Class 객체를 통해 열거형 인스턴스를 얻을 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/UpcastEnum.java
// 열거형을 업캐스트하는 경우 value() 메서드가 없습니다.
enum 검색 { HITHER, YON }
공개 클래스 UpcastEnum {
공개 정적 무효 메인(String[] args) {
검색[] vals = 검색.값();
Enum e = Search.HITHER // 업캐스트
// e.values(); // Enum에 값()이 없습니다.
for(Enum en : e.getClass().getEnumConstants())
System.out.println(en);
}
} /* 출력:
여기로
욘
*///:~
상속 없이 구현 우리가 정의한 열거 유형은 모두 java.lang.Enum에서 상속되고 Java는 다중 상속을 지원하지 않으므로 열거는 상속을 통해 생성되지 않지만 하나 이상의 인터페이스를 상속하여 열거를 생성할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거/만화/EnumImplementation.java
// 열거형은 인터페이스를 구현할 수 있습니다.
패키지 열거.만화;
import java.util.*;
수입 net.mindview.util.*;
enum CartoonCharacter는 Generator<AnimeCharacter>를 구현합니다.
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;
private Random rand = new Random(47);
공개 CartoonCharacter 다음() {
반환 값()[rand.nextInt(values().length)];
}
}
공개 클래스 EnumImplementation {
공개 정적 <T> 무효 printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
공개 정적 무효 메인(String[] args) {
// 인스턴스를 선택합니다:
CartoonCharacter cc = CartoonCharacter.BOB;
for(int i = 0; i < 10; i++)
printNext(cc);
}
} /* 출력:
밥, 펀치, 밥, 스팽키, 너티, 펀치, 슬래피, 너티, 너티, 슬래피,
*///:~
무작위 선택 이후의 많은 예제에서는 열거형 인스턴스에서 객체를 무작위로 선택합니다. 이를 구현하기 위해 공개 클래스를 만듭니다.
다음과 같이 코드 코드를 복사합니다 .
//: net/mindview/util/Enums.java
패키지 net.mindview.util;
import java.util.*;
공개 클래스 열거형 {
private static Random rand = new Random(47);
공개 정적 <T 확장 Enum<T>> T 무작위(Class<T> ec) {
return random(ec.getEnumConstants());
}
공개 정적 <T> T 무작위(T[] 값) {
반환값[rand.nextInt(values.length)];
}
} ///:~
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/RandomTest.java
수입 net.mindview.util.*;
enum Activity { 앉기, 누워 있기, 서기, 뛰기, 달리기, 피하기, 점프하기, 넘어지기, 날기 }
공개 클래스 RandomTest {
공개 정적 무효 메인(String[] args) {
for(int i = 0; i < 20; i++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* 출력:
서기 날기 달리기 서기 달리기 서기 서기 눕기 피하기 앉기 달리기 깡충 뛰기 깡충 뛰기 깡충깡충 뛰기 서기 눕기 넘어지기 달리기 날아가기 눕기
*///:~
인터페이스를 사용하여 열거형을 구성하는 것은 상속될 수 없으며 때로는 상속을 통해 열거형 수를 확장하고 싶고 때로는 열거형을 그룹화해야 하기 때문에 불편을 초래합니다. 후자의 경우 인터페이스 내에서 그룹화된 열거형을 정의한 다음 이 인터페이스에서 상속하여 열거형을 생성할 수 있습니다. 다음과 같이 열거형으로 생성해야 하는 다양한 음식 카테고리가 있지만 각 카테고리를 유형으로 정의해야 합니다. 식품의 종류는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거된/menu/Food.java
// 인터페이스 내의 열거형을 하위 분류합니다.
패키지 열거.메뉴;
공용 인터페이스 Food {enum Appetizer는 Food {SALAD, SOUP, SPRING_ROLLS;}를 구현합니다.
enum MainCourse는 Food {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}를 구현합니다.
enum 디저트는 음식 {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}을 구현합니다.
enum 커피는 음식을 구현합니다. {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
각 열거형은 인터페이스의 구현으로 정의되므로 각 열거형은 다음과 같이 Food 유형입니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거된/menu/TypeOfFood.java
패키지 열거.메뉴;
import static enumerated.menu.Food.*;
공개 클래스 TypeOfFood {
공개 정적 무효 메인(String[] args) {
음식 음식 = Appetizer.SALAD;
음식 = MainCourse.LASAGNE;
음식 = 디저트.젤라토;
음식 = 커피.카푸치노;
}
} ///:~
그러나 인터페이스는 열거형과 같은 여러 유형에서 작동할 수 없으므로 열거형 열거형이 필요한 경우 각 열거형 유형의 인스턴스를 열거형으로 캡슐화할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거된/menu/Course.java
패키지 열거.메뉴;
수입 net.mindview.util.*;
공개 열거형 코스 {
APPETIZER(Food.Appetizer.class),MAINCOURSE(Food.MainCourse.class),DESSERT(Food.Dessert.class),COFFEE(Food.Coffee.class);
개인 Food[] 값;
개인 코스(Class<? 확장 음식> 종류) {
값 = kind.getEnumConstants();
}
공공 음식 무작위 선택() {
return Enums.random(values);
}
} ///:~
각 열거형은 해당 생성자 매개변수로 Class 개체를 사용하여 열거형 인스턴스를 얻기 위해 이 매개변수에서 getEnumConstants를 사용할 수 있습니다. 이 인스턴스는 무작위 식사를 생성하기 위해 사용할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거된/menu/Meal.java
패키지 열거.메뉴;
공개 수업 식사 {
공개 정적 무효 메인(String[] args) {
for(int i = 0; i < 5; i++) {
for(강좌 코스 : Course.values()) {
음식 음식 =course.randomSelection();
System.out.println(음식);
}
System.out.println("---");
}
}
} /* 출력:
스프링_롤스
빈달루
과일
DECAF_커피
---
국
빈달루
과일
차
---
샐러드
부리또
과일
차
---
샐러드
부리또
크림_캐러멜
라떼
---
국
부리또
티라미수
에스프레소 커피
---
*///:~
보다 간결한 구현은 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/SecurityCategory.java
// 열거형을 더욱 간결하게 하위 분류합니다.
수입 net.mindview.util.*;
열거형 SecurityCategory {
STOCK(보안.스톡.클래스), BOND(보안.본드.클래스);
보안[] 값;
SecurityCategory(Class<? 확장 보안> 종류) {
값 = kind.getEnumConstants();
}
인터페이스 보안 {
enum Stock은 보안 { SHORT, LONG, MARGIN }을 구현합니다.
enum Bond는 보안을 구현합니다. { MUNICIPAL, JUNK }
}
공공 보안 무작위 선택() {
return Enums.random(values);
}
공개 정적 무효 메인(String[] args) {
for(int i = 0; i < 10; i++) {
SecurityCategory 카테고리 = Enums.random(SecurityCategory.class);
System.out.println(범주 + ": " +
카테고리.randomSelection());
}
}
} /* 출력:
채권: 시립
채권: 시립
재고: 마진
재고: 마진
본드: 정크
주식: 짧은
스톡: 롱
스톡: 롱
채권: 시립
본드: 정크
*///:~
다음과 같이 코드 코드를 복사합니다 .
//: 열거된/menu/Meal2.java
패키지 열거.메뉴;
수입 net.mindview.util.*;
공개 열거형 Meal2 {
APPETIZER(Food.Appetizer.class),MAINCOURSE(Food.MainCourse.class),DESSERT(Food.Dessert.class),COFFEE(Food.Coffee.class);
개인 Food[] 값;
private Meal2(Class<? 확장 Food> 종류) {
값 = kind.getEnumConstants();
}
공개 인터페이스 음식 {
enum Appetizer는 Food {SALAD, SOUP, SPRING_ROLLS;}를 구현합니다.
enum MainCourse는 Food {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}를 구현합니다.
enum 디저트는 음식 {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}을 구현합니다.
enum 커피는 음식을 구현합니다. {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
공공 음식 무작위 선택() {
return Enums.random(values);
}
공개 정적 무효 메인(String[] args) {
for(int i = 0; i < 5; i++) {
for(Meal2 식사 : Meal2.values()) {
음식 음식 = 식사.randomSelection();
System.out.println(음식);
}
System.out.println("---");
}
}
} /* Meal.java와 동일한 출력 *///:~
플래그 대신 EnumSet 사용 EnumSet은 정수 기반 비트 플래그를 대체하기 위해 enum과 Set을 결합하기 위해 Java SE5에 추가되었습니다. 일반적으로 비트 플래그는 어떤 종류의 정보가 전환되었음을 나타내는 데 사용되지만, 코드에서는 의미 있는 개념보다는 비트를 조작하므로 이해하기 쉽지 않습니다. EnumSet은 비트 플래그보다 빠릅니다. 내부적으로 long을 사용하여 비트 벡터를 나타내고, 효율성에 대한 걱정 없이 보다 개념적인 언어를 사용하여 특정 비트의 스위치를 나타낼 수 있습니다. EnumSet의 요소는 동일한 열거에서 나와야 합니다. 다음은 알람 위치의 열거를 정의합니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/AlarmPoints.java
패키지가 열거되었습니다.
공개 열거형 AlarmPoints {STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3,OFFICE4, BATHROOM, UTILITY, KITCHEN} ///:~
그런 다음 EnumSet 클래스를 사용하여 경보 상태를 추적합니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/EnumSets.java
// EnumSet에 대한 작업
패키지가 열거되었습니다.
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
공개 클래스 EnumSets {
공개 정적 무효 메인(String[] args) {
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class) // 빈 세트
points.add(욕실);
인쇄(포인트);
points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
인쇄(포인트);
points = EnumSet.allOf(AlarmPoints.class);
points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));
인쇄(포인트);
points.removeAll(EnumSet.range(OFFICE1, OFFICE4));
인쇄(포인트);
포인트 = EnumSet.complementOf(포인트);
인쇄(포인트);
}
} /* 출력:
[화장실]
[1층, 2층, 욕실, 주방]
[로비, 사무실1, 사무실2, 사무실3, 사무실4, 욕실, 유틸리티]
[로비, 욕실, 유틸리티]
[계단1, 계단2, 사무실1, 사무실2, 사무실3, 사무실4, 주방]
*///:~
EnumSet은 long 유형을 기반으로 하며 64비트를 가지는데, 열거 유형이 이 숫자를 초과하면 어떻게 될까요?
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/BigEnumSet.java
import java.util.*;
공개 클래스 BigEnumSet {
열거형 빅 { 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}
공개 정적 무효 메인(String[] args) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
} /* 출력:
[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]
*///:~
프로그램이 정상적으로 실행되는 것을 볼 수 있으므로 EnumMap을 사용하여 열거형 유형을 수용하는 데 도움이 되도록 내부적으로 long 유형이 추가되었을 가능성이 높습니다.
EnumMap은 Map의 특수한 유형입니다. 해당 키의 값은 동일한 열거형의 유형일 수 있습니다. 따라서 EnumMap은 배열을 통해 내부적으로 구현될 수 있으며 이는 매우 효율적입니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/EnumMaps.java
// EnumMap의 기본입니다.
패키지가 열거되었습니다.
import java.util.*;
import static enumerated.AlarmPoints.*;
import static net.mindview.util.Print.*;
인터페이스 명령 { void action() }
공개 클래스 EnumMaps {
공개 정적 무효 메인(String[] args) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(KITCHEN, 새로운 Command() {
public void action() { print("주방에 불이 났어요!") }
});
em.put(BATHROOM, new Command() {
public void action() { print("화장실 경고!") }
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // 특정 키에 대한 값이 없는 경우:
em.get(UTILITY).action();
} catch(예외 e) {
인쇄(e);
}
}
} /* 출력:
욕실: 욕실 경고!
주방: 주방에 불이 났어요!
java.lang.NullPointerException
*///:~
특정 상수 메서드 Java 열거형에는 매우 흥미로운 기능이 있습니다. 즉, 각 열거형 인스턴스에 대해 서로 다른 동작을 정의할 수 있습니다. 이를 달성하기 위해 열거형의 일부로 하나 이상의 추상 메서드를 정의한 다음 각각에 대해 서로 다른 동작을 정의합니다. 열거 인스턴스 정의 방법:
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/ConstantSpecificMethod.java
import java.util.*;
import java.text.*;
공개 열거형 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");}};
추상 문자열 getInfo();
공개 정적 무효 메인(String[] args) {
for(ConstantSpecificMethod csm : 값())
System.out.println(csm.getInfo());
}
} /* (실행하여 출력 확인) *///:~
위의 코드는 각 열거형 요소가 서로 다른 요소이고 모든 요소가 ConstantSpecificMethod 기본 클래스에서 상속된다는 점에서 멈춘 것처럼 보이지만 열거형 요소를 유형으로 처리할 수 없기 때문에 실제로 이런 식으로 이해할 수는 없습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/NotClasses.java
// {실행: javap -c LikeClasses}
import static net.mindview.util.Print.*;
enum LikeClasses {WINKEN { void 행동() { print("Behavior1") } },BLINKEN { void 행동() { print("Behavior2") } },NOD { void 행동() { print("Behavior3") ; } };
추상 무효 동작();
}
공개 클래스 NotClasses {
// void f1(LikeClasses.WINKEN 인스턴스) {} // 아니요
} /* 출력:
"NotClasses.java"에서 컴파일됨
추상 클래스 LikeClasses는 java.lang.Enum을 확장합니다.
공개 정적 최종 LikeClasses WINKEN;
공개 정적 최종 LikeClasses BLINKEN;
공개 정적 최종 LikeClasses NOD;
...
*///:~
또 다른 예를 들어보면 고객은 다양한 메뉴에 따라 다양한 서비스를 선택할 수 있으며, 다음과 같이 EnumSet을 사용하여 고객의 선택을 유지할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/CarWash.java
import java.util.*;
import static net.mindview.util.Print.*;
공개 클래스 CarWash {
public enum Cycle {UNDERBODY {void action() { print("하체 분사" }},
WHEELWASH {void action() { print("바퀴 세척") },
PREWASH {void action() { print("먼지 제거" }},
BASIC {void action() { print("기본 워시" }},
HOTWAX {void action() { print("뜨거운 왁스 도포 중") },
RINSE {void action() { print("헹굼" }},
BLOWDRY {void action() { print("건조함") }};
추상 무효 액션();
}
EnumSet<Cycle> 사이클 = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
공개 무효 추가(주기 주기) { Cycles.add(주기) }
공공 무효 wascar() {
for(사이클 c : 사이클)
c.액션();
}
공개 문자열 toString() { returncycles.toString() }
공개 정적 무효 메인(String[] args) {
CarWash 세척 = new CarWash();
인쇄(세탁);
세척.washCar();
// 추가 순서는 중요하지 않습니다.
세척.추가(Cycle.BLOWDRY);
Wash.add(Cycle.BLOWDRY); // 중복은 무시됩니다.
세척.추가(Cycle.RINSE);
세척.추가(Cycle.HOTWAX);
인쇄(세탁);
세척.washCar();
}
} /* 출력:
[기본, 린스]
기본적인 세탁
헹굼
[베이직, 핫왁스, 린스, 블로우드라이]
기본적인 세탁
핫 왁스 바르기
헹굼
불어 건조
*///:~
상속된 추상 메서드를 사용하는 대신 다음과 같이 기본 특정 상수 메서드를 재정의할 수도 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/OverrideConstantSpecific.java
import static net.mindview.util.Print.*;
공개 열거형 OverrideConstantSpecific {
NUT, BOLT,WASHER {void f() { print("재정의된 메서드") }};
void f() { print("기본 동작") }
공개 정적 무효 메인(String[] args) {
for(OverrideConstantSpecific ocs : 값()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* 출력:
NUT: 기본 동작
BOLT: 기본 동작
WASHER: 재정의된 메서드
*///:~
때때로 체인의 특정 요청을 전달하려는 경우 체인의 개체가 요청을 처리할 수 있다는 것을 아는 것은 특정 상수 메서드를 사용하여 쉽게 달성할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/PostOffice.java
// 우체국 모델링.
열거형 743
import java.util.*;
수입 net.mindview.util.*;
import static net.mindview.util.Print.*;
클래스 메일 {
// NO는 무작위 선택 확률을 낮춥니다.
열거형 일반배송 {YES,NO1,NO2,NO3,NO4,NO5}
열거형 스캔 가능성 {UNSCANNABLE,YES1,YES2,YES3,YES4}
열거형 가독성 {ILLEGIBLE,YES1,YES2,YES3,YES4}
열거형 주소 {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
열거형 반환 주소 {MISSING,OK1,OK2,OK3,OK4,OK5}
일반배송 일반배송;
스캔 가능성 스캔 가능성;
가독성 가독성;
주소 주소;
ReturnAddress returnAddress;
정적 긴 카운터 = 0;
긴 ID = 카운터++;
공개 문자열 toString() { 반환 "메일" + ID }
공개 문자열 세부정보() {
return toString() + ", 일반 배달: " + GeneralDelivery + ", 주소 스캔 가능성: " + 스캔 가능성 + ", 주소 가독성: " + 가독성 +
", 주소 주소: " + 주소 + ", 반환 주소: " + returnAddress;
}
//테스트 메일 생성:
공개 정적 메일 randomMail() {
메일 m = 새 메일();
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);
m을 반환;
}
public static Iterable<Mail> 생성기(최종 정수 개수) {
return new Iterable<Mail>() {
int n = 개수;
공개 Iterator<메일> iterator() {
새로운 Iterator<Mail>() {를 반환합니다.
공개 부울 hasNext() { 반환 n-- > 0 }
공개 메일 next() { return randomMail() }
public void Remove() { // 구현되지 않음
새로운 UnsupportedOperationException()을 던져라;
}
};
}
};
}
}
공개 클래스 우체국 {
열거형 메일 핸들러 {
일반_배달 {
부울 핸들(Mail m) {
스위치(m.generalDelivery) {
예:
print("일반 배달 사용 " + m);
사실을 반환;
기본값: false를 반환합니다.
}
}
},
MACHINE_SCAN {
부울 핸들(Mail m) {
스위치(m.scannability) {
스캔할 수 없는 경우: false를 반환합니다.
기본:
스위치(m.주소) {
대소문자가 올바르지 않음: false를 반환합니다.
기본:
print(""+ m + "를 자동으로 전달 중");
사실을 반환;
}
}
}
},
VISUAL_INSPECTION {
부울 핸들(Mail m) {
스위치(m.가독성) {
읽을 수 없는 경우: false를 반환합니다.
기본:
스위치(m.주소) {
대소문자가 올바르지 않음: false를 반환합니다.
기본:
print("" + m + "를 정상적으로 전달 중");
사실을 반환;
}
}
}
},
RETURN_TO_SENDER {
부울 핸들(Mail m) {
스위치(m.returnAddress) {
케이스 누락: false를 반환합니다.
기본:
print("발신자에게 " + m + "를 반환합니다.");
사실을 반환;
}
}
};
추상 불리언 핸들(Mail m);
}
정적 무효 핸들(메일 m) {
for(MailHandler 핸들러 : MailHandler.values())
if(handler.handle(m))
반품;
print(m + "는 데드레터입니다.");
}
공개 정적 무효 메인(String[] args) {
for(메일 메일 : Mail.generator(10)) {
print(mail.details());
핸들(메일);
인쇄("*****");
}
}
} /* 출력:
메일 0, 일반 배송: NO2, 주소 스캔 가능: UNSCANNABLE, 주소 판독 가능: YES3, 주소 주소: OK1, 반송 주소: OK1
메일 0을 정상적으로 배달 중
*****
메일 1, 일반 배송: NO5, 주소 스캔 가능: YES3, 주소 가독성: ILLEGIBLE, 주소 주소: OK5, 반송 주소: OK1
메일 1을 자동으로 배달하기
*****
메일 2, 일반 배송: YES, 주소 스캔 가능: YES3, 주소 판독 가능: YES1, 주소 주소: OK1, 반송 주소: OK5
메일 2에 일반 배달 사용
*****
메일 3, 일반 배송: NO4, 주소 스캔 가능: YES3, 주소 판독 가능: YES1, 주소 주소: INCORRECT, 반송 주소: OK4
메일 3을 보낸 사람에게 반환
*****
메일 4, 일반 배송: NO4, 주소 스캔 가능: UNSCANNABLE, 주소 판독 가능: YES1, 주소 주소: INCORRECT, 반송 주소: OK2
메일 4를 보낸 사람에게 반환
*****
메일 5, 일반 배송: NO3, 주소 스캔 가능: YES1, 주소 가독성: ILLEGIBLE, 주소 주소: OK4, 반송 주소: OK2
메일 5를 자동으로 배달하기
*****
메일 6, 일반 배송: YES, 주소 스캔 가능: YES4, 주소 가독성: ILLEGIBLE, 주소 주소: OK4, 반송 주소: OK4
메일 6에 일반 배달 사용
*****
메일 7, 일반 배송: YES, 주소 스캔 가능: YES3, 주소 판독 가능: YES4, 주소 주소: OK2, 반송 주소: MISSING
Mail 7에 일반 배달 사용
*****
메일 8, 일반 배송: NO3, 주소 스캔 가능: YES1, 주소 판독 가능: YES3, 주소 주소: INCORRECT, 반송 주소: MISSING
메일 8은 데드레터입니다
*****
메일 9, 일반 배송: NO1, 주소 스캔 가능: UNSCANNABLE, 주소 판독 가능: YES2, 주소 주소: OK1, 반송 주소: OK4
메일9 정상적으로 배달하기
*****
*///:~
열거형은 상태 기계를 생성하는 데 이상적인 유형이기도 합니다. 상태 기계는 입력에 따라 제한된 수의 상태 사이를 이동할 수 있으며 특정 상태가 충족되면 작업을 종료할 수 있습니다. 해당 출력은 다음과 같습니다. 열거형 내에서 다양한 입력을 정의하는 일반적인 상태 머신의 예입니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/Input.java
패키지가 열거되었습니다.
import java.util.*;
공개 열거형 입력 {
니켈(5), 다임(10), 쿼터(25), 달러(100), 치약(200), 칩(75), 소다(100), 비누(50), ABORT_TRANSACTION {
public int amount() { // 허용하지 않음
throw new RuntimeException("ABORT.amount()");
}
},
STOP { // 이것은 마지막 인스턴스여야 합니다.
public int amount() { // 허용하지 않음
throw new RuntimeException("SHUT_DOWN.amount()");
}
};
int 값; // 센트 단위
입력(int 값) { this.value = 값 }
입력() {}
int amount() { 반환 값 };
static Random rand = new Random(47);
공개 정적 입력 무작위 선택() {
// STOP을 포함하지 마세요:
반환 값()[rand.nextInt(values().length - 1)];
}
} ///:~
VendingMachine은 입력에 응답하는 데 사용됩니다. 먼저 Category 열거를 통해 입력을 분류한 다음 switch 문을 사용합니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/VendingMachine.java
// {Args: VendingMachineInput.txt}
패키지가 열거되었습니다.
import java.util.*;
수입 net.mindview.util.*;
import static enumerated.Input.*;
import static net.mindview.util.Print.*;
열거형 카테고리 {
MONEY(NICKEL, DIME, QUARTER, DOLLAR),ITEM_SELECTION(치약, 칩, 소다, 비누),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
개인 입력[] 값;
카테고리(입력... 유형) { 값 = 유형 }
private static EnumMap<Input,Category> 카테고리 = new EnumMap<Input,Category>(Input.class);
정적 {
for(카테고리 c : Category.class.getEnumConstants())
for(입력 유형 : c.values)
카테고리.put(유형, c);
}
공개 정적 카테고리 분류(입력 입력) {
카테고리를 반환합니다.get(입력);
}
}
공개 클래스 VendingMachine {
개인 정적 상태 상태 = State.RESTING;
개인 정적 정수 금액 = 0;
개인 정적 입력 선택 = null;
enum StateDuration {TRANSIENT} //태그 지정 enum
열거형 상태 {
휴식 중 {
void next(입력입력) {
스위치(Category.categorize(입력)) {
케이스 돈:
금액 += input.amount();
상태 = ADDING_MONEY;
부서지다;
케이스 SHUT_DOWN:
상태 = 터미널;
기본:
}
}
},
ADDING_MONEY {
void next(입력입력) {
스위치(Category.categorize(입력)) {
케이스 돈:
금액 += input.amount();
부서지다;
케이스 ITEM_SELECTION:
선택 = 입력;
if(금액 < 선택.금액())
print("금액이 부족하여 " + 선택);
그렇지 않으면 상태 = 분배 중;
부서지다;
QUIT_TRANSACTION:
상태 = GIVING_CHANGE;
부서지다;
케이스 SHUT_DOWN:
상태 = 터미널;
기본:
}
}
},
DISPENSING(StateDuration.TRANSIENT) {
무효 다음() {
print("여기에 " + 선택 항목이 있습니다);
금액 -= 선택.금액();
상태 = GIVING_CHANGE;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
무효 다음() {
if(금액 > 0) {
print("변경사항: " + 금액);
금액 = 0;
}
상태 = 휴식 중;
}
},
TERMINAL { void 출력() { print("정지됨") } };
개인 부울 isTransient = false;
상태() {}
State(StateDuration trans) { isTransient = true }
void next(입력입력) {
throw new RuntimeException("일시적이지 않은 상태에 대해서만 " + "next(입력 입력) 호출");
}
무효 다음() {
throw new RuntimeException("" + "StateDuration.TRANSIENT 상태에 대해서만 next()를 호출합니다.");
}
무효 출력() { 인쇄(금액) }
}
정적 무효 실행(Generator<Input> gen) {
while(state != State.TERMINAL) {
state.next(gen.next());
동안(state.isTransient)
상태.다음();
상태.출력();
}
}
공개 정적 무효 메인(String[] args) {
Generator<Input> gen = new RandomInputGenerator();
if(args.length == 1)
gen = new FileInputGenerator(args[0]);
실행(gen);
}
}
// 기본적인 온전성 검사를 위해:
RandomInputGenerator 클래스는 Generator<Input> {를 구현합니다.
공개 입력 next() { return Input.randomSelection() }
}
// ';'으로 구분된 문자열 파일에서 입력을 생성합니다.
FileInputGenerator 클래스는 Generator<Input> {를 구현합니다.
개인 Iterator<String> 입력;
공개 FileInputGenerator(문자열 파일 이름) {
입력 = new TextFile(fileName, ";").iterator();
}
공개 입력 next() {
if(!input.hasNext())
null을 반환;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* 출력:
여기 당신의 칩이 있습니다
여기 치약이 있어요
변경사항: 35
SODA에 자금이 부족함
SODA에 자금이 부족함
변경사항: 75
정지됨
*///:~
위의 출력을 생성하는 데 사용된 테스트 데이터는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
분기;
달러;
분기; ABORT_TRANSACTION;
쿼터;
쿼터;
ABORT_TRANSACTION;
멈추다;
///:~
다중 압축 풀기 여러 유형 간의 상호 작용을 처리할 때 Number.plush(Number), Number.mutiply(Number) 등과 같이 코드가 지저분해질 수 있습니다. Number는 패밀리의 기본 클래스일 뿐이므로 호출할 때 a.plus(b)의 경우 a의 유형이나 b의 유형을 알지 못하는데, 이들 사이의 상호 작용이 올바른지 어떻게 확인할 수 있습니까? Java는 단일 압축 해제만 수행할 수 있습니다. 즉, 알 수 없는 여러 유형의 작업이 하나 이상 수행되는 경우 Java는 위에서 설명한 문제를 해결할 수 없는 유형 중 하나에 대해서만 동적 바인딩 메커니즘을 수행할 수 있습니다. 동적 바인딩 코드를 수동으로 작성합니다.
해결책은 다중 바인딩을 사용하는 것입니다. 다형성은 메소드를 호출할 때만 발생할 수 있으므로 다중 언패킹이 필요한 경우 다중 메소드를 호출해야 합니다. 다중 언래핑을 사용하려면 언래핑할 각 유형의 메서드를 호출하는 가상 메서드가 있어야 합니다. 다음 예는 가위바위보 예입니다.
다음과 같이 코드 코드를 복사합니다 .
//: 열거됨/Outcome.java
패키지가 열거되었습니다.
공개 열거형 결과 {WIN, LOSE, DRAW } ///:~
//: 열거됨/RoShamBo1.java
// 다중 디스패칭 시연.
패키지가 열거되었습니다.
import java.util.*;
import static enumerated.Outcome.*;
인터페이스 항목 {
결과 경쟁(항목 it);
결과 평가(논문 p);
결과 평가(가위);
결과 평가(Rock r);
}
클래스 종이 도구 항목 {
공개 결과 경쟁(항목 it) { return it.eval(this) }
공개 결과 평가(논문 p) { return DRAW }
공개 결과 평가(가위) { WIN 반환 }
공개 결과 평가(Rock r) { LOSE 반환 }
공개 문자열 toString() { 반환 "종이" };
}
가위 클래스는 항목 {을 구현합니다.
공개 결과 경쟁(항목 it) { return it.eval(this) }
공개 결과 평가(종이 p) { LOSE 반환 }
공개 결과 평가(가위) { DRAW 반환 }
공개 결과 평가(Rock r) { WIN 반환 }
공개 문자열 toString() { "가위" 반환 }
}
클래스 Rock은 아이템 {을 구현합니다.
공개 결과 경쟁(항목 it) { return it.eval(this) }
공개 결과 평가 (종이 P) {반환 승리;
공개 결과 평가 (가위) {return Lose};
공개 결과 평가 (Rock R) {return draw}
공개 문자열 toString () {return "rock"};
}
공개 클래스 roshambo1 {
정적 최종 int 크기 = 20;
개인 정적 랜덤 랜드 = 새로운 랜덤 (47);
공개 정적 항목 newitem () {
스위치 (rand.nextint (3)) {
기본:
사례 0 : 새로운 가위 반환 ();
사례 1 : 새 용지를 반환합니다 ();
사례 2 : New Rock ()을 반환합니다.
}
}
공개 정적 무효 일치 (항목 A, 항목 B) {
System.out.println (a + "vs." + b + ":" + a.compete (b));
}
공개 정적 무효 메인(String[] args) {
for (int i = 0; i <size; i ++)
매치 (newitem (), newitem ());
}
} /* 출력 :
바위 대 바위 : 드로우
종이 대 록 : 승리
종이 대 록 : 승리
종이 대 록 : 승리
가위 대 종이 : 승리
가위 대 가위 : 그림
가위 대 종이 : 승리
바위 대 종이 : 잃어 버립니다
종이 대 종이 : 그리기
바위 대 종이 : 잃어 버립니다
종이 대 가위 : 잃어버린
종이 대 가위 : 잃어버린
바위 대 가위 : 승리
바위 대 종이 : 잃어 버립니다
종이 대 록 : 승리
가위 대 종이 : 승리
종이 대 가위 : 잃어버린
종이 대 가위 : 잃어버린
종이 대 가위 : 잃어버린
종이 대 가위 : 잃어버린
*/// : ~
우리는 여러 가지 방법을 사용하여 다중 포장 풀기를 달성했지만 우리가 얻은 것은 좋은 코드 구조였습니다. 위의 코드를 구현하기 위해 열거 솔루션을 사용할 때 가장 큰 문제는 열거 인스턴스가 유형이 아니므로 열거 인스턴스를 매개 변수 유형으로 사용할 수 없다는 것입니다. 그러나 우리는 여전히이 장애물을 둘러 볼 수있는 다른 방법을 가질 수 있습니다. 한 가지 방법은 생성자를 사용하여 각 열거 유형을 초기화 한 다음 출력을 조회 테이블로 구성하는 것입니다.
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo2.java
// 하나의 열거를 다른 열에 전환합니다.
열거 된 패키지;
import static enumerated.outcome.*;
Public Enum Roshambo2 경쟁자 <Roshambo2> {
종이 (그리기, 잃어버린, 승리), 가위 (승리, 그림, 잃음), 바위 (잃어버린, 승리, 그리기);
개인 결과 vpaper, vcissors, vrock;
Roshambo2 (결과 논문, 결과 가위, 결과 록) {
this.vpaper = 종이;
this.vcissors = 가위;
this.vrock = 바위;
}
공개 결과 경쟁 (Roshambo2 IT) {
스위치 (IT) {
기본:
사례 종이 : 반환 vpaper;
사례 가위 : 반환 vcsissors;
케이스 록 : 반환 vrock;
}
}
공개 정적 무효 메인(String[] args) {
Roshambo.play (Roshambo2.class, 20);
}
} /* 출력 :
바위 대 바위 : 드로우
가위 대 바위 : 잃어 버립니다
가위 대 바위 : 잃어 버립니다
열거 된 유형 753
가위 대 바위 : 잃어 버립니다
종이 대 가위 : 잃어버린
종이 대 종이 : 그리기
종이 대 가위 : 잃어버린
바위 대 가위 : 승리
가위 대 가위 : 그림
바위 대 가위 : 승리
가위 대 종이 : 승리
가위 대 종이 : 승리
바위 대 종이 : 잃어 버립니다
바위 대 가위 : 승리
가위 대 바위 : 잃어 버립니다
종이 대 가위 : 잃어버린
가위 대 종이 : 승리
가위 대 종이 : 승리
가위 대 종이 : 승리
가위 대 종이 : 승리
*/// : ~
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/competitor.java
// 하나의 열거를 다른 열에 전환합니다.
열거 된 패키지;
Public Interface Competitor <t 확장 경쟁자 <t >> {
결과 경쟁 (t 경쟁자);
} /// : ~
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo.java
// Roshambo 예제를위한 일반적인 도구.
열거 된 패키지;
import net.mindview.util.*;
공개 클래스 Roshambo {
public static <t는 경쟁자를 확장합니다 <t >> void match (t a, t b) {
System.out.println (a + "vs." + b + ":" + a.compete (b));
}
public static <t extends enum <t> & competitor <t >> void play (class <t> rsbclass, int size) {
for (int i = 0; i <size; i ++)
매치 (enums.random (rsbclass), enums.random (rsbclass));
}
} /// : ~
정적 방법을 공식화하는 것은 각 열거 유형에 대해 다른 방법을 제공 할 수 있기 때문에 여러 개의 포장 풀기를 달성하는 것이 좋은 솔루션 인 것 같습니다. 그러나 우리는 여전히 열거 인스턴스가 유형이 아니라는 문제에 직면하므로 스위치 문을 추가하는 것입니다. :
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo3.java
// 상수 특정 방법을 사용합니다.
열거 된 패키지;
import static enumerated.outcome.*;
Public enum roshambo3 경쟁자 <Roshambo3> {
종이 {
공개 결과 경쟁 (Roshambo3 IT) {
스위치 (IT) {
기본값 : // 컴파일러를 배치합니다
사례 용지 : 리턴 드로우;
사례 가위 : 반환 패배;
Case Rock : 리턴 승리;
}
}
},
가위 {
공개 결과 경쟁 (Roshambo3 IT) {
스위치 (IT) {
기본:
사례 종이 : 반환 승리;
사례 가위 : 리턴 드로우;
Case Rock : 반환 패배;
}
}
},
바위 {
공개 결과 경쟁 (Roshambo3 IT) {
스위치 (IT) {
기본:
사례 종이 : 반환 패배;
사례 가위 : 리턴 승리;
케이스 록 : 리턴 드로우;
}
}
};
공개 초록 결과 경쟁 (Roshambo3 IT);
공개 정적 무효 메인(String[] args) {
Roshambo.play (Roshambo3.class, 20);
}
}/ * Roshambo2.java와 동일한 출력 * /// : ~
다음 코드는보다 간결한 구현 방법입니다.
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo4.java
열거 된 패키지;
Public Enum Roshambo4 경쟁자 <Roshambo4> {
바위 {
공개 결과 경쟁 (Roshambo4 상대) {
귀환 경쟁 (가위, 상대);
}
},
가위 {
공개 결과 경쟁 (Roshambo4 상대) {
반품 경쟁 (종이, 상대);
}
},
종이 {
공개 결과 경쟁 (Roshambo4 상대) {
반품 경쟁 (록, 상대);
}
};
결과 경쟁 (Roshambo4 Loser, Roshambo4 상대) {
return ((옵션 == this)? upcome.raw.
}
공개 정적 무효 메인(String[] args) {
Roshambo.play (Roshambo4.class, 20);
}
}/ * Roshambo2.java와 동일한 출력 * /// : ~
EnumMap 클래스는 실제로 여러 포장 풀기를 구현하는 좋은 방법 인 것 같습니다.
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo5.java
// 열거의 열기 맵을 사용하여 다중 디스패치.
열거 된 패키지;
import java.util.*;
import static enumerated.outcome.*;
Enum Roshambo5 경쟁자 <Roshambo5> {
종이, 가위, 암석;
정적 ENUMMAP <ROSHAMBO5, ENUMMAP <ROSHAMBO5, 결과 >> table = new enummap <roShambo5, enumMap <Roshambo5, 결과 >> (roShambo5.class);
정적 {
for (roshambo5 it : roshambo5.values ())
table.put (It, New EnumMap <Roshambo5, 결과> (Roshambo5.class));
Initrow (종이, 그림, 잃고, 승리);
Initrow (가위, 승리, 그림, 잃음);
Initrow (바위, 잃고, 승리, 그림);
}
정적 무효 Initrow (Roshambo5 IT, 결과 vpaper, 결과 vcissors, 결과 vrock) {
enummap <roShambo5, 결과> row = roshambo5.table.get (it);
row.put (Roshambo5.paper, vpaper);
row.put (roshambo5.cissors, vcsissors);
row.put (Roshambo5.Rock, vrock);
}
공개 결과 경쟁 (Roshambo5 IT) {
return.get (this) .get (it);
}
공개 정적 무효 메인(String[] args) {
Roshambo.play (Roshambo5.class, 20);
}
}/ * Roshambo2.java와 동일한 출력 * /// : ~
또한 열거 인스턴스의 기능을 고정 값으로 사용하여 가장 간단한 구현 방법에 대한 데이터를 사용 할 수 있습니다.
다음과 같이 코드 코드를 복사합니다 .
// : 열거 된/roshambo6.java
// 여러 발송 대신 "테이블"을 사용하는 열거.
열거 된 패키지;
import static enumerated.outcome.*;
Enum Roshambo6 경쟁자 <Roshambo6> {
종이, 가위, 암석;
개인 정적 결과 [] [] 표 = {
{그리기, 잃어버린, 승리}, // 종이
{win, draw, lose}, // 가위
{잃고, 승리, 드로우}, // 락
};
공개 결과 경쟁 (Roshambo6 기타) {
리턴 테이블 [this.ordinal ()] [기타. ordinal ()];
}
공개 정적 무효 메인(String[] args) {
Roshambo.play (Roshambo6.class, 20);
}
} /// : ~