Java | Enum (열거형)

Lumpen·2025년 4월 23일
0

Java

목록 보기
28/38

문자열과 타입 안정성

문자열에 따른 특정 조건이 있을 때
단순히 문자열을 조건문으로 구분하여 코드를 실행한다면
오타가 발생하기 쉽고, 유효하지 않은 값이 입력될 수 있다
또한 코드 복잡도도 증가한다

  • 타입 안정성 부족(값의 제한 부족): 오타 발생, 유효하지 않은 값 입력 가능
  • 데이터 일관성 부족: 대소문자 구분 등 다양한 형식으로 입력될 수 있다
  • 컴파일 시 오류 감지 불가: 런타임에서만 위 문제들이 발견되기 때문에 디버깅이 어렵다

대안으로 문자열 상수 값으로 갖는 객체를 사용할 수 있다
보기에는 좋지만 위 문제를 근본적으로 해결할 수는 없다

매개변수에서 해당 객체 내의 값이 아닌 String 을 입력한다면
역시나 위 문제는 그대로 발생한다

타입 안전 열거형 패턴

위 문제를 해결하기 위해 오랜기간 고민 후 나온 결과가
타입 안전 열거형 패턴이다

public class Grade {
	public static final Grade BASIC = new Grade();
	public static final Grade GOLD = new Grade();
	public static final Grade DIAMOND = new Grade();
}
  1. 등급을 다루는 클래스를 만든 후 각 등급별 상수를 선언한다
  2. 각 상수마다 별도의 인스턴스를 생성, 생성한 인스턴스를 대입한다
    상수 선언을 위해 static 으로 메서드 영역에 선언, final 로 참조값을 변경할 수 없게 한다
  • 각 상수는 모두 Grade 타입 기반으로 만들었기 떄문에 getClass() 결과는 모두 Grade 다
  • 각 상수는 모두 각기 다른 Grade 의 인스턴스를 참조하기 떄문에 참조 값이 다르다
  • static 이므로 애플리케이션 로딩 시점에 Grade 인스턴스가 각각 생성된다
public class DiscountService {
	public int discount(Grade grade, int price) {
    	int discountPercent = 0;
        
        if (grade == Grade.BASIC) {
        	// basic
        } else if (grade == Grade.GOLD) {
        	// gold
        } else if (grade == Grade.DIAMOND) {
        	// diamon
        } else {
        	System.out.println('x')
        }
    }
    return price * discountPercent / 100;
}
  • 매개변수로 Grade 클래스를 사용
  • 값 비교 시 각 등급별 인스턴스의 참조가 다르기 때문에 == 을 사용하여 참조값 비교를 할 수 있다

이렇게 하더라도 Grade 인스턴스를 새로 생성해서 인자로 주게될 경우
앞선 문제가 발생할 수 있기 때문에
Grade 의 생성자를 private 으로 설정하여
외부에서 인스턴스를 생성할 수 없도록 한다

public class Grade {
	public static final Grade BASIC = new Grade();
	public static final Grade GOLD = new Grade();
	public static final Grade DIAMOND = new Grade();
    
    private Grade() {} // private 생성자 추가
}

타입 안전 열거형 패턴의 장점

  • 타입 안정성 향상: 정해진 객체만 사용할 수 있기 떄문에, 잘못된 값을 입력할 수 없다
  • 제한된 인스턴스 생성으로 미리 정의된 값을 사용할 수 있다
  • 데이터 일관성: 정해진 객체만 사용하므로 일관성이 보장된다
  • 잘못된 갑이 할당되거나 사용된다면 컴파일 시점에 방지할 수 있다

단점

타입 안전 열거형 패턴을 구현하기 위해 코드량이 많아지고
private 생성자를 추가하는 등 유의해야 하는 부분들이 있다

열거형 - Enum Type

타입 안전 열거형 패턴을 쉽게 작성할 수 있도록
Enum Type 을 지원한다
열거형은 상수들의 집합을 정의하는 것을 의미하며
프로그래밍에서는 이러한 상수들을 사용해 코드 내 미리 정의된 값들의 집합을 나타낸다

public enum Grade {
	BASIC, GOLD, DIAMOND
}

열거형 정의 시에는 enum 을 사용하여
원하는 상수들의 이름을 나열하면 된다

위 코드는 타입 안전 열거형 패턴의 class 와 같은 기능을 한다

public class Grade {
	public static final Grade BASIC = new Grade();
	public static final Grade GOLD = new Grade();
	public static final Grade DIAMOND = new Grade();
    
    private Grade() {} // private 생성자 추가
}
  • 열거형도 클래스다
  • 묵시적으로 java.lang.Enum 을 상속 받는다 (떄문에 다른 클래스를 상속 받을 수 없다)
  • 외부에서 임의로 생성할 수 없다 (private 생성자)
  • 인터페이스를 구현할 수 있다
  • 열거형에 추상 메서드를 선언하고 구현할 수 있다 (익명 클래스와 같은 방식 사용)

enum 을 사용하면 class 를 사용해
각 상수의 인스턴스를 생성하는 것과 정확히 동일한 결과를 가져온다

열거형은 toString() 이 자신의 이름을 참조하도록 오버라이딩 되어있기 때문에
따로 함수를 만들어 확인 가능하다

System.out.println(Grade.BASIC.getClass());
System.out.println(refValue(Grade.BASIC));


private static String refValue(Object grade) {
	return Integer.toHexString(System.identityHashCode(grade));
}

열거형을 switch 문에서 사용할 수 있다

열거형의 장점

  • 타입 안정성 향상
  • 간결성 및 일관성
  • 확장성

열거형을 사용하는 경우 static import 를 사용하여 간결한 코드를 만들 수 있다
-> 상수이기 때문에 가능

열거형 - 주요 메서드

모든 열거형은 java.lang.Enum 클래스를 상속받는다

	Grade[] values = Grade.values(); // 모든 ENUM 반환
    for (Grade value: values) {
    	System.out.println(value.name());
    }
    
    // String -> ENUM 변환 (이미 정의된 ENUM 상수에 대해서만 가능)
    String input = "GOLD";
    Grade gold = Grade.valueOf(input);

주의

ENUM 의 ordinal() 메서드는 사용하지 않는다
ordinal() 사용 중간에 상수 선언 위치가 변경되면
전체 상수 위치가 변경될 수 있다

열거형은 각 상수의 값을 순서대로
0, 1, 2.. 등으로 로 저장하기 때문에
상수 선언이 중간에 추가될 경우
기존에 사용하던 상수의 값이 변경되어도
정상적으로 실행된다
따라서 기존 코드의 모든 값이 다른 것으로 변경된다

열거형의 사용

public enum Grade {
	BASIC(10), GOLD(20), DIAMOND(30); // 생성자 호출
    
    private final int discountPercent;
    
    Grade(int discountPercent) { // 생성자
    	this.discountPercent = discountPercent;
    }
    
    // 열거형도 클래스이므로 메서드 추가 가능
    public int getDiscountPercent() {
    	return discountPercent;
    }
    
    public int discount(int price) {
    	return price * discountPercent / 100;
    }
}
profile
떠돌이 생활을 하는. 실업자, 부랑 생활을 하는

0개의 댓글