티스토리 뷰

Java

[Java] enum type Class

Nickolodeon 2022. 11. 18. 00:49
Enums 는 프로그램 내에서 절대 변하지 않을 값들을 모아 놓은 특별한 '클래스' 이다.
- W3Schools -
로또 당첨 통계를 내는 프로그램 구현 문제의 풀이 과정에서 enum 을 활용하라는 조건이 있었다. 이전에도 enum 을 접해본 적은 있었지만, 적극적으로 구현에 활용해본 것은 처음이었고, 활용 과정에서 적재적소에 enum 을 최대한으로 활용하기 위해서는 용도와 목적을 공부해야겠다는 필요성을 느껴 포스트를 작성하게 되었다.

1. Enum 의 용도와 목적

위에서 정의했듯이 일반 Class 와 비슷한 듯 다른 enum 을 이해하기 위해 일반 Class 와 enum 의 차이점을 정리해보았다.

구분 일반 Class enum type Class
멤버 변수의 접근 제어자 public, private, protected 없음
메서드의 주 용도 객체의 동작 정의 멤버 변수 (상수) 의 Getter
생성자 클래스 인스턴스 생성 시 필요 enum 내부에서 각 상수를 생성 시 생성자 활용
생성자의 접근 제어자 public (외부에서 생성자로 인스턴스 생성) 없음 또는 private (외부에서 생성자 활용 x)
추상화 대상 확장 가능성이 있고 후보 값이 미정인
데이터들의 집합
- 현실세계에 있는 정해진 값들의 데이터 집합
- 후보 값들을 모두 알고 있는 데이터의 집합
enum 필드 변수 이름 규칙 - 상수이므로 필드 변수들의 이름은 대문자로 작성한다.
- Oracle Java Documentaion -

2. Enum 의 활용 방법

우선 javac 컴파일 시 붙는 옵션들 (command line flags) 을 enum 으로 표현해보자. 각 옵션들을 붙여서 컴파일하면 옵션이 붙고 용도가 문자열로 출력된다. enum 클래스는 다음과 같다:

public enum CommandLineFlags {
    DEBUGGING,
    HELP,
    VERSION,
    DIRECTORY
}

물론 더 많은 옵션들이 있지만, 편의상 생략해주었다.

일단 이 상태로는 옵션을 붙이지도 (실제 옵션들의 값을 상수에 할당하지 않았으므로) , 용도 문자열을 출력하지도 못한다. 그래서 일단 옵션과 용도 문자열을 출력할 수 있도록 상수 뒤에 괄호와 내용을 추가해주었다.

public enum CommandLineFlags {
    DEBUGGING("-g", "디버깅 옵션 사용"),
    HELP("-help", "도움말 옵션 사용"),
    VERSION("-version", "버전 확인 옵션 사용"),
    DIRECTORY("-d", "디렉토리 지정 옵션 사용");
}

이렇게 상수에 특정 값들을 정해주는 것은 사실 생성자가 필요한 일이다. 현재 enum 클래스의 변수들은 두 개의 값으로 초기화된다. 그러므로 두 개의 매개 변수를 받는 생성자가 필요하다. 이 것이 위 표에서 설명한 'enum 내부에서 각 상수를 생성 시 생성자 활용' 의 의미이다. 생성자를 추가해준다.

public enum CommandLineFlags {
    DEBUGGING("-g", "디버깅 옵션 사용"),
    HELP("-help", "도움말 옵션 사용"),
    VERSION("-version", "버전 확인 옵션 사용"),
    DIRECTORY("-d", "디렉토리 지정 옵션 사용");

    private String value;
    private String messasge;

    CommandLineFlags(String value, String messasge) {
        this.value = value;
        this.messasge = messasge;
    }
}

여기서 생성자가 접근 제어자를 가지고 있지 않음을 볼 수 있다. enum 클래스 상위에서 상수들을 초기화할 때만 사용하기 때문에 다른 데에서 접근할 일이 없다. 이제 CommandLineFlags 의 상수 값들을 실제로 가지고 오기 위해서 Getter 를 추가해주어야 한다. 그래야 value 든 message 든 가져와서 옵션을 확인하거나 출력할 수 있다.

public enum CommandLineFlags {
    DEBUGGING("-g", "디버깅 옵션 사용"),
    HELP("-help", "도움말 옵션 사용"),
    VERSION("-version", "버전 확인 옵션 사용"),
    DIRECTORY("-d", "디렉토리 지정 옵션 사용");

    private String value;
    private String messasge;

