티스토리 뷰

Java/Java

<Java> 열거형(ENUM)이 생긴 이유?

면목동인간 2024. 6. 20. 18:53

열거형이란?

 열거의 뜻은 어떤 항목을 나열하는 것이며, 자바에서의 열거형은 서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다. 

 

열거형이 생긴 이유?

 우선 열거형이 생기기 전의 예제를 보면서 열거형이 생긴 이유를 봐야한다. 아래 예제는 부모, 선생님, 학생에 따라 노출되는 문자를 리턴해주는 예제이다.

예제1

public class SchoolService {

    public String show(String division) {

        String returnView = "";

        if (division.equals("Parent")) {
            returnView = "A";
        } else if (division.equals("Teacher")) {
            returnView = "B";
        } else if (division.equals("Student")) {
            returnView = "C";
        }
        return returnView;
    }
}
public class SchoolMain {

    public static void main(String[] args) {
        
        SchoolService schoolService = new SchoolService();
        String parent = schoolService.show("Parent");
        String teacher = schoolService.show("Teacher");
        String student = schoolService.show("Student");

        System.out.println("Parent의 노출 문자: " + parent);
        System.out.println("Teacher의 노출 문자: " + teacher);
        System.out.println("Student의 노출 문자: " + student);
    }
}
Parent의 노출 문자: A
Teacher의 노출 문자: B
Student의 노출 문자: C

 위의 코드에서 division의 매개변수에 따라 리턴 되는 문자가 다르다. 하지만 만약 division의 값이 다르다면 어떻게 될까? 예를 들어 Parent의 값이 parent라던가 Parentt 등등이면 의도와는 다른 빈 문자열이 리턴될 것이다.

문제점

  • 타입 안정성 부족: 오타가 발생하기 쉽고, 유효하지 않는 값 입력 가능
  • 데이터 일관성: parent, Parent, PARENT 등 다양한 형식으로 문자열 입력 가능)

예제2

 예제2는 위의 문제점의 대안인 문자열 상수를 사용했다.

public class StringSchool {
    public static final String PARENT = "Parent";
    public static final String TEACHER = "Teacher";
    public static final String STUDENT = "Student";
}
public class SchoolMain {

    public static void main(String[] args) {
       
        SchoolService schoolService = new SchoolService();
        String parent = schoolService.show(StringSchool.PARENT);
        String teacher = schoolService.show(StringSchool.TEACHER);
        String student = schoolService.show(StringSchool.STUDENT);

        System.out.println("Parent의 노출 문자: " + parent);
        System.out.println("Teacher의 노출 문자: " + teacher);
        System.out.println("Student의 노출 문자: " + student);
    }
}
Parent의 노출 문자: A
Teacher의 노출 문자: B
Student의 노출 문자: C

 위의 코드에서 division의 매개변수에 StringSchool의 문자열 상수를 사용한 덕에 코드가 명확해졌다. 하지만 상수를 사용해도 division의 매개변수는 String 타입이므로 문자열 상수가 아닌 직접 문자열로 전달 할 수 있다. 결국 아래와 같이 문자열로 전달해도 막을 수 없다.

String parent = schoolService.show("parent");

타입 안전 열거형 패턴

 위의 문제를 해결하기 위해 나온 결과가 타입 안전 열거형 패턴이다. 중요한 것은 이 패턴을 사용하면 위의  부모, 선생님, 학생의 항목만 사용할 수 있다는 것이다. 아래 코드는 열거형 패턴으로 변형한 코드이다.

예제1

public class ClassSchool {
    public static final ClassSchool PARENT = new ClassSchool();
    public static final ClassSchool TEACHER = new ClassSchool();
    public static final ClassSchool STUDENT = new ClassSchool();
}
public class SchoolService {

    public String show(ClassSchool classSchoolDivision) {

        String returnView = "";

        if (StringSchoolDivision == ClassSchool.PARENT) {
            returnView = "A";
        } else if (StringSchoolDivision == ClassSchool.TEACHER) {
            returnView = "B";
        } else if (StringSchoolDivision == ClassSchool.STUDENT) {
            returnView = "C";
        }
        return returnView;
    }
}
public class SchoolMain {

