언어(Language)/Java

[Java] 자바 이넘(Enum: 열거형) 개념 정리 및 활용

잇트루 2022. 9. 19. 02:00
반응형

Enum(열거형: Enumerated Type)

Enum(이넘)은 자바에서 여러 상수들을 보다 편리하게 선언할 수 있도록 만들어진 문법 요소이다.

Enum은 주로 서로 연관 있는 내용들을 한데 모아 관리하기 쉽도록 하기 위해 사용한다.

예를 들어, 계절(봄, 여름, 가을, 겨울)이나 방위(동, 서, 남, 북), 과목(국어, 영어, 수학, 사회, 과학) 등과 같이 관련 있는 내용들을 묶어서 관리할 수 있다.

 

자바에서 상수는 변하지 않는 값을 의미하며, final 키워드를 사용하여 선언한다.

Enum은 서로 연관된 상수들의 집합으로 서로 관련 있는 변하지 않는 데이터를 다루는 데 사용한다.

 

Enum을 사용하는 이유

JDK 1.5 이전 버전에서는 enum 문법을 지원하지 않았다. 따라서 여러 개의 상수를 사용하기 위해서는 public static final 키워드를 통해 상수를 설정하여 사용했다.

// 계절
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int AUTUMN = 3;
public static final int WINTER = 4;

// 프레임워크
public static final int DJANGO = 1;
public static final int SPRING = 2; // 중복 발생!
public static final int NEST = 3;
public static final int REACT = 4;

하지만, 이러한 방법은 상수명이 중복되는 경우가 발생하여 에러가 발생할 수 있다.

 

인터페이스를 사용하여 중복 상수 문제를 해결하기도 했다.

interface Seasons {
    int SPRING = 1;
    int SUMMER = 2;
    int AUTUMN = 3;
    int WINTER = 4;
}

interface Frameworks {
    int DJANGO = 1;
    int SPRING = 2;
    int NEST = 3;
    int REACT = 4;
}

이는 중복 상수 문제를 해결할 수 있으나, 타입 안정성 문제가 발생하게 된다.

 

즉, 계절의 SPRING 상수와 프레임워크의 SPRING 상수는 각각 1과 2라는 정수 값을 갖게 된다.

이 둘은 열거하기 위해 임의로 주어진 값일 뿐 어떠한 의미를 가지고 있지 않다.

그럼에도 불구하고 서로 비교하는 코드를 작성할 수 있다.

if (Seasons.SPRING == Frameworks.SPRING) {
}

즉, Seasons의 SPRING과 Frameworks의 SPRING은 어떠한 관련도 없음에도 불구하고 에러가 발생하지 않는 코드를 작성할 수 있기 때문에 타입 안정성이 떨어진다고 할 수 있다.

 

그럼 다시, 타입 안정성 문제와 상수 중복 문제를 동시에 해결하기 위해서는 서로 다른 객체로 생성하여 사용해야 한다.

class Seasons {
    public static final Seasons SPRING = new Seasons();
    public static final Seasons SUMMER = new Seasons();
    public static final Seasons AUTUMN = new Seasons();
    public static final Seasons WINTER = new Seasons();
}

class Frameworks {
    public static final Frameworks DJANGO = new Frameworks();
    public static final Frameworks SPRING = new Frameworks();
    public static final Frameworks NEST = new Frameworks();
    public static final Frameworks REACT = new Frameworks();
}

이로써 상수 중복과 타입 안정성 문제를 해결할 수 있다.

하지만, 단순히 열거 용도로 사용하기 위해 위 코드처럼 작성하여 사용할 사람은 없을 것이다.

 

Enum 사용법

Enum은 상수 중복과 타입 안정성, 코드의 복잡성 문제들을 해결하기 위해 등장했다.

enum Seasons { SPRING, SUMMER, AUTUMN, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, REACT }

이렇게 간단하게 작성하여 앞서 발생한 상수 중복과 타입 안정성을 해결하면서도 코드를 간결하게 나타낼 수 있다.

 

