작성자 주: 저는 C/C++ 개발을 할 때 비트 필드 구현을 많이 사용했습니다. 하나의 int/long 타입 정수에 여러 개의 flag를 넣을 수 있어 많이 사용됩니다. 보통 or 연산으로 합치고, and로 원하는 flag를 가져오는 식으로 사용합니다.
아래 예제는 리눅스 커널의 mman.h 파일에 있는 flag의 일부입니다.
#ifdef __USE_MISC
# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */
# define MAP_DENYWRITE 0x00800 /* ETXTBSY */
# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */
# define MAP_LOCKED 0x02000 /* Lock the mapping. */
# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */
# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */
# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */
# define MAP_STACK 0x20000 /* Allocation is for a stack. */
#endif
비트 필드의 단점은 정수 열거 패턴의 단점을 그대로 지닙니다. (ITEM 34)
참고하기 :
- 이 정수 열거 패턴은 type safe를 보장할 수 없다.(APPLE_FUJI==ORANGE_NAVEL의 결과는?)
- 개발자의 의도는 APPLE과 ORANGE를 분리하여 사용하고자 했을 것이다. namespace를 컴파일러가 아닌 개발자에게 맡겨버렸다.
- 컴파일하면 클라이언트 파일에 그대로 새겨진다.
- 상수의 값을 바꾸려면 다시 컴파일해야 했다.
- 디버깅할 때 의미나 문자열이 아닌 숫자로 보이기 때문에 디버그하기 힘들다.
- 순회를 하기 힘들다. 해당 가상의 namespace 안에 몇 개의 상수가 있을까?
또한
- 최대 몇 비트를 사용할 것인지 int나 long으로 적절히 선택해야 하며, 이미 확정되어 구현된 이후로는 의존성 때문에 수정이 매우매우 힘들다. 64bit가 최대인 한계도 존재한다.
대안 : EnumSet 클래스 사용하기
EnumSet의 특징은
- Set 인터페이스를 구현했다.
- 타입 안전하다.
- 원소가 64개 이하인 경우 비트 벡터 구현을 이용하여 비트 필드 수준의 성능을 보여준다.
- 직접 비트를 다룰 때의 오류를 걱정하지 않아도 된다.
public class Text {
public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}
// 어떤 Set을 넘겨도 되나, EnumSet이 가장 좋다.
public void applyStyles(Set<Style> styles) {
System.out.printf("Applying styles %s to text%n",
Objects.requireNonNull(styles));
}
// 사용 예
public static void main(String[] args) {
Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
}
}
불변 EnumSet을 만들 수 없다는 단점이 있지만 비트 필드를 사용할 이유가 없어졌다. EnumSet을 활용하자.
'IT > Effective Java' 카테고리의 다른 글
[Effective Java 3/E] ITEM 38. 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라. (0) | 2021.03.28 |
---|---|
[Effective Java 3/E] ITEM 37. ordinal 인덱싱 대신 EnumMap을 사용하라 (0) | 2021.03.28 |
[Effective Java 3/E] ITEM 35. ordinal 메서드 대신 인스턴스 필드를 사용하라 (0) | 2021.03.28 |
[Effective Java 3/E] ITEM 34. int 상수 대신 열거 타입을 사용하라 (0) | 2021.03.28 |
[Effective Java 3/E] 3장 모든 객체의 공통 메서드 (0) | 2021.02.28 |
댓글