    public static void main(String[] args) {
        
        SchoolService schoolService = new SchoolService();
        String parent = schoolService.show(ClassSchool.PARENT);
        String teacher = schoolService.show(ClassSchool.TEACHER);
        String student = schoolService.show(ClassSchool.STUDENT);

        System.out.println("Parent의 노출 문자: " + parent);
        System.out.println("Teacher의 노출 문자: " + teacher);
        System.out.println("Student의 노출 문자: " + student);
    }
}

 ClassSchool 클래스 내의 3개의 인스턴스 상수는 static이므로 로딩 시점에 3개의 ClassSchoold의 인스턴스가 생성된다. 따라서 ClassSchool 타입을 사용할 때는 로딩 시점에 생성한 3개의 ClassSchool 인스턴스만 사용하게 되며,  classSchoolDivision 매개 변수도 ClassSchool 타입이므로 ClassSchool 인스턴스만 전달 가능하다.

문제점

 ClassSchool 클래스를 보면 외부에서 임의로 ClassSchool의 인스턴스를 생성할 수 있다. 따라서 이 문제를 해결하기 위해서는 생성자를 private으로 변경하면 된다. 아래 코드는 생성자에 private를 선언했으며, ClassSchool의 인스턴스를 생성하는 것은 ClassSchool 클래스 내부에서만 가능하다.

public class ClassSchool {
    public static final ClassSchool PARENT = new ClassSchool();
    public static final ClassSchool TEACHER = new ClassSchool();
    public static final ClassSchool STUDENT = new ClassSchool();
    
    private ClassSchool() {}
}

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

  • 타입 안정성 향상: 정해진 객체만 사용할 수 있기 때문에, 잘못된 값을 입력하는 문제를 방지할 수 있다.
  • 데이터 일관성: 정해진 객체만 사용하므로 일관성이 보장된다.

패턴 적용 후 단점

 이 패턴을 구현하면 ClassSchool처럼 많은 코드를 구현해야하고 private 생성자를 추가하는 등 고려해야할 것이 있다.

 

열거형의 등장

 위의 단점에서 많은 코드의 구현을 해소하기 위해 자바는 타입 안정 열거형 패턴을 편리하게 사용할 수 있는 열거형을 제공한다. 

public enum Division {
    PARENT, TEACHER, STUDENT
}
public class ClassSchool extends Enum {
    public static final ClassSchool PARENT = new ClassSchool();
    public static final ClassSchool TEACHER = new ClassSchool();
    public static final ClassSchool STUDENT = new ClassSchool();
    
    private ClassSchool() {}
}

위의 열거형으로 작성한 첫번째 코드와 두번째 코드는 거의 같다. (열거형은 자동으로 java.lang.Enum 을 상속 받는다.)

열거형으로 변환

 아래 코드는 위에서 작성한 코드를 열거형으로 변환한 코드이다.

public class SchoolService {

    public String show(Division division) {

        String returnView = "";

        if (division == Division.PARENT) {
            returnView = "A";
        } else if (division == Division.TEACHER) {
            returnView = "B";
        } else if (division == Division.STUDENT) {
            returnView = "C";
        }
        return returnView;
    }
}
public class SchoolMain {

    public static void main(String[] args) {
        
        SchoolService schoolService = new SchoolService();
        String parent = schoolService.show(Division.PARENT);
        String teacher = schoolService.show(Division.TEACHER);
        String student = schoolService.show(Division.STUDENT);

        System.out.println("Parent의 노출 문자: " + parent);
        System.out.println("Teacher의 노출 문자: " + teacher);
        System.out.println("Student의 노출 문자: " + student);
    }
}

위의 코드에서 열거형을 사용함으로써 위의 타입 안정성 향상과 데이터 일관성 을 해결할 수 있다.

열거형의 장점

  • 타입 안정성 향상: 열거형은 사전에 정의도니 상수들로만 구성되므로, 유효하지 않은 값은 입력될 수 없다.
  • 간결성 및 일관성: 코드가 더 간결하고 명확해지며, 데이터의 일관성이 보장된다.
  • 확장성: 새로운 타입을 추가할 때 ENUM에 새로운 상수를 추가하면 된다. 

 

열거형 메서드

  • values(): 모든 ENUM 상수를 포함하는 배열을 반환한다
  • valueOf(String name): 주어진 이름과 일치하는 ENUM 상수를 반환한다
  • name(): ENUM 상수의 이름을 문자열로 반환한다
  • ordinal(): ENUM 상수의 선언 순서(0부터 시작)를 반환한다
  • toString(): ENUM 상수의 이름을 문자열로 반환한다. name() 메서드와 유사하지만, toString() 은 직접 오버라이드 할 수 있다

 


본 포스팅은 “김영한의 실전 자바 - 중급 1편/인프런”를 학습한 내용을 정리한 것

댓글
최근에 올라온 글
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함
Total
Today
Yesterday