어떤 상태를 저장하기 위해서 변수를 사용할때, 메모리를 차지하는 다른 타입들보다는 최소 단위인 bit단위로 상태를 관리할 수 있습니다.
1(1) | 2(10) = 3(11)
public class Text {
public static final int STYLE_BOLD = 1 << 0;
public static final int STYLE_ITALIC = 1 << 1;
public static final int STYLE_UNDERLINE = 1 << 2;
public static final int STYLE_STRIKETHROUGH = 1 << 3;
// 매개변수 styles는 0개 이상의 STYLE_ 상수를 비트별 OR한 값이다.
public void applyStyles(int styles) { // something }
}
```java
// 여러 상수를 비트 연산자 OR를 사용해 모아서 만들어진 하나의 집합 -> 비트 필드
text.applyStyles(Text.STYLE_BOLD | Text.STYLE_ITALIC);
// Text.STYLE_BOLD | Text.STYLE_ITALIC -> 3
API에 사용할 때는 최대 몇 비트가 필요한지 미리 예측해야 합니다. : 보통은 int나 long 사용
대신 java.util.EnumSet을 사용하자.
왜?
Set 인터페이스를 완벽히 구현
type safety
다른 Set구현체와 함께 사용 가능
EnumSet의 내부는 비트 벡터로 구현되었습니다.
원소가 64개 이하일 때, EnumSet 전체를 long 하나로 표현한다면 비트 필드와 성능에 비견됩니다.
비트 연산을 사용할 때 흔히 만나는 오류들에서 해방시켜줍니다.
EnumSet이 난해한 작업은 모두 처리하기 때문
EnumSet을 사용한 Text 클래스는 어떨까요?
public class Text {
public enum Style { BOLD, ITALIC, INDERLINE, STRIKETHROUGH }
// 깔끔하고 안전합니다.
// 어떤 Set을 넘겨도 되나, EnumSet이 가장 좋습니다.
public void applyStyles(Set<Style> styles) { // something }
}
applyStyles 메소드가 Set<Style>을 받은 이유는, 매개변수에 어떤 Set 구현체로 넘어올지 모르기 때문입니다.
이럴 때 인터페이스로 받는게 일반적으로 좋은 습관입니다. (#64)
정리하자면
EnumSet은 비트 필드 수준의 명료함과 성능을 제공합니다.
enum 타입의 장점도 제공합니다.
하지만 유일한 단점은, 아직 자바9에서는 불변 EnumSet을 만들 수 없습니다.
방지책으로 Collections.unmodifiableSet를 사용하면 됩니다.
Set immutableEnumSet = Collections.unmodifiableSet(EnumSet.of(Text.Style.BOLD, Text.Style.ITALIC));
immutableEnumSet.add(Text.Style.INDERLINE); // java.lang.UnsupportedOperationException
// java.util.Collections > UnmodifiableSet
public boolean add(E e) { throw new UnsupportedOperationException(); }
public boolean remove(Object o) { throw new UnsupportedOperationException(); }
public boolean addAll(Collection<? extends E> coll) { throw new UnsupportedOperationException(); }
public boolean removeAll(Collection<?> coll) { throw new UnsupportedOperationException(); }
public boolean retainAll(Collection<?> coll) { throw new UnsupportedOperationException(); }
public void clear() { throw new UnsupportedOperationException(); }
비트 필드(bit field)란?
비트 연산자는?
그럼 비트 필드는?
1(1) | 2(10) = 3(11)
// 매개변수 styles는 0개 이상의 STYLE_ 상수를 비트별 OR한 값이다. public void applyStyles(int styles) { // something } }
장점은?
하지만 단점은?
대신
java.util.EnumSet
을 사용하자.Set
인터페이스를 완벽히 구현Set
구현체와 함께 사용 가능EnumSet
의 내부는 비트 벡터로 구현되었습니다.EnumSet을 사용한
Text
클래스는 어떨까요?applyStyles
메소드가Set<Style>
을 받은 이유는, 매개변수에 어떤Set
구현체로 넘어올지 모르기 때문입니다.정리하자면
EnumSet
은 비트 필드 수준의 명료함과 성능을 제공합니다.Collections.unmodifiableSet
를 사용하면 됩니다.