수색…


소개

enum ( enum 키워드를 사용하여 선언 된) enum 은 단일 클래스의 상당한 양의 상수에 대한 약식 구문입니다.

통사론

  • [public / protected / private] enum Enum_name {// 새로운 enum을 선언합니다.
  • ENUM_CONSTANT_1 [, ENUM_CONSTANT_2 ...]; // enum 상수를 선언하십시오. 이것은 enum 내부의 첫 번째 줄이어야하며 마지막에는 세미콜론과 함께 쉼표로 구분해야합니다.
  • ENUM_CONSTANT_1 (param) [, ENUM_CONSTANT_2 (param) ...]; // 매개 변수로 enum 상수를 선언하십시오. 매개 변수 유형은 생성자와 일치해야합니다.
  • ENUM_CONSTANT_1 {...} [, ENUM_CONSTANT_2 {...} ...]; // 재정의 된 메서드를 사용하여 enum 상수를 선언합니다. 열거 형에 추상 메소드가 포함되어 있으면이 작업을 수행해야합니다. 그러한 모든 방법을 구현해야합니다.
  • ENUM_CONSTANT.name () // enum 정수의 이름을 가지는 String를 돌려줍니다.
  • ENUM_CONSTANT.ordinal () //이 열거 형 상수의 서수를 반환합니다.이 열거 형 상수는 열거 형 선언의 위치이며, 초기 상수에는 0의 서수가 할당됩니다.
  • Enum_name.values ​​() // 호출 할 때마다 해당 열거 형의 모든 상수를 포함하는 새 배열 (Enum_name [] 유형)을 반환합니다.
  • Enum_name.valueOf ( "ENUM_CONSTANT") // ENUM_CONSTANT.name ()의 역함 - 주어진 이름의 enum 상수를 반환합니다.
  • Enum.valueOf (Enum_name.class, "ENUM_CONSTANT") // 이전의 동의어 : ENUM_CONSTANT.name ()의 역함 - 주어진 이름의 enum 상수를 반환합니다.

비고

제한 사항

열거 형은 항상 java.lang.Enum 을 확장하므로 enum이 클래스를 확장 할 수 없습니다. 그러나 많은 인터페이스를 구현할 수 있습니다.

팁 & 트릭

특수 표현으로 인해 enum을 키로 사용할 수있는보다 효율적인 세트 가 있습니다. 이들은 종종 비 전문 기술자보다 더 빨리 실행됩니다.

기본 enum 선언 및 사용

열거 형 은 일련의 상수를 정의하기 위해 컴파일 타임에 알려진 여러 번 인스턴스화 된 봉인 된 클래스에 대한 구문 설탕으로 간주 될 수 있습니다.

다른 계절을 나열하는 간단한 열거 형은 다음과 같이 선언됩니다.

public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

열거 형 상수가 모두 대문자로되어있을 필요는 없지만, 상수의 이름은 완전히 대문자이며 단어는 밑줄로 구분됩니다.


Enum을 자체 파일에 선언 할 수 있습니다.

/**
 * This enum is declared in the Season.java file.
*/
public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

하지만 다른 클래스에서 선언 할 수도 있습니다.

 public class Day {

    private Season season;

    public String getSeason() {
        return season.name();
    }

    public void setSeason(String season) {
        this.season = Season.valueOf(season);
    }

    /**
     * This enum is declared inside the Day.java file and 
     * cannot be accessed outside because it's declared as private.
     */
    private enum Season {
        WINTER,
        SPRING,
        SUMMER,
        FALL
    }

}

마지막으로 메소드 몸체 또는 생성자 안에 Enum을 선언 할 수 없습니다.

public class Day {

    /**
     * Constructor
    */
    public Day() {
        // Illegal. Compilation error
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }
    }

    public void aSimpleMethod() {
        // Legal. You can declare a primitive (or an Object) inside a method. Compile!
        int primitiveInt = 42;

        // Illegal. Compilation error.
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }

        Season season = Season.SPRING;
    }
    
}

중복 열거 형 상수는 허용되지 않습니다.

public enum Season {
    WINTER,
    WINTER, //Compile Time Error : Duplicate Constants
    SPRING,
    SUMMER,
    FALL
} 

