본문 바로가기

Java

[Effective Java][아이템35] ordinal 메서드를 잘못사용한 사례와 해결방법

아이템35. ordinal 메서드 대신 인스턴스 필드를 사용하라

 

 

enum에서 제공하는 ordinal메서드를 프로그래머가 잘못사용하는 경우가 많다.

 

WHY: ordinal 메서드의 개념을 착각하기 쉽다.

enum에서 제공하는 ordinal메서드enum 상수가 그 열거타입에서 몇 번째 위치인지를 알려주는 메서드이다.

때문에, enum상수와 연결된 정숫값이 필요하면 쉽게 사용하려고 한다.

 

.

.

눈치 챘겠지만 이는 좋은 방법이 아니다.

 

 

 

예시1) [BAD] enum에 oridnal()을 사용하여 합주자 수를 구하는 예시

public enum Ensemble {
    SOLO, DUET, TRIO, QUARTET, QUINTET,
    SEXTET, SEPTET, OCTET, NONET, DECTET;


	// oridnal을 사용해 합주 종류별로 합주자 수를 구한다. -> 똑똑한 방법처럼 보인다!
    public int numberOfMusicians() { return ordinal()+1; }

}

간단하게 구현한거 같은데 단점이 무엇일까??

 

 

given

위 상황

 

when

상수 선언 순서를 바꾸는 순간

 

then!!

1. numberOfMusicians가 오동작한다.

DUET <-> TRIO로 선언 순서를 바꾸면, DUET = 3, TRIO = 2로 잘못된 결과를 가져온다.

 

2. 이미 사용중인 정수와 값이 같은 상수는 추가할 방법이 없다.

위 예시에서는 8중주(octet)상수가 있으니 똑같이 8명이 연주하는 복4중주(double quater)를 추가할 수 없다. 

 

3. 값을 중간에 비워둘 수도 없다. 

위 예시에서 12명이 연주하는 상수를 추가하려면 있지도 않은 11명 연주를 더미값으로 추가해야한다.

 


WHAT: ordinal 메서드

enum 상수가 그 열거타입에서 몇 번째 위치인지를 알려주는 메서드

EnumSet과 EnumMap 같이 열거타입 기반의 범용 자료구조에서 사용되고 있다.

개발자는 대부분의 경우 이 메서드를 사용할 일이 없음.

 


HOW: enum상수에 연결된 값은 ordinal메서드로 얻지 말고, 인스턴스 필드로 추가하자!

예시2) [GOOD] enum - 인스턴스 필드에 데이터를 저장하는 방식

public enum Ensemble {

    SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
    SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
    NONET(9), DECTET(10), TRIPLE_QUARTET(12);

    private final int numberOfMusicians;
    Ensemble(int size) { this.numberOfMusicians = size; }
    public int numberOfMusicians() { return numberOfMusicians; }


}