공부/Java

[Java] Enum values 조회 (Baeldung)

leejinwoo1126 2023. 7. 26. 13:59
반응형

 

 


1. Enum Month 클래스 생성 

- 각 Month 인스턴스는 codenumber 값을 가짐

- Enum Constructor(생성자)는 기본적으로 private 로 생략가능하다.

public enum Month {
    JANUARY("Jan", 1),
    FEBRUARY("Feb", 2),
    MARCH("Mar", 3),
    APRIL("Apr", 4),
    MAY("May", 5),
    JUNE("Jun", 6),
    JULY("Jul", 7),
    AUGUST("Aug", 7),
    SEPTEMBER("Sept", 7),
    OCTOBER("Oct", 10),
    NOVEMBER("Nov", 11),
    DECEMBER("Dec", 12);

    private final String code;
    private final int number;

    Month(String code, int number) {
        this.code = code;
        this.number = number;
    }

    public String getCode() {
        return code;
    }

    public int getNumber() {
        return number;
    }
}

 

참고.

enum은 각각 자기자신을 인스턴스화한 객체를 가지게 되는데, 아래와 같이 정적인 상수 클래스가 선언 되었다고 이해할 수 있다

public enum Month {
    public static final Month JANUARY = new Month("Jan", 1);
    // ...
    public static final Month DECEMBER = new Month("Dec", 2);

    private final String code;
    private final int number;

    Month(String code, int number) {
        this.code = code;
        this.number = number;
    }

    public String getCode() {
        return code;
    }

    public int getNumber() {
        return number;
    }
}

 

자바 컴파일을 해보게 되면 아래와 같은 형태로 확인된다

$ javac Month.java
$ javap Month.class
public final class {패캐지경로}.Month extends java.lang.Enum<{패키지경로}.Month> {
  public static final {패키지경로}.Month JANUARY;
  public static final {패키지경로}.Month FEBRUARY;
  public static final {패키지경로}.Month MARCH;
  public static final {패키지경로}.Month APRIL;
  public static final {패키지경로}.Month MAY;
  public static final {패키지경로}.Month JUNE;
  public static final {패키지경로}.Month JULY;
  public static final {패키지경로}.Month AUGUST;
  public static final {패키지경로}.Month SEPTEMBER;
  public static final {패키지경로}.Month OCTOBER;
  public static final {패키지경로}.Month NOVEMBER;
  public static final {패키지경로}.Month DECEMBER;
  public static basic.function.Month[] values();
  public static basic.function.Month valueOf(java.lang.String);
  public java.lang.String getCode();
  public int getNumber();
  static {};
}

 

2. name() 활용하여 Enum 찾기 

- Enum 추상 클래스 통해 name() method가 기본적으로 제공된다

- Enum 클래스에서 선언한 열거 객체의 명칭을 문자열로 반환

- Java 버전이 지원할 경우 현대적인 stream API 사용 권장

 

2-1. forEach 활용

static Month[] values() {
	return Month.values();
}

static Month findByName(String name) {
	Month result = null;
    for(Month m : values()) {
       if(m.name().equalsIgnoreCase(name)) { // equalsIgnoreCase (String.class)
          return = m;
          break;
       }
    }
    return result;
}

@DisplayName("올바른 name을 인자로 전달할 때, findByName 통해 Month 상수 객체가 반환된다")
@Test
void whenValidDirectionNameProvided_thenDirectionIsFound() {
    // given
    String givenName = "december";

    // when
    Direction result = findByName(givenName);

    // then
    Assertions.assertThat(result).isEqualTo(Month.DECEMBER); // OK
}

 

2-2. stream API 활용 

조회시 filter에 해당하는 첫 값을 리턴하고 없으면 IllegalArgumentException 을 던진다

static Month[] values() {
	return Month.values();
}

static Month findByName(String name) {
    return Arrays.stream(values()).filter(month -> month.name().equalsIgnoreCase(name))
            .findFirst().orElseThrow(IllegalArgumentException::new);
}

@DisplayName("올바른 name을 인자로 전달할 때, findByName 통해 Month 상수 객체가 반환된다")
@Test
void whenValidDirectionNameProvided_thenDirectionIsFound() {
    // given
    String givenName = "December";

    // when
    Direction result = findByName(givenName);

    // then
    Assertions.assertThat(result).isEqualTo(Month.DECEMBER); // OK
}