enum의 모든 상수는 기본적으로 public , staticfinal 입니다. 모든 상수는 static 이므로 열거 형 이름을 사용하여 직접 액세스 할 수 있습니다.

열거 형 상수는 메소드 매개 변수로 전달 될 수 있습니다.

public static void display(Season s) {
    System.out.println(s.name());  // name() is a built-in method that gets the exact name of the enum constant
}

display(Season.WINTER);  // Prints out "WINTER"

values() 메서드를 사용하여 열거 형 상수의 배열을 가져올 수 있습니다. 값은 반환 된 배열에서 선언 순서가되도록 보장됩니다.

Season[] seasons = Season.values();

주 :이 메소드는, 불려 갈 때마다 새로운 값의 배열을 할당합니다.


열거 형 상수를 반복하려면 다음을 수행하십시오.

public static void enumIterate() {
    for (Season s : Season.values()) {
        System.out.println(s.name());
    }
}

switch 문에서 enum을 사용할 수 있습니다.

public static void enumSwitchExample(Season s) {
    switch(s) {
        case WINTER:
            System.out.println("It's pretty cold");
            break;
        case SPRING:
            System.out.println("It's warming up");
            break;
        case SUMMER:
            System.out.println("It's pretty hot");
            break;
        case FALL:
            System.out.println("It's cooling down");
            break;
    }
}

== 사용하여 열거 형 상수를 비교할 수도 있습니다.

Season.FALL == Season.WINTER    // false
Season.SPRING == Season.SPRING  // true

열거 형 상수를 비교하는 또 다른 방법은 다음과 같이 함정에 쉽게 빠질 수있는 나쁜 연습으로 간주되는 equals() 를 사용하는 것입니다.

Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false and no compiler error

게다가 enum 에있는 인스턴스 집합은 런타임에 변경할 수 없지만 인스턴스 자체는 본질적으로 변경되지 않습니다. 왜냐하면 다른 클래스와 마찬가지로 enum 은 아래에 설명 된 것처럼 변경할 수있는 필드를 포함 할 수 있기 때문입니다.

public enum MutableExample {
    A,
    B;

    private int count = 0;

    public void increment() {
        count++;
    }

    public void print() {
        System.out.println("The count of " + name() + " is " + count);
    }
}

// Usage:
MutableExample.A.print();       // Outputs 0
MutableExample.A.increment();
MutableExample.A.print();       // Outputs 1 -- we've changed a field   
MutableExample.B.print();       // Outputs 0 -- another instance remains unchanged

그러나 좋은 예는 enum 인스턴스를 변경 불가능하게 만드는 것입니다. 즉, 필드에 추가 필드가 없거나 모든 필드가 final 로 표시되고 불변 인 경우입니다. 이렇게하면 응용 프로그램의 수명 동안 enum 이 메모리를 누설하지 않으며 모든 스레드에서 해당 인스턴스를 사용하는 것이 안전하다는 것을 보장합니다.


열거 형은 Enum 클래스가 수행하기 때문에 SerializableComparable 암시 적으로 구현합니다.

public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable

생성자와 함께 열거 형