    CommandLineFlags(String value, String messasge) {
        this.value = value;
        this.messasge = messasge;
    }

    public String getValue() {
        return value;
    }

    public String getMessasge() {
        return messasge;
    }
}

이제 상수들을 활용할 준비가 되었다. main 함수가 위치한 Application 에서는 컴파일 시 javac 뒤에 주어지는 옵션을 파악한 후에, 옵션이 있다면 이에 맞는 메시지를 출력한다.

public class Application {
    public static void main(String[] args) {
     	if (args.length > 0) {
            if (CommandLineFlags.HELP.getValue().equals(args[0])) System.out.println(CommandLineFlags.HELP.getMessage());
            if (CommandLineFlags.DEBUGGING.getValue().equals(args[0])) System.out.println(CommandLineFlags.DEBUGGING.getMessage());
            if (CommandLineFlags.VERSION.getValue().equals(args[0])) System.out.println(CommandLineFlags.VERSION.getMessage());
            if (CommandLineFlags.DIRECTORY.getValue().equals(args[0])) System.out.println(CommandLineFlags.DIRECTORY.getMessage());
        }
    }
}

여기서 멈추면 사실 정말 enum 의 효과가 가독성 증가 말고는 없는 것 같이 느껴진다. 하지만 컴파일 시 enum 클래스에는 enum 클래스의 활용을 돕는 몇 가지의 메서드들이 자동으로 추가된다:


1. values() - enum 클래스 내에서 필드 변수들이 선언된 순서대로 들어있는 배열을 리턴하는 메서드.

이를 활용하면 위의 코드를 간단하게 만들 수 있다. for each 를 활용할 수 있기 때문이다. 아래는 리팩토링 후의 코드의 모습이다:

public class Application {
    public static void main(String[] args) {
        for (CommandLineFlags value : CommandLineFlags.values()) {
            if (args.length > 0)
            	if (value.getValue().equals(args[0])) System.out.println(value.getMessasge());
        }
    }
}

정말 간결해지는 것을 볼 수 있다.

 

2. ordinal() - enum 클래스 내에서 필드 변수들이 선언된 순서를 리턴하는 메서드.

 

List 의 get(Object value) 의 동작과 비슷하다고 생각하면 된다. 예를 들어, 다음 코드의 결과는 무엇일까?

public class Application {
    public static void main(String[] args) {
        System.out.println(CommandLineFlags.HELP.ordinal());
    }
}

바로 1이다. 이유는 HELP 가 CommandLineFlags 에서 index 1 을 갖기 때문이다. (두 번째에 선언되어 있기 때문)

3. 결론 & enum 사용 권장 이유

결국 enum 은 상수를 모아 놓은 클래스이다. 컴퓨터와 사람의 가장 큰 차이는 세상을 인식하는 방법이다. 컴퓨터의 언어는 숫자로, 세상의 모든 것들을 숫자로 인식한다. 반면 사람의 언어는 다양한데, 그 중 영어를 광범위하게 사용한다. 프로그램 작성 시에도 영어가 쓰이고, 변수 이름도 사람이 인식하기 위해 대부분 영어로 쓰인다. 숫자의 표현 범위는 영어에 비해 정말 작다. 숫자의 표현 범위를 넓히기 위해 변수에 숫자를 할당하여 사용하는데, 이러한 관습이 가장 큰 힘을 발휘할 때는 코드를 사람이 이해하기 쉽게 작성하고자 할 때이다. 자주 사용되는 표현을 변수에 고정적으로 할당해서 숫자 대신에 사용하면 일관성 있는 표현을 가진 코드를 작성하는 데에 도움이 된다. 매번 월요일을 일주일의 첫 번째 날이므로 1이란 숫자로 표현하는 대신에 MONDAY = 1 을 사용한 후 월요일이 나올 때마다 MONDAY 를 대신 써주면 일관성 있게 월요일을 표현하고 1을 다양한 용도에 재사용해서 일관성을 잃는 것을 예방한다.

4. 참고자료

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

 

Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

https://www.w3schools.com/java/java_enums.asp

 

Java Enums

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

https://techblog.woowahan.com/2527/

 

Java Enum 활용기 | 우아한형제들 기술블로그

{{item.name}} 안녕하세요? 우아한 형제들에서 결제/정산 시스템을 개발하고 있는 이동욱입니다. 이번 사내 블로그 포스팅 주제로 저는 Java Enum 활용 경험을 선택하였습니다. 이전에 개인 블로그에 E

techblog.woowahan.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
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
글 보관함