Java - Enum

설명

Enum 은 Enumeration의 약자입니다.

Enumeration 은 "열거, 목록 "이라는 뜻을 가지고 있으며, 보통 한글로는 열거형이라고 부릅니다.

즉, 열거형은 요소, 멤버라 불리는 명명된 값의 집합을 이루는 자료형입니다.

어렵게 생각할 필요 없이 상수 데이터들의 집합으로 치부하면 됩니다.

 

Enum 은 월,화,수,목.. 요일이나 봄, 여름, 가을, 겨울 등 이와 같이 정해져 있는 한정된 데이터 묶음을 열거형 타입인 Enum으로 묶어주면 보다 구조적으로 프로그래밍할 수 있습니다.

 

Enum의 기본 구조

1. enum 명은 클래스와 같이 첫 문자를 대문자로 하고 나머지는 소문자로 구성합니다.

2. 관례적으로, 열거 상수는 모두 대문자로 작성합니다.

3. 열거 상수가 여러 단어로 구성될 경우, 단어 사이를 밑줄 ( _ )로 연결합니다.

enum Day {
  MONDAY,TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

enum Month{
	JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, 
	AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;
}

 

JAVA의 enum 은 인터페이스와 같이 독립된 특수한 클래스로 구분합니다.

즉, 일종의 객체이기 때문에 힙(heap) 메모리에 저장되며 각 enum 상수들은 별개의 메모리 주소값을 가짐으로써 완벽히 독립된 상수를 구성할 수 있습니다.

 

변수 선언

Enum 타입 객체도 하나의 데이터 타입이므로 변수를 선언하고 사용하면 됩니다.

// 열거타입 변수 = 열거타입.열거상수;
Week monday = Week.MONDAY;
Week sunday = Week.SUNDAY;
enum 타입은 primitive 타입이 아닌 reference 타입으로 분류되며, 힙 영역에 저장합니다.

 

따라서 다음과 같이 같은 enum 타입 변수끼리 같은 상수 데이터를 바라봄으로써 둘이 주소를 비교하는 == 연산 결과 true를 반환하게 됩니다.

Week today = null; // 참조 타입이기 때문에 null도 저장 가능
today = Week.SUNDAY;

// 주소값 비교
System.out.println(today == Week.SUNDAY); // true

 

자주 쓰는 enum 메소드 종류

enum Week {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

 

name() 메소드

열거 객체가 가지고 있는 문자열을 return

반환되는 문자열은 열거 타입을 정의할 때 사용한 상수 이름과 동일

Week w = Week.FRIDAY;

// 열거 객체의 문자열을 리턴
String weekName = w.name();
System.out.println(weekName); // FRIDAY

 

만약 w 만 넣어줘도 FRIDAY를 출력하고 싶다면 toString을 오버라이드 해야 합니다.

enum Week {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    @Override
    public String toString() {
        return "It's " + name();  // "It's MONDAY"와 같은 형식으로 출력
    }
}

public class Main {
    public static void main(String[] args) {
        Week w = Week.FRIDAY;
        System.out.println(w);  // "It's FRIDAY" 출력
    }
}

values() 메소드

열거 타입의 모든 열거 객체들을 배열로 만들어 return

// 모든 열거 객체들을 배열로 리턴
Week[] w4 = Week.values();

System.out.println(Arrays.toString(w4)); // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]

for (Week type : Week.values()) { // 열거 순회
    System.out.println(type);  // 순서대로 열거 객체 출력
}

 

Enum 고급 문법

Enum 매핑

Season이라는 4계절 상수를 저장한 enum 이 있는데, 만일 SPRING 상수를 가져오면 "봄"이라는 상수의 고유 값(value)을 문자열을 출력하게 만들고 싶을 때 enum을 매핑해서 구성해 줄 수 있습니다.

enum Season {
  SPRING("봄"),
  SUMMER("여름"),
  FALL("가을"),
  WINTER("겨울");
  
  //문자열 저장할 필드
  private String season;
  
  // 생성자 ( 싱글톤 )
  private Season(String season) {
    this.season = season;
  }
  