enum 은 public 생성자를 가질 수 없습니다. 그러나 private 생성자는 허용 가능합니다 (enum의 생성자는 기본적으로 package-private입니다 ).

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25); // usual names for US coins
    // note that the above parentheses and the constructor arguments match
    private int value;

    Coin(int value) { 
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

열거 형에 대한 인스턴스 수가 제한되어 있으므로 모든 필드를 비공개로 유지하고 getter 메서드를 제공하는 것이 좋습니다.


Enum 을 대신 class 로 구현하면 다음과 같이 보입니다.

public class Coin<T extends Coin<T>> implements Comparable<T>, Serializable{
    public static final Coin PENNY = new Coin(1);
    public static final Coin NICKEL = new Coin(5);
    public static final Coin DIME = new Coin(10);
    public static final Coin QUARTER = new Coin(25);

    private int value;

    private Coin(int value){
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

int p = Coin.NICKEL.getValue(); // the int value will be 5

열거 형 상수는 기술적으로 변경할 수 있으므로 열거 형 상수의 내부 구조를 변경하기 위해 설정자가 추가 될 수 있습니다. 그러나 이것은 매우 나쁜 실행으로 간주되므로 피해야합니다.

가장 좋은 방법은 final Enum 필드를 변경하지 못하게하는 것입니다.

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){ 
        this.value = value;
    }

    ...

}

같은 열거 형에 여러 생성자를 정의 할 수 있습니다. 당신이 할 때, 귀하의 enum 선언에 전달 인자는 호출되는 생성자를 결정합니다 :

public enum Coin {
    PENNY(1, true), NICKEL(5, false), DIME(10), QUARTER(25);

    private final int value;
    private final boolean isCopperColored;

    Coin(int value){
        this(value, false);
    }

    Coin(int value, boolean isCopperColored){ 
        this.value = value;
        this.isCopperColored = isCopperColored;
    }

    ...

}

주 : Enum 클래스가하기 (위해) 때문에, 모든 원시적이 아닌 enum 필드는 Serializable 를 구현할 필요가 있습니다.

메소드 및 정적 블록 사용

열거 형은 모든 클래스와 마찬가지로 메소드를 포함 할 수 있습니다. 이것이 어떻게 작동하는지 보려면 다음과 같이 enum을 선언하십시오.

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
}

열거 형을 반대 방향으로 반환하는 메서드가 있습니다.

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction getOpposite(){
        switch (this){
            case NORTH:
                return SOUTH;               
            case SOUTH:
                return NORTH;                
            case WEST:
                return EAST; 
            case EAST:
                return WEST;  
            default: //This will never happen
                return null;
        }
    }
}

이것은 필드와 정적 이니셜 라이저 블록을 사용하여 더 향상 될 수 있습니다.

public enum Direction {
    NORTH, SOUTH, EAST, WEST;
    
    private Direction opposite;
    
    public Direction getOpposite(){
        return opposite;
    }
    
    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        WEST.opposite = EAST;
        EAST.opposite = WEST;
    }
}

이러한 예에서, 역방향은 전용 인스턴스 필드에 저장된 opposite 정적 처음 초기화되고, Direction 사용된다. (때문에 특별한 경우 NORTH 참조 SOUTH 반대로)을, 우리는 사용할 수 없습니다 생성자와 열거 형 여기 (생성자 NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST) 더 우아한 것 허용 할 oppositefinal 으로 선언되었지만 자기 참조적일 수 있으므로 허용되지 않습니다).

인터페이스 구현

enum 은 미리 컴파일 된 정규식 패턴에 대해 String 입력을 테스트하는 호출 가능 함수이기도합니다.

import java.util.function.Predicate;
import java.util.regex.Pattern;

enum RegEx implements Predicate<String> {
    UPPER("[A-Z]+"), LOWER("[a-z]+"), NUMERIC("[+-]?[0-9]+");

    private final Pattern pattern;

    private RegEx(final String pattern) {
        this.pattern = Pattern.compile(pattern);
    }

    @Override 
    public boolean test(final String input) {
        return this.pattern.matcher(input).matches();
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(RegEx.UPPER.test("ABC"));
        System.out.println(RegEx.LOWER.test("abc"));
        System.out.println(RegEx.NUMERIC.test("+111"));
    }
}

열거 형의 각 멤버는 메서드를 구현할 수도 있습니다.

import java.util.function.Predicate;

enum Acceptor implements Predicate<String> {
    NULL {
        @Override
        public boolean test(String s) { return s == null; }
    },
    EMPTY {
        @Override
        public boolean test(String s) { return s.equals(""); }
    },
    NULL_OR_EMPTY {
        @Override
        public boolean test(String s) { return NULL.test(s) || EMPTY.test(s); }
    };
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Acceptor.NULL.test(null));  // true
        System.out.println(Acceptor.EMPTY.test(""));   // true
        System.out.println(Acceptor.NULL_OR_EMPTY.test(" ")); // false
    }
}

열거 다형 패턴

