[STUDY HALLE] 11주차 과제: Enum

2 minute read

학습 목표

자바의 열거형에 대해 학습하세요.

  • enum 정의하는 방법
  • enum이 제공하는 메소드 (values()와 valueOf())
  • java.lang.Enum
  • EnumSet

Deadline: ~2021/01/30 13:00

Enum

Enum이란 Enumeration의 준말로, 직역하면 ‘열거’이다. 상수를 보다 효율적으로 관리하기 위해 사용되며, 사용 방식은 다음과 같다.

// 선언
enum 열거체이름 { 상수1이름, 상수2이름, ... }
enum Rainbow { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET }

// 사용
열거체이름.상수이름
Rainbow.RED

C/C++의 경우 Enum이 결국 int값일 뿐이지만, Java의 Enum은 완전한 기능을 갖춘 클래스이기 때문에 매우 다양한 활용이 가능하다. 다른 언어에서 enum값을 비교할 때는 int형의 자료형을 비교하지만, Java에서는 상수값 이전에 같은 enum객체인지도 비교를 하기 때문에, 타입 안전성이 보장된다.

package week11;

enum Rainbow {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;

    Rainbow() {
        System.out.println("Constructor called : " + this.toString());
    }

    public void colorInfo() {
        System.out.println("I'm " + this.toString());
    }
}

public class Week11 {
    public static void main(String[] args) {
        Rainbow RED = Rainbow.RED;
        RED.colorInfo();
    }
}

enum은 생성자와 메소드를 가질 수 있고, enum 클래스가 로드 될 때 각 상수들이 개별적으로 실행된다.

Constructor called : RED
Constructor called : ORANGE
Constructor called : YELLOW
Constructor called : GREEN
Constructor called : BLUE
Constructor called : INDIGO
Constructor called : VIOLET
I'm RED

생성자의 접근 제어자는 private로 ‘강제’된다. 기본적으로 private이며, public으로 선언하면 에러가 발생한다. enum은 ‘상수’의 집합이므로, 그 값은 컴파일타임에 확정되어야하기 때문이다. 즉, enum타입에 접근해서 값을 정해줄 수 없다.

그렇다면 enum은 언제 사용해야할까?

필요한 원소를 컴파일 타임에 다 알 수 있는 상수 집합이라면 항상 열거 타입을 사용하자. 태양계 행성, 한 주의 요일, 체스 말처럼 본질적으로 열거 타입인 타입은 당연히 포함된다. 그리고 메뉴 아이템, 연산 코드, 명령줄 플래그 등 허용하는 값 모두를 컴파일타임에 이미 알고 있을 때도 쓸 수 있다. 열거 타입에 정의된 상수 개수가 영원히 고정 불변일 필요는 없다. 열거 타입은 나중에 상수가 추가돼도 바이너리 수준에서 호환되도록 설계되었다 -이펙티브 자바

Enum이 제공하는 메소드

  • name() : 열거체의 문자열을 리턴
  • ordinal() : 열거체의 순번을 리턴
  • values() : 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환
  • valueOf() : 인자로 전달된 문자열과 일치하는 열거체 상수를 반환
public class Week11 {
    public static void main(String[] args) {
        Rainbow r = Rainbow.valueOf("RED");
        System.out.println(r.name());
        System.out.println(r.ordinal());

        Rainbow[] rs = r.values();
        for(Rainbow val : rs){
            System.out.print(val + " ");
        }
    }
}
RED
0
RED ORANGE YELLOW GREEN BLUE INDIGO VIOLET 

다만 ordinal() 메소드같은 경우는 사용이 지양되는데, API문서에서는 다음과 같이 설명하고있다.

대부분 프로그래머는 이 메서드를 쓸일이 없다. 이 메서드는 EnumSet과 EnumMap 같이 열거 타입 기반의 범용 자료구조에 쓸 목적으로 설계되었다.

java.lang.Enum

위에서 사용한 enum 메소드는 해당 클래스에 구현이 되어있고, 이를 상속한 것이다. enum은 java.lang.Enum를 상속하고 있으므로, 다른 클래스는 상속 받을 수 없다.

EnumSet

EnumSet은 java.util 패키지 내에 선언되어 있는 추상 클래스이다. Enumset은 bit vector들로 표현되므로, 시간과 공간 복잡도에서 매우 효율적이다.

package week11;

import java.util.EnumSet;
import java.util.Set;

enum Rainbow {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;

    Rainbow() {
        // System.out.println("Constructor called : " + this.toString());
    }

    public void colorInfo() {
        System.out.println("I'm " + this.toString());
    }

    public void printSet(Set<Rainbow> Colors) {
        System.out.println(Colors);
    }
}

public class Week11 {
    public static void main(String[] args) {
        EnumSet<Rainbow> colors = EnumSet.of(Rainbow.RED, Rainbow.ORANGE);
        EnumSet<Rainbow> all = EnumSet.allOf(Rainbow.class);
        EnumSet<Rainbow> none = EnumSet.noneOf(Rainbow.class);
        EnumSet<Rainbow> inner = EnumSet.range(Rainbow.YELLOW, Rainbow.INDIGO);

        System.out.println(colors);
        System.out.println(all);
        System.out.println(none);

        // printSet 메소드를 호출하기 위해 아무거나 생성
        Rainbow Test = Rainbow.RED;
        Test.printSet(inner);
    }
}
[RED, ORANGE]
[RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET]
[]
[YELLOW, GREEN, BLUE, INDIGO]

참고문헌

https://woowabros.github.io/tools/2017/07/10/java-enum-uses.html
https://wisdom-and-record.tistory.com/52
http://www.tcpschool.com/java/java_api_enum

Leave a comment