JAVA

[JAVA]enum

당고개 2023. 11. 15. 17:49

enum은 자바 가상 머신에 의해 singleton으로 생성되며 의미 있는 상수를 정의하고 프로그램의 안정성을 위해 사용됩니다.

enum CafeFoodCategory {
    BREAD, CAKE, COFFEE, BEVERAGE
}

enum은 이러한 문제를 해결하기 위해 만들어졌습니다.

public void eat(int foodCategory) {
    if (0 == foodCategory) {
        System.out.println("빵");
    } else if (1 == foodCategory) {
        System.out.println("케이크");
    } else if (2 == foodCategory) {
        System.out.println("커피");
    } else if (3 == foodCategory) {
        System.out.println("음료");
    } else {
        System.out.println("존재하지않음");
    }
}

이러한 메서드가 있다고 가정해봅시다. 해당 메서드는 0~3까지의 정수형 데이터를 넣으면 빵, 케이크, 커피, 음료를 출력하는 메서드입니다.

그리고 이러한 메서드를 사용하려면 일반적으로는 이렇게 할 겁니다.

eat(0);

eat(1);

메서드를 사용하는 코드만 본다면 eat(0), eat(1)이 무엇을 의미하는지 알 수 없습니다. 인자로 들어가는 0과 1의 의미를 확인하려면 eat 메서드 구현체를 직접 확인해야 겠지요.

그래서 이러한 불편함과 문제를 해결하기 위해 정수를 심볼릭 상수로 만들어서 의미를 부여했습니다.

final class FoodCategory {
    public static final int BREAD = 0;
    public static final int CAKE = 1;
    public static final int COFFEE = 2;
    public static final int BEVERAGE = 3;
}

 

심볼릭 상수를 정의한 FoodCategory 클래스를 만든다면 좀 더 낫습니다. 어느 정도 코드의 의미를 파악할 수 있지요.

eat(FoodCategory.BREAD);

eat(FoodCategory.CAKE);

그러나 해당 코드에는 본질적인 문제가 있습니다. eat 메서드는 정수로 된 모든 인자를 전달받을 수 있기 때문에 이러한 코드 작성도 가능합니다.

eat(-1);

eat(-100);

eat 메서드를 구현한 개발자는 eat 메서드를 이렇게 사용하라고 만들지는 않았을 겁니다. 그러나 논리적으로는 발생 할 수 있는 일입니다. 정수형 인자를 전달 받기 전에 특정 정수만 전달할 수 있도록 할 수 없으니까요.

이럴 땐 enum을 이용하면 상수에 의미를 부여하면서 전달할 수 있는 인자를 제한할 수 있습니다.

FoodCategory를 정의한 enum

enum FoodCategory {
    BREAD, CAKE, COFFEE, BEVERAGE
}

enum 상수를 전달 받는 eat 메서드

public void eat(FoodCategory foodCategory) {
    if (FoodCategory.BREAD == foodCategory) {
        System.out.println("빵");
    } else if (FoodCategory.CAKE == foodCategory) {
        System.out.println("케이크");
    } else if (FoodCategory.COFFEE == foodCategory) {
        System.out.println("커피");
    } else if (FoodCategory.BAVERAGE == foodCategory) {
        System.out.println("음료");
    }
}

eat 메서드를 FoodCategory enum에 정의된 상수만 전달받을 수 있도록 변경합니다.

eat(FoodCategory.BREAD);

eat(FoodCategory.CAKE);

그러면 eat 메서드를 호출할 때 enum에 정의된 상수만 전달할 수 있습니다. 코드의 가독성도 좋아지고 코드의 안정성도 확보됩니다.

ordinal()

ordinal() 메서드는 enum 상수에 정의된 순서값을 반환합니다.

enum FoodCategory {
    BREAD, CAKE, COFFEE, BEVERAGE
}
enum FoodCategory {
    BREAD, CAKE, COFFEE, BEVERAGE
}

단순히 순서값만 반환하기 때문에 정의된 상수에 위치가 달라지면 순서값이 달라질 수 있습니다. 특별한 상황이 아니라면 ordinal()에 반환된 값을 이용하여 조건을 판단하는 것을 하지 않는 것이 좋습니다.

name()

name() 메서드는 enum 상수에 정의된 이름을 반환합니다.

enum FoodCategory {
    BREAD, CAKE, COFFEE, BEVERAGE
}
System.out.println(FoodCategory.CAKE.name());

// 출력 : CAKE

만약의 상수의 이름을 이렇게 작성했다면 다음과 같이 출력됩니다.

enum FoodCategory {
    Bread, Cake, Coffee, Beverage
}
enum FoodCategory {
    Bread, Cake, Coffee, Beverage
}

Enum을 다르게 정의하기 

enum 상수에 특정한 값을 정의할 수 있습니다.

enum FoodCategory {
    BREAD(2800), 
    CAKE(17000), 
    COFFEE(4300), 
    BEVERAGE(2500);

    int cost;

    FoodCategory(int cost) {
        this.cost = cost;
    }
}

상수에 특정한 값을 지정할 때는 상수의 끝맺음에 반드시 세미콜론(;)을 작성해 주어야 합니다. 그리고 특정한 값이 정의에 맞게 생성자를 반드시 정의해 주어야 합니다. 그리고 enum 내에 변수를 선언하고 생성자를 통해 값을 저장하면 다음과 같이 사용할 수 있습니다.

System.out.println(FoodCategory.BREAD.cost);
System.out.println(FoodCategory.CAKE.cost);
System.out.println(FoodCategory.COFFEE.cost);
System.out.println(FoodCategory.BEVERAGE.cost);

// 출력 
2800
17000
4300
2500

하나의 특정한 값이 아니라 여러 개의 특정한 값을 지정할 수 있습니다.

enum FoodCategory {
    BREAD("빵", 2800), 
    CAKE("케이크", 17000), 
    COFFEE("커피", 4300), 
    BEVERAGE("음료", 2500);

    int name;
    int cost;

    FoodCategory(String name, int cost) {
        this.name = name;
        this.cost = cost;
    }
}
System.out.println(FoodCategory.CAKE.name);
System.out.println(FoodCategory.CAKE.cost);


// 출력 
케이크
17000

Enum의 생성자는 기본적으로 private이다

enum의 특성상 내부적으로 singleton 방식으로 관리하기 때문에 enum의 생성자는 기본적으로 private로 처리됩니다.

// 불가능한 코드
FoodCategory foodCategory = new FoodCategory(…);

 

 

 

 

출처 : https://www.codelatte.io/courses/java_programming_basic/EF27ZVVHZZI7SKWY

'JAVA' 카테고리의 다른 글

[JAVA]<제네릭>  (0) 2023.11.17
[JAVA]Singleton 패턴  (1) 2023.11.17
[JAVA]예외처리  (0) 2023.11.10
[JAVA]null  (0) 2023.11.09
[JAVA]Object 클래스  (0) 2023.11.07