조슈아 블로크 님의 "Effective Java" 책을 정리한 포스팅 입니다.
1. int 상수 대신 열거 타입을 사용하라
정수 열거 타입 vs Enum
항목 | 정수 열거 타입 (int enum pattern) | Enum (자바 열거 타입) |
타입 안정성 | ❌ 잘못된 값도 전달될 수 있음 | ✅ 컴파일 타임에 잘못된 값 차단 가능 |
이름 공간 | ❌ 상수 이름이 전역으로 퍼짐 | ✅ 열거 타입 별도로 이름공간을 가짐 |
유지보수 | 상수 값 변경 시, 모든 클라이언트 코드 수정 필요 | 상수 변경이 있어도 클라이언트 코드는 영향 거의 없음 |
순회 (iterability) | 수동 작업 필요 (별도 배열 등) | 간단하게 순회 가능 (Enum.values()) |
상수 개수 파악 | 어렵거나 불명확함 | 간단하게 확인 가능 (values().length) |
필드/메서드 추가 가능 여부 | ❌ 단순 int 값일 뿐 | ✅ 필드, 메서드, 생성자 등 클래스 수준 기능 활용 가능 |
인터페이스 구현 가능 여부 | ❌ | ✅ 각 열거 상수가 특정 동작을 구현하도록 만들 수 있음 |
확장성 (상속 등) | ❌ 단순 상수 집합일 뿐 | ❌ 열거 타입의 생성자는 기본적으로 private임 |
보안 및 안정성 | 낮음 – 정수 값이 예상 밖의 결과 유발 가능 | 높음 – 엄격한 타입 제한과 불변성 보장 |
예시) 정수 열거 타입
더보기
public final class IntEnumPattern {
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;
}
예시) Enum
더보기
// 인터페이스 정의
interface Displayable {
String display();
}
// Enum 정의
enum Fruit implements Displayable {
APPLE("Red", 95) {
@Override
public String specialFeature() {
return "Keeps doctors away!";
}
},
ORANGE("Orange", 62) {
@Override
public String specialFeature() {
return "Rich in Vitamin C!";
}
},
BANANA("Yellow", 105) {
@Override
public String specialFeature() {
return "Great for energy boost!";
}
};
// 필드
private final String color;
private final int calories;
// 생성자
Fruit(String color, int calories) {
this.color = color;
this.calories = calories;
}
// 일반 메서드
public String getColor() { return color; }
public int getCalories() { return calories; }
// 추상 메서드: 각 열거 상수가 고유한 동작을 제공
public abstract String specialFeature();
// 인터페이스 메서드 구현
@Override
public String display() {
return String.format("%s: Color=%s, Calories=%d", this.name(), color, calories);
}
}
2. ordinal 메서드 대신 인스턴스 필드를 사용하라
ordinal 메서드
- 열거 타입에서 몇번째 인스턴스인지를 반환하는 메서드
- 열거타입 기반의 범용 자료구조에 쓸 목적으로 설계됨
- 유지보수 하기 어려움
ordinal 관련 값은 인스턴스 필드에 저장하기
public enum Ensemble {
SOLO(1), DUET(2);
private final int numberOfMusicians;
}
3. 비트 필드 대신 EnumSet을 사용하라
비트 필드
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 0001
public static final int STYLE_ITALIC = 1 << 1; // 0010
public static final int STYLE_UNDERLINE = 1 << 2; // 0100
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 1000
public void applyStyles(int styles) {
System.out.println("Applying styles: " + styles);
}
public static void main(String[] args) {
Text text = new Text();
text.applyStyles(STYLE_BOLD | STYLE_ITALIC); // 비트 연산 사용
}
}
- 여러 상수 값을 조합해서 사용할 수 있도록 비트를 활용한 방식
단점
- 타입 안전성 부족
- 가독성 낮음
- 확장성 부족
EnumSet
public class Text {
public enum Style {
BOLD, ITALIC, UNDERLINE, STRIKETHROUGH
}
public void applyStyles(Set<Style> styles) {
System.out.println("Applying styles: " + styles);
}
public static void main(String[] args) {
Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC)); // EnumSet 사용
}
}
- 열거 타입 상수의 값으로 구성된 집합을 효과적으로 표현해줌
- Set 인터페이스 구현
- 내부는 비트 벡터로 구현됨
장점
- 타입 안전
'Java' 카테고리의 다른 글
[Effective Java] 6-3. 열거 타입과 애노테이션 (0) | 2024.12.31 |
---|---|
[Effective Java] 6-2. 열거 타입과 애노테이션 (0) | 2024.12.31 |
[Effective Java] 5-3. 제네릭: 고려 사항 (1) | 2024.12.30 |
[Effective Java] 5-2. 제네릭: 권고 사항 (3) | 2024.12.28 |
[Effective Java] 5-1. 제네릭: 제한 사항 (1) | 2024.12.27 |