이 방법의 "확장"세트에 동의 할 필요가있을 때 enum 값, 프로그래머는 통상에서와 같은 다형을 적용 할 수있는 class 를 Where anywere 사용될 인터페이스 만들어 enum 들을 사용한다 :

public interface ExtensibleEnum {
    String name();
}

이 방법으로, 인터페이스에 의해 태그 화 된 ( enum ) 모든 enum 매개 변수로 사용할 수 있으므로 프로그래머는 메소드에서 허용되는 다양한 양의 enum 을 작성할 수 있습니다. 예를 들어 기본 (변경 불가능한) enum 이있는 API에서 유용 할 수 있으며 이러한 API 사용자는 더 많은 값으로 enum 을 "확장"하려고합니다.

기본 enum 값 집합은 다음과 같이 정의 할 수 있습니다.

public enum DefaultValues implements ExtensibleEnum {
    VALUE_ONE, VALUE_TWO;
}

그런 다음 추가 값을 다음과 같이 정의 할 수 있습니다.

public enum ExtendedValues implements ExtensibleEnum {
    VALUE_THREE, VALUE_FOUR;
}

열거 형을 사용하는 방법을 보여주는 샘플 - printEnum() 이 두 enum 모두의 값을 허용하는 방법에 유의하십시오.

private void printEnum(ExtensibleEnum val) {
    System.out.println(val.name());
}  

printEnum(DefaultValues.VALUE_ONE);    // VALUE_ONE
printEnum(DefaultValues.VALUE_TWO);    // VALUE_TWO
printEnum(ExtendedValues.VALUE_THREE); // VALUE_THREE
printEnum(ExtendedValues.VALUE_FOUR);  // VALUE_FOUR

참고 :이 패턴은 다른 열거 형에서 이미 하나의 열거 형에 정의 된 열거 형 값을 재정의하는 것을 방해하지 않습니다. 이러한 enum 값은 다른 인스턴스가됩니다. 또한 switch-on-enum은 실제 enum 아닌 인터페이스이기 때문에 사용할 수 없습니다.

추상 메서드로 열거 형

열거 형은 각 enum 멤버가 구현해야하는 추상 메서드를 정의 할 수 있습니다.

enum Action {
    DODGE {
        public boolean execute(Player player) {
            return player.isAttacking();
        }
    },
    ATTACK {
        public boolean execute(Player player) {
            return player.hasWeapon();
        }
    },
    JUMP {
        public boolean execute(Player player) {
            return player.getCoordinates().equals(new Coordinates(0, 0));
        }
    };

    public abstract boolean execute(Player player);
}

이렇게하면 각 열거 형 멤버가 최상위 수준 정의의 메서드에서 형식을 전환하지 않고도 지정된 작업에 대한 고유 한 동작을 정의 할 수 있습니다.

이 패턴은 다형성 및 / 또는 구현 인터페이스를 사용하여 일반적으로 달성되는 간단한 형태입니다.

enums 문서화

항상 enum 이름이 이해 될 정도로 명확하지는 않습니다. enum 을 문서화하려면 표준 javadoc을 사용하십시오.

/**
 * United States coins
 */
public enum Coins {
    
    /**
     * One-cent coin, commonly known as a penny, 
     * is a unit of currency equaling one-hundredth 
     * of a United States dollar
     */
    PENNY(1),

    /**
     * A nickel is a five-cent coin equaling 
     * five-hundredth of a United States dollar
     */        
    NICKEL(5),

    /**
     * The dime is a ten-cent coin refers to 
     * one tenth of a United States dollar
     */        
    DIME(10),

    /**
     * The quarter is a US coin worth 25 cents, 
     * one-fourth of a United States dollar
     */        
    QUARTER(25);

    private int value;

    Coins(int value){ 
        this.value = value;
    }

    public int getValue(){
        return value;
    }
}

열거 형 값 가져 오기

각 enum 클래스에는 values() 라는 암시 적 정적 메서드가 포함되어 있습니다. 이 메서드는 해당 열거 형의 모든 값을 포함하는 배열을 반환합니다. 이 메서드를 사용하여 값을 반복 할 수 있습니다. 그러나이 메서드는 호출 될 때마다 배열을 반환한다는 점에 유의해야합니다.

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
    
    /**
    * Print out all the values in this enum.
    */
    public static void printAllDays() {
        for(Day day : Day.values()) {
            System.out.println(day.name());
        }
    }
}

