<Java> Enum

라모스·2021년 9월 3일
0

Java☕

목록 보기
11/14
post-thumbnail

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

학습할 것

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

Intro. 열거형?

서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다. JDK1.5부터 새로 추가되었다. 자바의 열거형은 '타입에 안전한 열거형'이라서 실제 값이 같아도 타입이 다르면 컴파일 에러가 발생한다.

📌 기존 방식의 문제점?

  • 한 클래스에 final static으로 다 선언하기엔 네임충돌 발생 우려가 있고 복잡함
  • 인터페이스를 사용하면 위 문제는 해결되나, 타입의 안정성이 떨어짐

📌 enum의 장점

  • 코드가 단순해지고 가독성이 좋아짐
  • enum 키워드를 사용해서 구현의 의도가 열거임을 나타냄
  • 열거체를 비교할 때 실제 값 뿐만이 아니라 타입까지도 체크함(타입에 안전한 열거형)
  • 열거체의 상수값이 재정의되더라도 다시 컴파일 할 필요가 없다.

1. enum 정의하는 방법

다음과 같이 { } 안에 상수의 이름을 나열하기만 하면 된다.

enum 열거형 이름 { 상수명1, 상수명2, ... , 상수명n }

예시)

class Card {
    enum Kind { CLOVER, HEART, DIAMOND, SPADE }
    enum Value { TWO, THREE, FOUR }

    final Kind kind; // 타입이 int가 아닌 Kind임.
    final Value value;
}

사용하는 방법은 다음과 같이 '열거형이름.상수명'이다. 클래스의 static 변수를 참조하는 것과 동일하다.

class Unit {
    int x, y;
    Direction dir; // 열거형을 인스턴스 변수로 선언

    void init() {
        dir = Direction.EAST;
    }
}

2. enum이 제공하는 메소드

values()

열거 타입의 모든 열거 객체들을 배열로 만들어 리턴한다.

enum Direction {
    north, south, west, east
}

public class enum_ex {
    public static void main(String[] args) {
        for(Direction dir : Direction.values()) {
            System.out.println(dir);
        }
    }
}

valueOf()

매개 값으로 주어지는 문자열과 동일한 문자열을 가지는 열거 객체를 리턴한다.

enum Direction {
    north, south, west, east
}

public class enum_ex {
    public static void main(String[] args) {
        Direction dir = Direction.valueOf("north");
        System.out.println(dir); // 출력: north
    }
}

ordinal()

전체 열거 객체 중 몇 번째 열거 객체인지 알려준다. 열거 객체의 순번은 0부터 시작된다.

enum Direction {
    north, south, west, east
}

public class enum_ex {
    public static void main(String[] args) {
        Direction dir = Direction.west;
        System.out.println(dir.ordinal()); // 출력: 3
    }
}

name()

열거 객체가 가지고 있는 문자열을 리턴한다. 이때 리턴되는 문자열은 열거 타입을 정의할 때 사용한 상수 이름과 동일하다.

enum Direction {
    north, south, west, east
}

public class enum_ex {
    public static void main(String[] args) {
        Direction dir = Direction.south;
        String name = dir.name();
        System.out.println(name);
    }
}

compareTo()

매개값으로 주어진 열거 객체를 기준으로, 앞뒤로 몇 번째 위치하는지 비교한다.
만약 열거 객체가 매개값의 열거 객체보다 순번이 빠르다면 음수, 늦다면 양수가 리턴됨.

enum Direction {
    north, south, west, east
}

public class enum_ex {
    public static void main(String[] args) {
        Direction dir1 = Direction.west;
        Direction dir2 = Direction.east;

        int result1 = dir1.compareTo(dir2);
        int result2 = dir2.compareTo(dir1);

    	System.out.println("result1 = " +result1); // 출력 : result = -1
    	System.out.println("result2 = " +result2); // 출력 : result = 1
    }
}

3. java.lang.Enum

모든 enum들은 내부적으로 java.lang.enum 클래스에 의해 상속된다.

enum 생성자는 private이다.
자바에서 enum 타입은 열거형을 의미하는 특별한 형태의 클래스이다. 따라서 일반 클래스와 같이 생성자가 있어야 한다. 생성자를 만들어 주지 않아도 자바가 default로 생성자를 만들어 주긴 하지만, enum의 경우엔 생성자의 접근 제어자를 private로 지정한다.

enum 타입은 고정된 상수들의 집합으로, 런타임이 아닌 컴파일 타임에 모든 값을 알고 있어야 한다. 즉 다른 패키지나 클래스에서 enum 타입에 접근해서 동적으로 어떤 값을 정해줄 수 없다.

해당 enum 클래스 내에서 까지도 new 키워드로 인스턴스 생성이 불가능하다. 이렇게 하면 외부에서 접근 가능한 생성자가 없으므로 enum 타입은 실제적으로 final과 다름이 없다.

4. EnumSet

java.util 패키지의 EnumSet 클래스는 열거 타입 상수의 값으로 구성된 집합을 효과적으로 표현한다.
기본적으로 EnumSet은 abstract 키워드가 사용되기 때문에 객체로써 생성 및 사용이 불가하다.

public abstract class EnumSet { //EnumSet은 abstract하여 객체 생성이 불가능하다.
    ...
    
    //noneOf 메소드에서 상황에 따라 다른 구현체 객체들을 만들어서 반환해주고 있다.
    public static noneOf(...) {
        if (enumElementSize <= 64)
            return new RegularEnumSet<>(...);  
        else
            return new JumboEnumSet<>(...);
    }
}

메서드

  • EnumSet.allOf(): Enum 클래스 전체를 담는다.
  • EnumSet.noneOf(): 비어있는 EnumSet 반환
  • EnumSet.range(): Enum의 하위 집합을 만든다.
  • EnumSet.complementOf(): 매개변수로 전달된 요소로 제외한다.
  • EnumSet.copyOf(): 다른 EnumSet의 모든 요소를 복사하여 EnumSet을 만들 수 있다.

장점

  • 사용자는 어떤 구현 객체가 적합한지 몰라도 상관없다.
  • 사용자는 빈번하게 발생되는 EnumSet 초기화 과정을 간단히 진행할 수 있다.
  • EnumSet의 확장성과 유지보수상의 이점

References

  • Java의 정석 3판
profile
Step by step goes a long way.

0개의 댓글