  //Getter
  public String getSeason() {
    return season;
  }
}
public static void main(String[] args) throws Exception {
  Season s = Season.SUMMER;
  
  System.out.println(s.name()); // SUMMER
  System.out.println(s.getSeason()); // 여름
}

 

enum 은 데이터의 그룹화 및 관리에 용이

체크카드를 다룬다고 한다면, 카드사마다 다르며 신한 카드를 쓰더라도 또 여러 가지 카드 종류가 있을 텐데, 본래라면 '카드사' 클래스와 '카드종류' 클래스인 두 개로 나누어 서로 연관되게 코드를 구성해야 합니다.

하지만 enum을 이용하면 한눈에 보기 쉽게 아래처럼 구성이 가능하여 관계를 가시적으로 표현할 수 있습니다.

그리고 적절하게 메소드 로직을 enum 객체 내 안에 구현해 준다면 강력한 상수 클래스를 구현할 수 있게 됩니다.

 

enum CreditCard {
  SHINHAN("신한", Arrays.asList("Mr.Life 카드", "Deep Dream 카드", "Deep Oil 카드")),
  KB("국민", Arrays.asList("톡톡D 카드", "티타늄 카드", "다담 카드")),
  NH("농협", Arrays.asList("올바른 FLEX 카드", "테이크 5 카드", "NH 올원 파이카드"));
  
  private final String enterprise;
  private final List<String> cards;
  
  private CreditCard(String enterprise, List<String> cards) {
    this.enterprise = enterprise;
    this.cards = cards;
  }
  
  public String getEnterprise() {
    return enterprise;
  }
  
  public List<String> getCards() {
    return cards;
  }
  
  public static CreditCard getCard(String cardName) {
    return Arrays.stream(CreditCard.values())
      .filter(creditCard -> creditCard.cards.contains(cardName))
      .findFirst()
      .orElseThrow(() -> new IllegalArgumentException("Card not found: " + cardName));
  }
}
꿀팁
Arrays.stream(CreditCard.values())라는 코드가 싫다면 따로 변수로 빼서 사용하시면 됩니다.
CreditCard card = CreditCard.values() → return card.stream().filter()....

 

public class CreditCardExample {
    public static void main(String[] args) {
        // 특정 카드 이름으로 CreditCard enum 찾기
        String cardName = "Deep Dream 카드";
        
        try {
            CreditCard creditCard = CreditCard.getCard(cardName); // CreditCard.SHINHAN
            System.out.println("카드 이름: " + cardName);
            System.out.println("발급사: " + creditCard.getEnterprise());
            System.out.println("해당 발급사의 카드 목록: " + creditCard.getCards());
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }

        System.out.println();

        // 모든 발급사와 카드 목록 출력
        for (CreditCard card : CreditCard.values()) {
            System.out.println("발급사: " + card.getEnterprise());
            System.out.println("카드 목록: " + card.getCards());
        }
    }
}
카드 이름: Deep Dream 카드
발급사: 신한
해당 발급사의 카드 목록: [Mr.Life 카드, Deep Dream 카드, Deep Oil 카드]

발급사: 신한
카드 목록: [Mr.Life 카드, Deep Dream 카드, Deep Oil 카드]
발급사: 국민
카드 목록: [톡톡D 카드, 티타늄 카드, 다담 카드]
발급사: 농협
카드 목록: [올바른 FLEX 카드, 테이크 5 카드, NH 올원 파이카드]

 

enum 확장

enum 매핑 기능을 확장하여, enum을 단순히 상수 값을 넘어서 상수 메소드로서도 이용이 가능합니다.

enum Operation {
    PLUS("+") {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS("-") {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTI("*") {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE("/") {
        public double apply(double x, double y) {
            return x / y;
        }
    };

    // 클래스 생성자와 멤버
    private final String symbol;
    Operation(String symbol) {
        this.symbol = symbol;
    }

    // toString을 재정의하여 열거 객체의 매핑된 문자열을 반환하도록
    @Override
    public String toString() {
        return symbol;
    }

    // 열거 객체의 메소드에 사용될 추상 메소드 정의
    public abstract double apply(double x, double y);
}

 

public static void main(String[] args) {
    double x = 2.5;
    double y = 5.0;

    // Operation 상수집합의 PLUS 상수를 정의
    Operation plus = Operation.PLUS;

    // enum 매핑값 출력
    String name = plus.toString();
    System.out.println(name); // +

    // enum 확장 메소드 실행
    double result = plus.apply(x, y); // 덧셈을 수행하는 메소드 (Operation.PLUS.apply(x, y) 로 해도됨)
    System.out.println(result); // 7.5

    // ------------------------------------------------------------------- //

    // Operation 상수집합의 PLUS 상수를 정의
    Operation multi = Operation.MULTI;

    String name = plus.toString();
    System.out.println(name); // *

    // enum 확장 메소드 실행
    double result2 = multi.apply(x, y); // 곱셈을 수행하는 메소드
    System.out.println(result2); // 12.5
}

 

'Java' 카테고리의 다른 글

간단한 에러 출력 방법과 문제점  (0) 2025.01.02
자바의 람다 표현식  (1) 2024.12.26
자바의 Optional  (0) 2024.12.23
자바의 Generic  (1) 2024.12.19
자바의 오류처리: 예외(Exception) 와 트랜잭션 처리  (0) 2024.12.18