본문 바로가기
Java

[자바 라이브 스터디] 11. 열거형

by 매트(Mat) 2021. 10. 18.

11주차 과제: Enum

목표

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

 

학습할 것

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




enum 정의하는 방법

Enum이란 Enumeration의 앞 글자를 따 열거라는 의미를 갖습니다. 즉, 관련이 있는 상수들의 집합입니다. 상수를 정의할 때 자바에서는 final 키워드를 사용하여 값을 고정할 수 있습니다.

 

기존에는 인터페이스나 클래스 내에서 상수를 선언함으로써 상수를 관리하였는데 클래스 내에서 선언하는 부분은 네이밍이 겹칠 수 있고 불필요하게 상수가 많아진다는 단점이 있습니다. 이런 단점을 보완하여 나온 것이 Enum입니다.

Enum 정의

package azurealstn;

public enum Rank {

    THREE(3, 4000),
    FOUR(4, 10000),
    FIVE(5, 30000);

    private final int match;
    private final int money;
    private int count;

    (private 생략) Rank(int match, int money) {
        this.match = match;
        this.money = money;
    }
}

클래스를 상수처럼 사용할 수 있습니다.
위 코드를 보면 default 생성자는 private으로 되어 있으며 public으로 변경하면 컴파일 에러를 발생시킵니다. 다른 클래스나 인터페이스에서의 상수 선언이 클래스 로드 시점에서 생성되는 것처럼 Enum 또한 생성자가 존재하지만 클스 로드 시점에서 생성되기 때문에 임의로 생성하여 사용할 수 없습니다.

Enum 사용

package azurealstn;

public class Main {
    public static void main(String[] args) {
        System.out.println(Rank.THREE);
        System.out.println(Rank.FOUR);
        System.out.println(Rank.FIVE);
    }
}

Enum을 사용하는 방법은 Rank.THREE와 같이 상수처럼 접근하면 됩니다.

 

package azurealstn;

public enum Rank {

    THREE(3, 4000),
    FOUR(4, 10000),
    FIVE(5, 30000);

    private final int match;
    private final int money;
    private int count;

    Rank(int match, int money) {
        this.match = match;
        this.money = money;
    }

    public int plusCount() {
        return count++;
    }
}

Enum 클래스에서 다른 클래스나 인터페이스처럼 선언된 상수들은 클래스가 로드될 때 생성되기 때문에 싱글톤 형태로 어플리케이션 전체에서 사용됩니다. 따라서 위 코드에서 count 같은 변수들은 공유되기 때문에 사용할 때 주의해야 합니다.

 

그 밖에 특징으로는 서로 관련 있는 상수 값들을 모아 enum으로 구현하는 경우에 유용하며,
클래스와 같은 문법 체계를 따르며,
상속을 지원하지 않습니다.




enum이 제공하는 메소드 (values()와 valueOf())

Enum은 기본적으로 java.lang.Enum 클래스를 상속받고 있기 때문에 Enum이 제공하는 메소드가 있습니다.

values()

values() 메소드는 Enum 클래스가 가지고 있는 모든 상수 값을 배열의 형태로 리턴해줍니다.
단순히 String 형태로 반환하는 것이 아닌 인스턴스를 반환해줍니다. 즉, Enum 클래스가 가지고 있는 모든 인스턴스를 배열에 담아 반환합니다.

package azurealstn;

public class Main {
    public static void main(String[] args) {
        Rank[] values = Rank.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
        }
    }
}

valueOf()

valueOf() 메소드는 String 을 파라미터로 받는데 해당 파라미터가 Enum의 상수 인스턴스와 동일하다면 그 인스턴스를 반환합니다. 이 또한 String 형태로 반환하는 것이 아닌 인스턴스를 반환해줍니다.

package azurealstn;

public class Main {
    public static void main(String[] args) {
        System.out.println(Rank.valueOf("FOUR"));
    }
}




java.lang.Enum

Enum은 내부적으로 java.lang.Enum 클래스를 상속받고 있습니다. 따라서 클래스는 하나의 클래스만 상속받을 수 있으므로 Enum 클래스는 다른 클래스를 상속받을 수 없는 것입니다.

 

toString() 메소드는 java.lang.Enum 클래스에서 가져온 것입니다.
toString() 메소드는 상수의 이름을 리턴합니다.
enum은 다양한 인터페이스들을 상속받을 수 있습니다.

public class Main {
    public static void main(String[] args) {
        System.out.println(Rank.FIVE.toString());
    }
}




EnumSet

EnumSet은 enum 클래스로 작동하기 위해 특화된 Set 컬렉션입니다.

  • Set 특징 : 데이터를 중복해서 저장할 수 없으며 순서가 보장되지 않습니다.

EnumSet은 Set 인터페이스를 구현하고 AbstractSet을 상속받습니다.

EnumSet 사용시 주의 사항

  • 열거형 값만 포함할 수 있으며, 모든 값은 열거형이어야 합니다.
  • null을 추가할 수 없습니다.
  • 멀티쓰레드에 안전하지 않으므로 필요할 경우 외부에서 동기화홥니다.

 

EnumSet 사용하기

package azurealstn;

import java.util.EnumSet;

public class Main {
    public static void main(String[] args) {
        EnumSet<Rank> set = EnumSet.allOf(Rank.class); //모든 요소
        set.forEach((a) -> System.out.println(a));

        System.out.println("===================");

        EnumSet<Rank> set1 = EnumSet.noneOf(Rank.class); //빈 Rank 컬렉션
        set1.forEach((a) -> System.out.println(a));

        System.out.println("===================");

        EnumSet<Rank> set2 = EnumSet.of(Rank.THREE); //들어갈 요소를 직접 입력
        set2.forEach((a) -> System.out.println(a));

        System.out.println("===================");

        EnumSet<Rank> set3 = EnumSet.complementOf(EnumSet.of(Rank.FIVE)); //원하는 요소 제거
        set3.forEach((a) -> System.out.println(a));
    }
}

 

EnumSet의 장점

EnumSet의 모든 메소드는 산술 비트 연산을 사용하여 구현되므로 연산이 매우 빠릅니다.

 

EnumSet은 HashSet과 같은 다른 Set 구현체와 비교해서 데이터가 예상 가능한 순서로 저장되며 각 계산을 하는데 있어서 더 빠릅니다. 또한 HashSet처럼 데이터를 저장할 버킷을 찾는데 hashcode를 계산할 필요가 없습니다.

 

또흔 EnumSet은 더 작은 메모리를 사용합니다.




References

댓글