처음부터 차근차근

[Java] Enum 본문

Language/Java

[Java] Enum

HangJu_95 2024. 8. 9. 11:34
728x90

Enum Type

enum은 Enumeration의 줄임말로, 번역하면 열겨라는 뜻이다.
enum은 일련의 명명된 상수들의 집합을 정의하는 것을 의미하며, 프로그래밍에서는 이러한 상수들을 사용하여 코드 내에서 미리 정의된 값들의 집합을 나타낸다.

Enum은 왜 만들어졌을까??

Enum은 타입 안전 열거형 패턴(Type-Safe Enum Pattern)으로부터 만들어졌다.
간단한 예시로, 특정 문자열을 사용해서 회원을 구분하는 경우, 아래와 같은 문제점이 발생할 수 있다.

  • 문자열은 오타가 발생하기 쉽고, 유효하지 않은 값이 입력될 수 있다.
  • "Gold", "gold" 등 다양한 형식으로 문자열을 입력할 수 있다.

이러한 문제를 해결하기 위해 특정 범위로 값을 제한할려고 하였으며, 나열한 항목만 사용할 수 있도록 아래 예시와 같은 코드가 만들어졌다.

public class ClassGrade {
    public static final ClassGrade BASIC = new ClassGrade();
    public static final ClassGrade GOLD = new ClassGrade();
    public static final ClassGrade DIAMOND = new ClassGrade();

    // private 생성자 추가 -> 객체를 생성하지 못하도록 막는다.
    private ClassGrade() {}
}

이렇게 타입 안전 열거형 패턴을 만든다면

  • 타입 안정성 향상: 정해진 객체만 사용할 수 있기 때문에, 잘못된 값을 입력하는 문제를 근본적으로 방지할 수 있다.
  • 데이터 일관성: 정해진 객체만 사용하므로 데이터의 일관성이 보장된다.
  • 제한된 인스턴스 생성: 클래스는 사전에 정의된 몇 개의 인스턴스만 생성하고, 외부에서는 이 인스턴스들만 사용할 수 있도록 한다. 이를 통해 미리 정의된 값들만 사용하도록 보장한다.
  • 타입 안전성: 이 패턴을 사용하면, 잘못된 값이 할당되거나 사용되는 것을 컴파일 시점에 방지할 수 있다. 예를 들어, 특정 메서드가 특정 열거형 타입의 값을 요구한다면, 오직 그 타입의 인스턴스만 전달할 수 있다. 여기서는 메서드의 매개변수로 ClassGrade 를 사용하는 경우, 앞서 열거한 BASIC , GOLD , DIAMOND 만 사용할 수 있다.

단, 이러한 패턴을 구현하려면 코드를 많이 작성해야 한다. 따라서 Java에서는 편하게 사용할 수 있도록 Enum이라는 타입을 만들어줬다.

package enumeration.ex3;

public enum Grade {
    BASIC, GOLD, DIAMOND
}

타입 안전 열거형 패턴보다 오히려 더 간단하게 만들 수 있다.

Enum의 특징

  • 열거형도 Class이다.
  • 열거형은 자동으로 java.lang.Enum을 상속 받는다.
  • 외부에서 임의로 생성할 수 없다.

간단하게 Enum을 실행시켜보자.

public class EnumRefMain {
    public static void main(String[] args) {
        System.out.println("class BASIC = " + Grade.BASIC.getClass());
        System.out.println("class GOLD = " + Grade.GOLD.getClass());
        System.out.println("class DIAMOND = " + Grade.DIAMOND.getClass());

        System.out.println("ref BASIC = " + refValue(Grade.BASIC));
        System.out.println("ref GOLD = " + refValue(Grade.GOLD));
        System.out.println("ref DIAMOND = " + refValue(Grade.DIAMOND));
    }

    private static String refValue(Object grade) {
        return Integer.toHexString(System.identityHashCode(grade));
    }
}

실행결과

class BASIC = class enumeration.ex3.Grade
class GOLD = class enumeration.ex3.Grade
class DIAMOND = class enumeration.ex3.Grade

ref BASIC = x001
ref GOLD = x002
ref DIAMOND = x003

실행 결과를 보면 상수들이 열거형으로 선언한 타입인 Grade 타입을 사용하는 것을 확인할 수 있다. 그리고 각각의 인스턴스도 서로 다른 것을 확인할 수 있다.
참고로 열거형은 toString() 을 재정의 하기 때문에 참조값을 직접 확인할 수 없다. 참조값을 구하기 위해 refValue() 를 만들었다.

  • System.identityHashCode(grade) : 자바가 관리하는 객체의 참조값을 숫자로 반환한다.
  • Integer.toHexString() : 숫자를 16진수로 변환, 우리가 일반적으로 확인하는 참조값은 16진수
    열거형도 클래스이다. 열거형을 제공하기 위해 제약이 추가된 클래스라 생각하면 된다.

Enum의 장점

  • 타입 안정성 향상: 열거형은 사전에 정의된 상수들로만 구성되므로, 유효하지 않은 값이 입력될 가능성이 없다. 이런 경우 컴파일 오류가 발생한다.
  • 간결성 및 일관성: 열거형을 사용하면 코드가 더 간결하고 명확해지며, 데이터의 일관성이 보장된다.
  • 확장성: 새로운 회원 등급을 타입을 추가하고 싶을 때, ENUM에 새로운 상수를 추가하기만 하면 된다.

Enum 주요 메서드

  • values(): 모든 ENUM 상수를 포함하는 배열을 반환한다.
  • valueOf(String name): 주어진 이름과 일치하는 ENUM 상수를 반환한다.
  • name(): ENUM 상수의 이름을 문자열로 반환한다.
  • ordinal(): ENUM 상수의 선언 순서(0부터 시작)를 반환한다.
  • toString(): ENUM 상수의 이름을 문자열로 반환한다. name() 메서드와 유사하지만, toString() 은 직접 오버라이드 할 수 있다.

참고로, ordinal()의 값은 가급적 사용하지 않는 것이 좋다. 왜냐하면 이 값을 사용하다가 중간에 상수를 선언하는 위치가 변경되면 전체 상수의 위치가 모두 변경될 수 있기 때문이다.

Enum 예시 코드

public enum Grade {
    BASIC(10), GOLD(20), DIAMOND(30);

    // class처럼 내부 맴버를 가질 수 있다.
    private final int discountPercent;

    // 또한 생성자도 사용이 가능하다.
    // 단, 생성자에 접근이 불가능하도록 막혀있다. private이라고 생각하면 편하다.
    Grade(int discountPercent) {
        this.discountPercent = discountPercent;
    }

    // 메서드도 가질 수 있다.
    public int getDiscountPrecent() {
        return discountPercent;
    }

    public int discount(int price) {
        return price * discountPercent / 100;
    }
}

참조

 

김영한의 실전 자바 - 중급 1편 강의 | 김영한 - 인프런

김영한 | 실무에 필요한 자바의 다양한 중급 기능을 예제 코드로 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을

www.inflearn.com

 

'Language > Java' 카테고리의 다른 글

[Java] 날짜와 시간  (4) 2024.08.27
[Java] Wrapper Class  (0) 2024.07.31
[Java] String 클래스  (0) 2024.07.31
[Java] 불변 객체  (0) 2024.07.26
[Java] Object 클래스  (0) 2024.07.24