@DisplayName("틀린 name이 인자로 주어졌을 때, findByname 실행시 IllegalArgumentException 예외를 던진다")
@Test
void findByNameException() {
    // given
    String givenName = "holiday";

    // when
    // then
    Assertions.assertThatThrownBy(() -> findByName(givenName))
            .isInstanceOf(IllegalArgumentException.class); // Ok
}

- equalsIgnoreCase()  : 대소문자 구분 x

 

3. 직접 선언한 String 필드 사용 (String code)하여 Enum 찾기 

- name()의 경우 추상클래스 enum에 선언되었지만, 사용자 정의 필드의 경우 getter method를 생성해서 사용

- 내용은 name()과 동일

- Java 버전이 지원할 경우 현대적인 stream API 사용 권장

 

3-1. forEach 활용

static Month findByCode(String code) {
    Month month = null;
    for(Month m : values()) {
        if(m.getCode().equalsIgnoreCase(code)) {
            month = m;
            break;
        }
    }
    
    return month;
}

@DisplayName("code 값이 존재하는 경우 Month 객체 반환를 반환한다")
@Test
void searchByCode() {
    // given
    String givenCode = "nov";

    // when
    Month result = findByCode(givenCode);

    // then
    assertThat(result).isEqualTo(Month.NOVEMBER); // Ok
}

 

3-2. stream API 활용

static Month findByCode(String code) {
    return Arrays.stream(values())
            .filter(month -> month.getCode().equalsIgnoreCase(code))
            .findFirst()
            .orElseThrow(IllegalArgumentException::new);
}

@DisplayName("code 값이 존재하는 경우 Month 객체 반환를 반환한다")
@Test
void searchByCode() {
    // given
    String givenCode = "nov";

    // when
    Month result = findByCode(givenCode);

    // then
    assertThat(result).isEqualTo(Month.NOVEMBER); // Ok
}

@DisplayName("없는 Month 코드 조회할 경우, findByCode 실행시 IllegalArgumentException 던진다")
@Test
void givenMonthCode_whenCodeNotFound_thenThrowIllegalArgumentException() {
    // given
    String givenEmptyCode = "empty";

    // when
    // then
    assertThatThrownBy(() -> findByCode(givenEmptyCode))
            .isInstanceOf(IllegalArgumentException.class); // Ok
}

 

4. 직접 선언한 int 필드 사용(int number)하여 Enum 찾기 

- 위와 동일하고 primitive type 사용하기 때문에 filter/조건문에서 비교 연산자로 대체됨

 

4-1. forEach 활용

static Month findByNumber(int monthNumber) {
    Month result = null;

    for(Month m : values()) {
        if(m.getNumber() == monthNumber) {
            result = m;
            break;
        }
    }

    return result;
}

@DisplayName("number 값이 존재하는 경우, findByNumber 실행시 Month 객체 반환를 반환한다")
@Test
void searchByNumber() {
    // given
    int givenMonthNumber = 12;

    // when
    Month result = findByNumber(givenMonthNumber);

    // then
    assertThat(result).isEqualTo(Month.DECEMBER);
}

 

4-2. stream API 활용 

static Month findByNumber(int monthNumber) {
    return Arrays.stream(values()).filter(month -> month.getNumber() == monthNumber).findFirst()
            .orElseThrow(IllegalArgumentException::new);
}

@DisplayName("number 값이 존재하는 경우 Month 객체 반환를 반환한다")
@Test
void searchByNumber() {
    // given
    int givenMonthNumber = 12;

    // when
    Month result = findByNumber(givenMonthNumber);

    // then
    assertThat(result).isEqualTo(Month.DECEMBER);
}

@DisplayName("없는 number 의 경우, findByNumber 실행시 IllegalArgumentException 던진다")
@Test
void givenMonthNumber_whenCodeNotFound_thenThrowIllegalArgumentException() {
    // given
    int givenEmptyMonthNumber = 13;

    // when
    // then
    assertThatThrownBy(() -> findByNumber(givenEmptyMonthNumber))
            .isInstanceOf(IllegalArgumentException.class);
}

 


참고 & 출처 

https://www.baeldung.com/java-search-enum-values

반응형