프로그래밍 언어/Java

[Java] 자바 열거형(enums)이란?

happy_life 2022. 7. 2. 11:46

자바 열거형이란?

 

열거형(enums) 개요

열거형은 서로 관련된 상수를 모아 클래스 형식으로 선언한 것이다. 열거형은 JDK 1.5부터 추가된 것으로, 값뿐만 아니라 타입까지도 관리한다. 따라서 실제 값이 같아도 타입이 다르면 조건식에서 false를 return한다. 마지막으로 상수가 바뀌어도 기존의 소스코드를 다시 컴파일하지 않아도 된다는 장점이 있다.

 

관련된 것끼리 상수를 모은다는 것

예를 들어 이 코드를 보자.

 

기존 코드

class Food {
    // 과일
    static final int APPLE = 0;
    static final int BANANA = 1;
    static final int CHERRY = 2;

    // 한식
    static final int KIMCHI = 0;
    static final int BAB = 1;
}

과일과 한식으로 묶이는데, 이를 eum을 사용하면 아래의 코드로 바꿀 수 있다.

 

enum을 사용한 코드

class FoodEnum {
    enum Fruit{APPLE,BANANA,CHEERY}

    enum Korean{KIMCHI, BAB}
}

 

타입에 안전한 열거형을 제공한다는 것

예를들어 APPLE과 KIMCHI는 0으로 값이 같다. 하지만 타입이 다르므로 자바에서는 둘을 비교하면 true가 아닌 컴파일 에러가 발생하게 된다. 이런식으로 값뿐만 아니라 타입까지 고려해주기 때문에 안전한 열거형을 제공한다는 것이다.

 

 

열거형(enums) 정의와 사용법

열거형 정의

eum 열거형이름 {상수이름1, 상수이름2 ... } 

enum Fruit{APPLE,BANANA,CHEERY} //0 1 2 값이 자동 부여

 

열거형 비교

열거형에서의 비교로 "=="를 사용할 수 있지만, 비교 연산자는 사용 불가능하다. 대신 compareTo()는 사용할 수 있다. 

 

코드 예제

public class enumEx1 {
    public static void main(String[] args) {
        FoodEnum.Fruit e1 = FoodEnum.Fruit.APPLE;
        FoodEnum.Fruit e2 = FoodEnum.Fruit.APPLE;
        FoodEnum.Fruit e3 = FoodEnum.Fruit.BANANA;

        // 비교하기
        System.out.println("e1==e2 = " + (e1==e2));
        System.out.println("e1==e2 = " + (e1==e3));

        System.out.println("e1.compareTo(e3) = " + e1.compareTo(e3));
    }
}

class FoodEnum {
    enum Fruit{APPLE,BANANA,CHEERY}

}

 

열거형(enums) 에 멤버 추가하기

enum Fruit{APPLE,BANANA,CHEERY} //0 1 2 값이 자동 부여

앞서 0 1 2 값이 자동으로 부여된다고 했는데 이 값들을 다르게 바꾸고 싶은 경우 어떻게 해야할까?

열거형에 멤버와 생성자를 추가하면 된다.

 

아래의 코드를 보며 이해해 보자.

 

코드 예제

class FoodEnum {
    enum Fruit {
        APPLE(3000), BANANA(4000), CHEERY(1000);

        final int val; // 멤버

        Fruit(int val) { // 생성자
            this.val = val;
        }
    }
}

각각에 3000, 4000, 1000이라는 값을 부여하기 위해 val이라는 멤버와 아래에 생성자를 추가해주었다. 참고로 생성자에는 private이 생략되어 있으며APPLE(3000), BANANA(4000), CHEERY(1000);는 생성자 호출이라고 생각하면 된다.

 

values() 와 name() 이라는 메서드를 사용해 값을 확인해볼 수 있다.

    FoodEnum.Fruit[] values = FoodEnum.Fruit.values();
    for (FoodEnum.Fruit value : values) {
        System.out.println("value.val, value.name() = " + value.val + ", " + value.name());
    }
}

 

출력 결과

 

 

열거형(enums) 에 추상 메서드

위의 APPLE, BANANA, CHERRY를 팔게 된다고 생각해보자. 각 가격을 알리기 위해메서드를 작성해 가격(val)을 return 한다고 하면 아래와 같이 코드를 작성할 수 있다.

class FoodEnum {
    enum Fruit {
        APPLE(3000), BANANA(4000), CHEERY(1000);

        final int val;

        Fruit(int val) {
            this.val = val;
        }

        int price() {
            return val;
        }
    }
}

 

하지만 사과는 1000원 세일하고, 바나나는 가격 그대로, 체리는 500원 세일한다면 위 코드만으로는 해결할 수 없다. 이런 문제를 해결하기 위해 추상 메서드를 활용할 수 있다.

 

코드 예제


System.out.println("할인된 가격: " + FoodEnum.Fruit.APPLE.price(1000)); //2000
System.out.println("할인된 가격: " + FoodEnum.Fruit.BANANA.price(0)); //4000
System.out.println("할인된 가격: " + FoodEnum.Fruit.CHEERY.price(500)); //500


class FoodEnum {
    enum Fruit {
        APPLE(3000){
            // 추상 메서드 구현
            int price(int sale) {
                return val - sale;
            }
        },
        BANANA(4000){
            // 추상 메서드 구현
            int price(int sale) {
                return val - sale;
            }

        },
        CHEERY(1000){
            // 추상 메서드 구현
            int price(int sale) {
                return val - sale;
            }
        };

        final int val;

        Fruit(int val) {
            this.val = val;
        }

        // 추상 메서드
        abstract int price(int sale);
    }
}

 

결국 이 코드들에서 알 수 있듯, 열거형은 특정한 상수가 아니라, 클래스를 상수처럼 사용하는 것임을 알 수 있다. 위의 APPLE, BANANA, CHERRY는 eum 클래스의 객체로 상수처럼 사용되는 것이다. 앞서 == 와 compareTo로 비교할 수 있었던 이유도 객체였기 때문에 가능한 것이다.