Set 가 필요하면 EnumSet.allOf(Day.class) 도 사용할 수 있습니다.

바운드 형식 매개 변수로서의 열거 형

generics를 사용하여 java 클래스를 작성할 때 type 매개 변수가 enum인지 확인하는 것이 가능합니다. 모든 열거 형은 Enum 클래스를 확장하므로 다음 구문을 사용할 수 있습니다.

public class Holder<T extends Enum<T>> {
    public final T value;

    public Holder(T init) {
        this.value = init;
    }
}

이 예에서 T 유형은 열거 형 이어야합니다 .

이름으로 열거 형을 가져옵니다.

열거 형 DayOfWeek 가 있다고 가정 DayOfWeek .

enum DayOfWeek {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}

열거 형은 내장 된 정적 valueOf() 메소드로 컴파일됩니다.이 메소드는 이름으로 상수를 조회하는 데 사용할 수 있습니다.

String dayName = DayOfWeek.SUNDAY.name();
assert dayName.equals("SUNDAY");

DayOfWeek day = DayOfWeek.valueOf(dayName);
assert day == DayOfWeek.SUNDAY;

이것은 또한 동적 enum 유형을 사용하여 가능합니다.

Class<DayOfWeek> enumType = DayOfWeek.class;
DayOfWeek day = Enum.valueOf(enumType, "SUNDAY");
assert day == DayOfWeek.SUNDAY;

지정된 enum에 일치하는 이름을 가지는 정수가없는 경우, 이러한 valueOf() Methods는 모두 IllegalArgumentException 합니다.

Guava 라이브러리는 명시 적 예외 처리를 제거하기 위해 Guava Optional 을 반환하는 도우미 메서드 Enums.getIfPresent() 를 제공합니다.

DayOfWeek defaultDay = DayOfWeek.SUNDAY;
DayOfWeek day = Enums.valueOf(DayOfWeek.class, "INVALID").or(defaultDay);
assert day == DayOfWeek.SUNDAY;

단일 요소 열거 형을 사용하여 싱글 톤 패턴 구현

열거 형 상수는 열거 형을 처음 참조 할 때 인스턴스화됩니다. 따라서 단일 요소 열거 형을 사용하여 Singleton 소프트웨어 디자인 패턴을 구현할 수 있습니다.

public enum Attendant {

    INSTANCE;

    private Attendant() {
        // perform some initialization routine
    }

    public void sayHello() {
        System.out.println("Hello!");
    }
}


public class Main {

    public static void main(String... args) {
        Attendant.INSTANCE.sayHello();// instantiated at this point
    }
}

Joshua Bloch의 "Effective Java"서적에 따르면 단일 요소 열거 형은 싱글 톤을 구현하는 가장 좋은 방법입니다. 이 접근법에는 다음과 같은 장점이 있습니다.

  • 스레드 안전성
  • 단일 인스턴스화의 보장
  • out-of-the-box 직렬화

그리고 인터페이스를 구현 하는 섹션에서 볼 수 있듯이이 싱글 톤은 하나 이상의 인터페이스를 구현할 수도 있습니다.

속성 (필드)이있는 열거 형

우리가 더 많은 정보와 함께 상수 값이 아닌 enum 을 사용하고자 할 때, 우리는 두 개의 enum을 비교할 수 있기를 원합니다.

다음 예제를 고려하십시오.

public enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int value;

    Coin(int value){
        this.value = value;
    }

    public boolean isGreaterThan(Coin other){
        return this.value > other.value;
    }

}

여기서 우리는 그 가치를 나타내는 Coin 이라는 Enum 을 정의했습니다. isGreaterThan 메서드를 사용하면 두 개의 enum 비교할 수 있습니다.

Coin penny = Coin.PENNY;
Coin dime = Coin.DIME;

System.out.println(penny.isGreaterThan(dime)); // prints: false
System.out.println(dime.isGreaterThan(penny)); // prints: true

