본문 바로가기
JAVA/Effective Java

item 36. 비트 필드 대신 EnumSet을 사용하라

by Garonguri 2022. 5. 31.
728x90

과거 ..

열거 값들이 집합으로 사용되는 경우 비트 마스킹을 활용한 정수 열거 패턴을 사용하곤 했다.

public class Text {
    public static final int STYLE_BOLD = 1 << 0; // 1st : 1 (0001)
    public static final int STYLE_ITALIC = 1 << 1; // 2nd : 2 (0010)
    public static final int STYLE_UNDERLINE = 1 << 2; // 3rd : 4 (0011)
    public static final int STYLE_STRIKETHROUGH = 1 << 3; // 4th : 8 (0100)

    public void applyStyles(int styles) { //...}
    }
}
  • 클래스 안에 상수로 표현할 때 shift연산을 해서  비트로 표현하는 것. 이를 통해 상수 값을 비트로 표현할 수 있다.
  • 또한, 아래와 같이 bit값으로 표현된 상수들을 OR연산해 합집합이나 교집합으로 표현할 수도 있다.
text.applyStyles(STYLE_BOLD | STYLE_ITALIC); // 1st, 2nd를 OR 연산함. 01 | 10 -> 11 (3)

 

왜 쓰면 안될까?

  • 끔찍한(?) 정수 열거 패턴의 단점을 그대로 지니고 있다.
  • 여기에 더해 비트 필드 값이 출력될 경우 더 해석하기 어렵다는 특징을 가지고 있다.
  • 비트 필드 하나에 있는 모든 원소를 순회하는 것도 까다롭다.
  • 최대 몇 비트가 필요한지 API작성 시 미리 예측하여 int/long 등 적절한 타입을 선택해야 한다.
  • API를 수정하지 않고는 비트를 늘릴 수 없다.

대안은?

java.util 의 EnumSet 클래스 사용

 

장점!

  • Enum 상수 값으로 구성된 집합을 효과적으로 표현하며
  • Set 인터페이스도 완벽히 구현할 수 있다.
  • 타입 안전하다.
  • 다른 어떤 Set 구현체와도 함께 사용할 수 있다.

 

EnunmSet의 내부는 비트 벡터로 구현되어 있다. => 원소가 64개 이하라면 long하나로 표현할 수 있다. 비트 필드와 비견된 성능을 보여준다.

(낫고 못할 것이 없이 정도가 서로 비슷하게 견주어지다. 앞서거나 뒤서지 않고 어깨를 나란히 한다는 뜻) ㅎ

 

그러나 비트를 직접 다룰때 겪는 오류는 일어나지 않는다. EnumSet이 난해한 작업을 처리해주기 때문이다.

게다가, 정보도 그대로 가지고 있고 비트필드를 사용하면 할 수 없었던 순회도 할 수 있다.

    public static void main(String[] args) {
        //of method : EnumSet이 제공하는 정적 팩터리 메소드
        Text.applyStyles(EnumSet.of(Text.Style.BOLD, Text.Style.ITALIC, Text.Style.UNDERLINE));
    }


    public class Text {
        public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }

		"클라이언트가 다른 Set 구현체를 넘기더라도 처리할 수 있게
        EnumSet보단 Set<Style>을 사용하는 것이 좋은 습관이다."
        public static void applyStyles(Set<Style> styles) {
            //...
        }
    }

 

핵심 정리

열거할 수 있는 타입을 한데 모아 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다.
비트 필드 사용하지 마!

EnumSet은 비트 필드 수준의 성능을 제공하고 열거 타입의 장점까지 가져갈 수 있는 멋진 클래스다. 얘를 사용해라.

아직까지 불변 EnumSet을 만들 수는 없지만, 괜찮다.
일단 Collections-unmodifiableSet으로 얘를 감싸서 사용하고 언젠간 자바가 개발해 줄 것이라 믿자.

 

 

 

 

728x90

댓글