열거형 ENUM 보충자료

Enum (Enumeration - 열거형)

1. Enum이란?

  • 열거형미리 정해진 상수들의 집합을 표현하는 클래스입니다.

  • 자바에서 열거형은 enum 키워드를 사용해 정의됩니다.

  • 값의 범위를 제한하고, 타입 안전성을 보장하여 데이터의 일관성을 유지할 수 있도록 합니다.


2. Enum이 왜 필요한가?

(1) 문자열 기반 로직의 문제점

  • 문자열로 로직을 구성하면 다음과 같은 문제가 발생할 수 있습니다:

    • 오타: 문자열 비교 시 오타가 있어도 컴파일러가 인식하지 못합니다.

    • 유효하지 않은 값: 잘못된 값이 입력되어 런타임 오류가 발생할 가능성이 높습니다.

    • 타입 안전성 부족: 문자열은 다양한 값으로 표현되기 때문에 데이터 일관성이 떨어집니다.

(2) 상수 기반의 문제점

  • 상수를 사용해도 여전히 문자열을 비교해야 하므로 안정성을 확보하기 어렵습니다.

(3) Enum의 장점

  • 타입 안정성:

    • 열거형 외의 값은 컴파일 시 오류로 처리됩니다.

  • 값의 범위 제한:

    • 특정 범위의 값만 허용되므로 데이터 일관성을 유지할 수 있습니다.

  • 코드 가독성 및 간결성:

    • 열거형을 사용하면 코드가 더 간결하고 의미가 명확해집니다.


3. Enum의 특징

  1. 미리 정의된 상수 집합:

    • Enum은 사전에 정의된 값을 가집니다.

    • 새로운 값을 외부에서 생성할 수 없습니다.

  2. 클래스와 동일한 성격:

    • 열거형도 자바의 클래스입니다.

    • 멤버 변수, 메서드, 생성자를 가질 수 있습니다.

  3. Private 생성자:

    • Enum의 생성자는 항상 private입니다.

    • 생성자를 명시적으로 선언하지 않으면 자바가 기본적으로 private 생성자를 제공합니다.

  4. 컴파일 오류 방지:

    • 유효하지 않은 값이 사용되면 컴파일 시 오류가 발생합니다.

  5. Switch문과 함께 사용:

    • 열거형은 switch문에서 간결하게 사용할 수 있습니다.


4. Enum 예제

(1) 기본 Enum 사용

코드

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

public class EnumBasicExample {
    public static void main(String[] args) {
        Day today = Day.MONDAY;

        // Enum 값 출력
        System.out.println("Today is: " + today);

        // Enum 비교
        if (today == Day.MONDAY) {
            System.out.println("Start of the week!");
        }

        // Enum을 switch문에서 사용
        switch (today) {
            case MONDAY:
                System.out.println("Work hard!");
                break;
            case FRIDAY:
                System.out.println("Almost weekend!");
                break;
            case SUNDAY:
                System.out.println("Time to relax!");
                break;
            default:
                System.out.println("Keep going!");
        }
    }
}

실행 결과

Today is: MONDAY
Start of the week!
Work hard!

(2) Enum에 멤버 변수와 생성자 추가

코드

enum Fruit {
    APPLE("Red"), BANANA("Yellow"), GRAPE("Purple");

    private final String color; // 멤버 변수

    // Private 생성자
    private Fruit(String color) {
        this.color = color;
    }

    // Getter 메서드
    public String getColor() {
        return color;
    }
}

public class EnumWithFieldsExample {
    public static void main(String[] args) {
        for (Fruit fruit : Fruit.values()) {
            System.out.println(fruit + " is " + fruit.getColor());
        }
    }
}

실행 결과

csharp코드 복사APPLE is Red
BANANA is Yellow
GRAPE is Purple

(3) Enum으로 상태 관리하기

코드

enum Status {
    SUCCESS, FAIL, PENDING
}