enum을 String으로 변환하십시오.

때로는 열거 형을 String으로 변환하고 싶을 때가 있습니다. 두 가지 방법이 있습니다.

우리가 가지고 있다고 가정하자.

public enum Fruit {
    APPLE, ORANGE, STRAWBERRY, BANANA, LEMON, GRAPE_FRUIT;
}

그래서 우리는 Fruit.APPLE 같은 것을 어떻게 변환합니까? "APPLE" Fruit.APPLE 은 무엇입니까?


name() 사용하여 변환 name()

name()enumString 표현을 반환하는 enum 의 내부 메서드이며 반환 String 은 열거 형 값이 정의 된 방식을 정확하게 나타냅니다.

예 :

System.out.println(Fruit.BANANA.name());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.name()); // "GRAPE_FRUIT"

toString() 사용하여 변환

toString()기본적 으로 name() 과 동일한 비헤이비어를 갖도록 재정의됩니다.

다만, 개발자toString() 를 오버라이드 (override toString() 해,보다 유저에게 친숙한 String 인쇄 할 가능성이 있습니다

코드를 검사하려면 toString() 사용하지 마십시오. name() 은 훨씬 안정적입니다. 값을 로그 또는 표준 출력 또는 다른 것으로 출력 할 때만 toString() 사용하십시오.

기본적으로:

System.out.println(Fruit.BANANA.toString());      // "BANANA"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "GRAPE_FRUIT"

재정의되는 예

System.out.println(Fruit.BANANA.toString());      // "Banana"
System.out.println(Fruit.GRAPE_FRUIT.toString()); // "Grape Fruit"

열거 상수 특정 본문

에서 enum 특정 상수에 대한 특정 동작을 정의 할 수있다 enum 의 기본 동작에 우선 enum 이 기술은 일정한 특정 기관으로 알려져있다.

세 명의 피아노 학생, John, Ben 및 Luke가 다음과 같이 PianoClass 라는 enum 정의되어 있다고 가정합니다.

    enum PianoClass {
    JOHN, BEN, LUKE;
        public String getSex() {
            return "Male";
        }
        public String getLevel() {
            return "Beginner";
        }
    }

그리고 언젠가 다른 두 명의 학생들이 도착합니다 - 리타와 탐 - 이전의 것과 일치하지 않는 성 (여자)과 레벨 (중급) :

    enum PianoClass2 {
    JOHN, BEN, LUKE, RITA, TOM;
        public String getSex() {
            return "Male"; // issue, Rita is a female
        }
        public String getLevel() {
            return "Beginner"; // issue, Tom is an intermediate student
        }
    }

그래서 새로운 학생을 상수 선언에 단순히 추가하는 것은 다음과 같이 정확하지 않습니다.

PianoClass2 tom = PianoClass2.TOM;
PianoClass2 rita = PianoClass2.RITA;
System.out.println(tom.getLevel()); // prints Beginner -> wrong Tom's not a beginner
System.out.println(rita.getSex()); // prints Male -> wrong Rita's not a male

PianoClass2 기본 동작을 다음과 같이 재정의하는 Rita 및 Tom의 상수에 대해 특정 동작을 정의 할 수 있습니다.

enum PianoClass3 {
    JOHN, BEN, LUKE,
    RITA {
        @Override
        public String getSex() {
            return "Female";
        }
    },
    TOM {
        @Override
        public String getLevel() {
            return "Intermediate";
        }
    };
    public String getSex() {
        return "Male";
    }
    public String getLevel() {
        return "Beginner";
    }
}

지금 Tom의 레벨과 Rita의 섹스는 다음과 같아야합니다.

PianoClass3 tom = PianoClass3.TOM;
PianoClass3 rita = PianoClass3.RITA;
System.out.println(tom.getLevel()); // prints Intermediate
System.out.println(rita.getSex()); // prints Female

콘텐츠 특정 본문을 정의하는 또 다른 방법은 생성자를 사용하는 것입니다. 예를 들면 다음과 같습니다.

enum Friend {
    MAT("Male"),
    JOHN("Male"),
    JANE("Female");
    
    private String gender;

    Friend(String gender) {
        this.gender = gender;
    }

    public String getGender() {
        return this.gender;
    }
}

및 사용 :

Friend mat = Friend.MAT;
Friend john = Friend.JOHN;
Friend jane = Friend.JANE;
System.out.println(mat.getGender());     // Male
System.out.println(john.getGender());    // Male
System.out.println(jane.getGender());    // Female

0 인스턴스 enum

enum Util {
    /* No instances */;

    public static int clamp(int min, int max, int i) {
        return Math.min(Math.max(i, min), max);
    }

    // other utility methods...
}

싱글 톤 (1 인스턴스 클래스)에 enum 사용할 수있는 것처럼 유틸리티 클래스 (0 인스턴스 클래스)에도 사용할 수 있습니다. 그냥 열거 형 상수의 (비어있는) 목록을 a ; .

개인 생성자 와 비교하여 프로 및 토론에 대한 토론을 위해 인스턴스 생성방지하기위한 제로 인스턴스 enum 대 private 생성자에 대한 질문을 참조하십시오.

정적 필드가있는 열거 형

enum 클래스에 정적 필드가 있어야하는 경우 열거 형 값 자체 뒤에 생성된다는 점에 유의하십시오. 즉, 다음 코드는 NullPointerException 을 발생시킵니다.

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers = new HashMap<>();

    private Example(int value) {
        integers.put(this.name(), value);
    }
}