또한, Enum은 앞서 객체를 생성하는 방법과 다르게 switch문과 함께 사용할 수 있다.

enum Seasons { SPRING, SUMMER, AUTUMN, WINTER }

public class EnumTest {
    public static void main(String[] args) {
        Seasons seasons = Seasons.SUMMER;

        switch (seasons) {
            case SPRING:
                System.out.println("봄");
                break;
            case SUMMER:
                System.out.println("여름");
                break;
            case AUTUMN:
                System.out.println("가을");
                break;
            case WINTER:
                System.out.println("겨울");
                break;
        }
    }
}

 

enum 정리

enum의 장점

  1. 중복 상수 문제를 해결할 수 있다.
  2. 타입 안정성을 보장한다.
  3. 보다 간결하고 가독성 있게 작성할 수 있다.
  4. switch문과 혼용할 수 있다.

 

Enum 활용

enum은 다음과 같이 정의할 수 있다.

enum EnumName {
ONE,
TWO,
THREE,
...
}

enum을 사용할 때, 상수는 대소문자를 혼용하여 작성이 가능하지만 관례적으로 대문자로만 작성한다. 또 enum 상수들에는 값을 따로 지정하지 않아도 자동으로 순차적으로 0부터 시작하는 정수 값을 할당한다.

 

enum의 접근 방법

enum에 선언된 상수에 접근하기 위해서는 ‘enum이름.상수명’을 통해 접근이 가능하다.

static 변수를 참조하는 것과 동일한 방법이다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        System.out.println(Seasons.SPRING); // SPRING 출력

        // Seasons.SPRING을 Seasons 타입의 참조변수에 할당
        Seasons seasons = Seasons.SPRING;

        // switch문을 활용하여 사용
        switch (seasons) {
            case SPRING:
                System.out.println("봄");
                break;
            case SUMMER:
                System.out.println("여름");
                break;
            case AUTUMN:
                System.out.println("가을");
                break;
            case WINTER:
                System.out.println("겨울");
                break;
        }
    }
}

 

Enum 메서드

name()

Enum 객체가 가지고 있는 문자열을 리턴한다. 문자열은 정의할 때 선언한 상수 이름과 동일하며 String 타입으로 반환한다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        // Seasons.SPRING을 Seasons 타입의 참조변수에 할당
        Seasons seasons = Seasons.SPRING;

        System.out.println(seasons.name());
    }
}
// 출력
SPRING

 

ordinal()

enum 객체의 순번을 int형으로 반환한다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        // Seasons.SPRING을 Seasons 타입의 참조변수에 할당
        Seasons seasons = Seasons.SPRING;

        System.out.println(seasons.ordinal());
    }
}
// 출력
0

 

compareTo(비교 값)

주어진 매개 값과 비교해서 순번 차이를 int형으로 리턴한다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        // Seasons.SPRING을 Seasons 타입의 참조변수에 할당
        Seasons seasons1 = Seasons.SPRING;
        Seasons seasons2 = Seasons.WINTER;

        System.out.println(seasons1.compareTo(seasons2));
    }
}
// 출력
-3

 

valueOf(String name)

주어진 문자열의 Enum 객체를 리턴한다. 반환 타입은 Enum 타입이다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        // Seasons.SPRING을 Seasons 타입의 참조변수에 할당
        Seasons seasons = Seasons.valueOf("SUMMER");
        System.out.println(seasons);
    }
}
// 출력
SUMMER

 

values()

모든 enum 객체들을 배열로 반환한다. 반환 타입은 enum[]이다.

enum Seasons {
    SPRING, // 0
    SUMMER, // 1
    AUTUMN, // 2
    WINTER  // 3
}

public class EnumTest {
    public static void main(String[] args) {
        // for문을 활용하여 접근 가능
        for (Seasons season : Seasons.values()) {
            System.out.println(season);
        }

        // Arrays.toString() 메서드를 활용 가능
        System.out.println(Arrays.toString(Seasons.values()));

        // length 사용 가능
        System.out.println(Seasons.values().length);
    }
}
반응형