public class EnumStatusExample {
    public static void main(String[] args) {
        Status currentStatus = Status.PENDING;

        switch (currentStatus) {
            case SUCCESS:
                System.out.println("Operation completed successfully.");
                break;
            case FAIL:
                System.out.println("Operation failed.");
                break;
            case PENDING:
                System.out.println("Operation is still pending.");
                break;
        }
    }
}

(4) Enum을 활용한 커스텀 메서드 추가

코드

enum Operation {
    ADDITION {
        @Override
        public double apply(double x, double y) {
            return x + y;
        }
    },
    SUBTRACTION {
        @Override
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTIPLICATION {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVISION {
        @Override
        public double apply(double x, double y) {
            return x / y;
        }
    };

    // 추상 메서드 정의
    public abstract double apply(double x, double y);
}

public class EnumWithMethodsExample {
    public static void main(String[] args) {
        double x = 10, y = 2;

        for (Operation op : Operation.values()) {
            System.out.println(op + ": " + op.apply(x, y));
        }
    }
}

실행 결과

makefile코드 복사ADDITION: 12.0
SUBTRACTION: 8.0
MULTIPLICATION: 20.0
DIVISION: 5.0

5. Enum 사용 시 주의사항

  1. 타입 안전성:

    • Enum을 사용하면 값의 범위를 제한하여 코드의 타입 안정성을 보장합니다.

    • 유효하지 않은 값이 사용되면 컴파일 시 오류가 발생합니다.

  2. 문자열 사용 대체:

    • Enum은 문자열 비교보다 안전하며, 값의 일관성을 유지합니다.

  3. Switch문에서 사용:

    • Enum을 switch문과 함께 사용하면 조건문을 간결하고 읽기 쉽게 작성할 수 있습니다.

  4. 기능 확장:

    • Enum은 클래스처럼 멤버 변수, 메서드를 정의할 수 있으므로 필요에 따라 다양한 기능을 구현할 수 있습니다.

Enum (열거형) 심화

1. 상수를 새로 생성하는 식의 클래스로 만드는 예제

열거형을 사용하지 않고 상수로 구성된 클래스를 작성하면 다음과 같이 불안정하고 관리가 어려운 구조가 됩니다.

(1) 기존 상수 클래스 방식 (문제점 있는 코드)

class Status {
    public static final int SUCCESS = 1;
    public static final int FAIL = 2;
    public static final int PENDING = 3;
}

public class StatusExample {
    public static void main(String[] args) {
        int currentStatus = Status.SUCCESS;

        switch (currentStatus) {
            case Status.SUCCESS:
                System.out.println("Operation completed successfully.");
                break;
            case Status.FAIL:
                System.out.println("Operation failed.");
                break;
            case Status.PENDING:
                System.out.println("Operation is still pending.");
                break;
            default:
                System.out.println("Unknown status.");
        }
    }
}

문제점

  • 값이 단순한 정수이므로 타입 안전성이 없습니다.

  • 잘못된 값을 넣어도 컴파일 오류가 발생하지 않습니다.

    java코드 복사int currentStatus = 999; // 유효하지 않은 값
  • 값의 의미를 코드만으로 쉽게 파악하기 어렵습니다.


(2) Enum을 활용한 개선된 코드

열거형을 사용하여 코드의 안정성가독성을 높일 수 있습니다.

enum Status {
    SUCCESS, FAIL, PENDING
}

public class EnumStatusExample {
    public static void main(String[] args) {
        Status currentStatus = Status.SUCCESS; // Enum 타입 사용

        switch (currentStatus) {
            case SUCCESS:
                System.out.println("Operation completed successfully.");
                break;
            case FAIL:
                System.out.println("Operation failed.");
                break;
            case PENDING:
                System.out.println("Operation is still pending.");
                break;
        }
    }
}

개선점

  • 유효하지 않은 값은 컴파일 시 오류로 처리됩니다.

    Status currentStatus = 999; // 컴파일 오류 발생

리팩토링된 코드

enum Status {
    SUCCESS("Operation completed successfully."),
    FAIL("Operation failed."),
    PENDING("Operation is still pending.");

    private final String message; // 멤버 변수

    // 생성자
    Status(String message) {
        this.message = message;
    }

    // 메시지 출력 메서드
    public void handle() {
        System.out.println(message);
    }
}

public class EnumStatusExample {
    public static void main(String[] args) {
        Status currentStatus = Status.SUCCESS; // 현재 상태
        currentStatus.handle(); // 상태에 따른 동작 실행
    }
}

2. 열거형의 주요 메서드

(1) values()toString() 사용

  • values(): 열거형의 모든 상수를 배열로 반환합니다.

  • toString(): 열거형 상수의 이름을 문자열로 반환합니다.

코드

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

public class EnumMethodsExample {
    public static void main(String[] args) {
        // values()를 사용하여 모든 상수 출력
        for (Day day : Day.values()) {
            System.out.println("Day: " + day);
        }

        // toString() 호출
        Day today = Day.MONDAY;
        System.out.println("Today is: " + today.toString());
    }
}

실행 결과

Day: MONDAY
Day: TUESDAY
Day: WEDNESDAY
Day: THURSDAY
Day: FRIDAY
Day: SATURDAY
Day: SUNDAY
Today is: MONDAY

(2) valueOf()를 사용하여 문자열에서 Enum 변환

  • 문자열로 받은 값을 열거형으로 변환할 수 있습니다.

코드

enum Color {
    RED, GREEN, BLUE
}

public class EnumValueOfExample {
    public static void main(String[] args) {
        String colorName = "RED";
        
        // valueOf()를 사용하여 문자열을 Enum으로 변환
        Color color = Color.valueOf(colorName);
        System.out.println("Selected Color: " + color);
    }
}

실행 결과

Selected Color: RED

3. Enum에 메서드 추가로 리팩토링

상황

  • 각 열거형 상수에 특정 데이터를 연결하거나, 상수마다 다른 동작을 구현해야 할 경우 메서드를 추가하면 코드가 더 간결하고 유지보수가 용이해집니다.


(1) 기본적인 Enum에 메서드 추가

코드

enum Fruit {
    APPLE("Red"), BANANA("Yellow"), GRAPE("Purple");

    private final String color;

    // Private 생성자
    private Fruit(String color) {
        this.color = color;
    }

    // Getter 메서드
    public String getColor() {
        return color;
    }
}

public class EnumWithMethods {
    public static void main(String[] args) {
        for (Fruit fruit : Fruit.values()) {
            System.out.println(fruit + " is " + fruit.getColor());
        }
    }
}

실행 결과

APPLE is Red
BANANA is Yellow
GRAPE is Purple

(2) 열거형 상수별로 다른 동작 추가

코드

enum Operation {
    ADD {
        @Override
        public double calculate(double x, double y) {
            return x + y;
        }
    },
    SUBTRACT {
        @Override
        public double calculate(double x, double y) {
            return x - y;
        }
    },
    MULTIPLY {
        @Override
        public double calculate(double x, double y) {
            return x * y;
        }
    },
    DIVIDE {
        @Override
        public double calculate(double x, double y) {
            return x / y;
        }
    };

    // 추상 메서드 정의
    public abstract double calculate(double x, double y);
}

public class EnumAdvancedExample {
    public static void main(String[] args) {
        double x = 10;
        double y = 5;

        for (Operation op : Operation.values()) {
            System.out.println(op + ": " + op.calculate(x, y));
        }
    }
}

실행 결과

makefile코드 복사ADD: 15.0
SUBTRACT: 5.0
MULTIPLY: 50.0
DIVIDE: 2.0

4. Enum 활용 시 장점

  1. 코드의 안정성:

    • 유효하지 않은 값의 사용을 방지하여 컴파일 시 오류를 제공합니다.

  2. 가독성:

    • 상수 값을 열거형으로 정의함으로써 코드가 더 명확하고 직관적입니다.

  3. 리팩토링 용이:

    • 열거형에 데이터를 추가하거나 메서드를 구현하면 복잡한 로직을 간결하게 리팩토링할 수 있습니다.

Last updated