이 문제를 해결할 수있는 방법은 다음과 같습니다.

enum Example {
    ONE(1), TWO(2);

    static Map<String, Integer> integers;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
}

정적 필드를 초기화하지 마십시오.

enum Example {
    ONE(1), TWO(2);

    // after initialisisation integers is null!!
    static Map<String, Integer> integers = null;

    private Example(int value) {
        putValue(this.name(), value);
    }

    private static void putValue(String name, int value) {
        if (integers == null)
            integers = new HashMap<>();
        integers.put(name, value);
    }
    // !!this may lead to null poiner exception!!
    public int getValue(){
        return (Example.integers.get(this.name()));
    }
}

초기화 :

  • enum 값을 만든다.
    • 부작용으로 putValue ()가 호출되어 정수가 초기화됩니다.
  • 정적 값이 설정됩니다.
    • 정수 = null; // 열거 형 뒤에 실행되어 정수의 내용이 손실됩니다.

열거 형 값을 비교 및 ​​포함합니다.

열거 형은 상수 만 포함하고 == 와 직접 비교할 수 있습니다. 따라서, 참조 검사 만 필요하며 .equals 메서드를 사용할 필요가 없습니다. 또한 .equals 잘못 사용되면 NullPointerException 하지만 이는 == check .equals .

enum Day {
    GOOD, AVERAGE, WORST;
}

public class Test {

    public static void main(String[] args) {
        Day day = null;

        if (day.equals(Day.GOOD)) {//NullPointerException!
            System.out.println("Good Day!");
        }

        if (day == Day.GOOD) {//Always use == to compare enum
            System.out.println("Good Day!");
        }

    }
}

EnumSet 클래스를 그룹핑, 보완, 범위 지정하려면 EnumSet 클래스에 다른 메소드가 포함되어 있어야합니다.

  • EnumSet#range : 두 끝점에서 정의한 범위에 따라 열거 형의 하위 집합을 가져 오려면

  • EnumSet#of : 범위가없는 특정 열거 형 집합입니다. 여러 가지 오버로드 of 메소드가 있습니다.

  • EnumSet#complementOf : 메소드 매개 변수에서 제공된 enum 값을 보완하는 enum 세트

    enum Page {
       A1, A2, A3, A4, A5, A6, A7, A8, A9, A10
    }
    
    public class Test {
    
      public static void main(String[] args) {
          EnumSet<Page> range = EnumSet.range(Page.A1, Page.A5);
    
          if (range.contains(Page.A4)) {
              System.out.println("Range contains A4");
          }
    
          EnumSet<Page> of = EnumSet.of(Page.A1, Page.A5, Page.A3);
    
          if (of.contains(Page.A1)) {
              System.out.println("Of contains A1");
          }
      }
    }
    


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow