[Java]열거 타입(Enum)

Euiyeon Park·2024년 9월 21일

Java

목록 보기
14/16
post-thumbnail

🧛 열거 타입(Enum, Enumeration)

  • 요일과 관련된 데이터: 월, 화, 수, 목, 금, 토, 일
  • 계절과 관련된 데이터: 봄, 여름, 가을, 겨울

이와 같이 한정된 값만을 갖는 타입열거 타입(Enumeration Type)이라고 한다.


열거 타입은 한정된 값인 열거 상수(Enumeration Constant)중에서 하나의 상수를 저장한다.

public enum Week {
	MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

Week today = Week.SATURDAY;
  • 열거 타입: Week
  • 열거 상수: Monday , . . . , SUNDAY

🧛 열거 타입의 특징

  • 열거 타입은 참조 타입이므로, 열거 타입 변수null값을 저장할 수 있다.
  • 일반적인 상수를 사용할 경우 잘못된 값을 전달할 가능성이 있지만,
    열거 타입은 컴파일 시점에 오류를 잡을 수 있어 타입 안정성을 보장한다.
  • 열거 상수는 의미있는 이름을 가지기 때문에 코드 가독성이 좋아진다.
  • 열거 타입은 고정된 상수 집합을 제공하며, 각 상수는 열거 타입의 고유한 인스턴스다.
  • enum으로 정의된 상수들은 프로그램이 실행될 때 한 번만 생성되며, 재사용된다.

🧛 열거 타입의 필드, 메소드, 생성자

열거 타입은 상수 외에도 필드, 메소드 생성자를 가질 수 있다.
이 기능을 통해 상수에 부가적인 속성을 추가하고 다양한 동작을 수행할 수 있다.

🎃 열거 타입의 생성자

열거 타입의 목적은 미리 정의된 상수들을 고정된 인스턴스로 제공하는 것으로,
사용자는 열거 타입의 상수들을 직접 생성할 수 없고,
자바 컴파일러가 자동으로 필요한 인스턴스를 만들어 관리한다.

따라서 열거 타입의 생성자는 public 접근 제어자를 사용할 수 없으며
열거 타입의 생성자는 항상 private 또는 default로 정의되어야 한다.

열거 타입의 생성자가 public일 경우, 외부에서 열거 타입의 새로운 인스턴스를 생성할 수 있기 때문에 public허용하지 않는다.


🧛 열거 타입 코드 예제 살펴보기

public enum CoffeeType {
  	// 열거 상수
	ESSPRESSO(30, "Strong),
  	AMERICANO(120, "Mild"),
  	LATTEE(150, "Creamy");
  
  	// 필드
  	private int caffeine;
  	private String flavor;
  
  	// 생성자 - private, default만 허용한다.
  	CoffeeType(int caffeine, String flavor){
  		this.caffeine = caffeine;
  		this.flavor = flavor;
  	}
  
  	// 메소드
  	public int getCaffeine(){
  		return caffeine;
 	}
  
  	public String getFlavor(){
  		return flavor;
  	}
}

public class Main {
    public static void main(String[] args) {
        CoffeeType myCoffee = CoffeeType.LATTE;

        System.out.println("My coffee's caffeine: " + myCoffee.getCaffeine());
        System.out.println("My coffee's flavor " + myCoffee.getFlavor());
    }
}

🎃 1. 열거 타입 상수는 "객체"다.

  • 열거 타입은 단순한 상수가 아니라 미리 생성된 객체다.
  • ESSPRESSO, AMERICANO, LATTEE는 각각 고유한 객체이며,
    해당 객체가 생성될 때 필요한 값들을 생성자를 통해 초기화한다.

🎃 2. 열거 타입의 생성자와 필드 초기화

열거 상수들에 추가적인 정보를 담고 싶을 때 필드를 사용하고,
그 값들을 초기화 하기 위해 생성자가 필요하다.

ESSPRESSO(30, "Strong");

이렇게 열거 상수를 정의할 때, 열거 상수의 30, "Strong"생성자의 매개 변수로 전달한다.

  • 열거 상수(ESSPRESSO, AMERICANO, LATTE)는 열거 타입이 정의될 때 한번만 생성된다.
  • 이때 열거 상수는 생성자를 통해 고유한 값을 초기화 한다.
  • 열거 상수(ESSPRESSO, AMERICANO, LATTE)는 각각 CoffeeType 클래스의 객체로 생성된다.
    • 각 상수는 생성자를 호출하면서 자신만의 caffeineflavor 값을 전달받아 초기화된다.
    • ESPRESSO는 30mg의 카페인과 "Strong"이라는 맛으로 초기화되며,
      이는 해당 상수가 프로그램 실행 중인 동안 계속 유지된다.

🎃 3. 사용자가 new 를 하지 않는 이유

CoffeeType myCoffee = CoffeeType.LATTE;
  • CoffeeType.LATTEE이미 생성된 고정된 객체를 참조한다.
    사용자가 new로 객체를 생성할 필요가 없는 이유는,
    열거 상수(LATEE )는 미리 생성되어 고정된 객체이기 때문이다.
  • 열거 타입이 선언되는 순간, ESPRESSO, AMERICANO, LATTE라는 객체들을 한 번만 생성하고,
    이후 코드에서 이를 재사용하게 된다.
    이때 각 상수는 미리 생성된 고유한 객체이므로, 사용자가 이를 직접 생성할 필요가 없다.

🎃 4. 생성자 호출 시점

컴파일 타임

자바 컴파일러가 열거 타입을 처리하고 열거 상수들을 미리 정의하지만,
이때 실제로 객체가 생성되지는 않고 열거 타입의 구조와 상수들의 선언만이 처리된다.

런타임

프로그램 실행 중, 해당 열거 타입이 처음으로 사용되거나 참조될 때
JVM이 열거 타입의 클래스를 로드한다.
이때 열거 상수 각각에 대해 생성자가 호출되고, 상수 객체가 메모리에 생성된다.

LATTE(150, "Creamy"); 

LATTE 객체는 150mg의 카페인과 "Creamy"라는 맛을 가지는 고유한 객체로 존재하게 된다.

이후 CoffeeType.LATTE를 호출할 때마다, 자바는 이 고유한 객체를 반환한다.


🧛 열거 타입의 메소드

열거 타입에 기본적으로 제공되는 메소드

  • values() : 열거 타입의 모든 상수를 배열로 반환
  • ordinal() : 열거 상수가 정의된 순서(인덱스)를 반환
  • name() : 열거 상수의 이름을 반환
public class Main {
    public static void main(String[] args) {
        CoffeeType myCoffee = CoffeeType.LATTE;

        System.out.println("My coffee is " + myCoffee.name() 
        + "and its ordinal is " + myCoffee.ordinal() );

        for(CoffeeType coffee : CoffeeType.values()){
            System.out.println(coffee.name() + " has " 
            + coffee.getCaffeine() + "mg of caffeine");
        }
    }
}
  • valueOf() : 문자열 값을 기반으로 해당 열거 상수를 반환하는 정적 메소드
CoffeeType myCoffee = CoffeeType.valueOf("LATTE");

🪄 valueOf() 메소드에 잘못된 문자열을 넣었을 때는 IllegalArgumentException이 발생한다.


🧛 열거 타입과 Switch문

열거 타입은 switch문과 함께 자주 사용된다.
switch문에서 열거 타입 상수를 사용할 수 있어 코드가 더 간결해진다.

public class Main {
    public static void main(String[] args) {
        CoffeeType coffee = CoffeeType.ESPRESSO;

        switch (coffee) {
            case ESPRESSO:
                System.out.println("Espresso is strong!");
                break;
            case AMERICANO:
                System.out.println("Americano is mild.");
                break;
            case LATTE:
                System.out.println("Latte is creamy.");
                break;
        }
    }
}

🪄 switch문에서 사용할 수 있는 값

  • 정수형 타입(long은 사용할 수 없다), 문자형, 문자열, 상수(final), 열거형(enum)

🧛 열거 타입의 제약

  • 열거 타입은 상속을 할 수 없다.
    모든 열거 타입은 암묵적으로 java.lang.Enum을 상속받기 때문에
    다른 클래스를 상속받을 수 없습니다.

  • 열거 상수는 new 키워드를 사용하여 생성할 수 없다.
    열거 상수는 미리 정의된 고정된 인스턴스다.

profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글