Enum
(열거형)은 자바에서 서로 연관된 상수들을 하나의 집합으로 정의하는 특별한 데이터 타입입니다. 열거형은 일반적으로 일정한 값들 중 하나를 선택해야 할 때 유용하며, 코드의 가독성과 안전성을 높여줍니다.
enum
키워드를 사용해 정의하며, 여러 상수를 모아 하나의 데이터 타입으로 표현할 수 있습니다.public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Week
라는 Enum 클래스에 포함된 상수들은 Week.class
파일이 메서드 영역에 로드되면서 함께 생성됩니다. Enum 상수는 각 상수에 대한 고유의 참조(포인터)를 가지고 있으며, MONDAY
와 SUNDAY
같은 Enum 상수들이 메서드 영역에 존재하게 됩니다.Week
객체는 메서드 영역의 상수 참조를 통해 접근할 수 있으며, Week.MONDAY
, Week.SUNDAY
와 같은 상수들이 실제 힙 영역에 존재하는 Enum 객체를 가리키게 됩니다.이 구조 덕분에 Enum 상수는 싱글톤(Singleton)으로 관리됩니다. 즉, 동일한 상수에 대해 하나의 인스턴스만 존재하며 메모리 효율성이 높습니다.
int
로 정의하기가장 기초적인 방법으로는 int
타입의 상수를 정의하는 방식이 있습니다.
public class Days {
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
// 나머지 요일도 정의
}
int
타입 상수는 다른 int
값들과 구분이 어려워, 실수로 잘못된 값이 들어와도 컴파일러에서 오류를 잡아내지 못합니다.1
, 2
, 3
으로 요일을 표현하면, 이를 해석하기 어렵고 코드 가독성이 떨어집니다.다음 단계로는 상수를 담은 인터페이스를 사용하는 방법입니다. 이 방식은 여러 상수를 하나의 인터페이스로 모아 관리하며, 클래스에서 이를 구현하거나 쉽게 참조할 수 있습니다.
public interface Days {
int MONDAY = 1;
int TUESDAY = 2;
int WEDNESDAY = 3;
// 나머지 요일도 정의
}
public interface Months {
int JANUARY = 1;
int FEBRUARY = 2;
// 나머지 월도 정의
}
int
값의 의미가 명확하지 않고, 상수값이 겹칠 경우(MONDAY
와 JANUARY
가 둘 다 1
인 경우) 혼란을 초래할 수 있습니다.위의 문제를 해결하기 위해 자바 1.5부터 Enum(열거형)이 도입되었습니다. Enum은 상수를 관리하는 새로운 방식으로, 타입 안전성을 보장하면서도 코드의 가독성과 유지보수성을 높입니다.
public enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
public enum Month {
JANUARY,
FEBRUARY,
MARCH,
// 나머지 월도 정의
}
Week.MONDAY
와 같이 명확하게 사용되기 때문에 다른 Enum
타입이나 잘못된 값을 넣는 실수를 방지할 수 있습니다.Week.MONDAY
처럼 읽기 쉬운 표현이 가능하여, 코드의 가독성이 크게 향상됩니다.ordinal()
, name()
, values()
등의 메서드를 제공하여 열거형 상수의 순서나 이름을 쉽게 확인할 수 있습니다.today
라는 변수는 스택 영역에 위치하고, 이는 Week
Enum 상수들을 담은 배열을 참조하고 있습니다. today
변수는 힙 영역에 저장된 각 Enum 상수를 참조하고 있습니다.today
변수는힙 영역에 위치한 Enum 상수 객체들(Week.MONDAY
, Week.SUNDAY
등)을 가리킵니다.public enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
// 열거형 생성자 - 각 열거 상수 초기화 시 호출
Week() {
System.out.println("생성자 호출");
}
}
package com.exam;
public class EnumEx01 {
public static void main(String[] args) {
// Week 열거형의 상수 MONDAY를 참조
Week monday = Week.MONDAY;
// 열거형 상수의 이름 출력
System.out.println(monday); // MONDAY 출력
System.out.println(Week.MONDAY); // MONDAY 출력
// 열거형 생성자 호출은 각 열거 상수가 처음 참조될 때 한 번씩 호출됨.
// 출력 시 각 상수별 생성자가 호출되며 "생성자 호출"이 출력됨.
// 즉, 열거형 상수 MONDAY에 처음 접근할 때 생성자 호출 메시지가 출력됨.
// name() 메서드: 열거형 상수의 이름을 문자열로 반환
String name = monday.name();
System.out.println("name = " + name);
// ordinal() 메서드: 열거형 상수의 순서(index)를 반환
Week friday = Week.FRIDAY;
int weekNum = monday.ordinal();
System.out.println("weekNum = " + weekNum); // 0 출력 (MONDAY의 순서)
weekNum = friday.ordinal();
System.out.println("weekNum = " + weekNum); // 4 출력 (FRIDAY의 순서)
// compareTo() 메서드: 열거형 상수 간 순서 비교
Week day1 = Week.MONDAY;
Week day2 = Week.FRIDAY;
int result1 = day1.compareTo(day2);
int result2 = day2.compareTo(day1);
System.out.println("result1 = " + result1); // 음수 출력 (MONDAY가 FRIDAY보다 앞에 위치)
System.out.println("result2 = " + result2); // 양수 출력 (FRIDAY가 MONDAY보다 뒤에 위치)
// valueOf() 메서드: 문자열로 열거형 상수를 가져옴
Week day = Week.valueOf("SUNDAY");
System.out.println(day); // SUNDAY 출력
// values() 메서드: 모든 열거형 상수를 배열로 반환
Week[] days = Week.values();
for (Week week : days) {
System.out.println(week); // 각 요일 상수를 출력
}
}
}
package com.exam;
public enum Season {
SPRING("봄"),
SUMMER("여름"),
AUTUMN("가을"),
WINTER("겨울");
private String season; // 각 열거형 상수에 대응하는 문자열 값을 저장할 변수
// 생성자: 열거형 상수가 처음 참조될 때 한 번씩 호출됨
private Season(String season) {
System.out.println("생성자 호출: " + season);
this.season = season;
}
// 열거형 상수의 문자열 값을 반환하는 메서드
public String getSeason() {
return season;
}
}
package com.exam;
import java.util.Calendar;
public class EnumEx02 {
public static void main(String[] args) {
// Calendar.WEEK_OF_YEAR - Enum을 사용한 옵션
Calendar calendar = Calendar.getInstance();
int week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(week);
}
}
package com.exam;
import java.util.Calendar;
public class EnumEx03 {
public static void main(String[] args) {
// Season 열거형의 상수 SPRING을 참조
Season spring = Season.SPRING;
// 열거형 상수의 이름과 설명 출력
System.out.println(spring); // SPRING 출력
System.out.println(spring.getSeason()); // "따뜻한 봄" 등 계절 설명 출력
// 모든 Season 열거형 상수의 이름과 설명 출력
for (Season season : Season.values()) {
System.out.println("현재 계절: " + season + ", 설명: " + season.getSeason());
// season : 현재 순회 중인 Season 열거형 상수
// season.getSeason() : 현재 Season 상수의 설명을 반환
}
}
}
✔️ 힙 영역에 객체가 생성된다?
enum
의 각 값(상수)은 실제로 각각 하나의 객체입니다. 예를 들어, enum Week { MONDAY, TUESDAY }
와 같이 선언하면 MONDAY
와 TUESDAY
는 각각 Week
클래스의 객체로 힙 영역에 생성됩니다. 이 객체들은 JVM이 실행될 때 생성되고, enum
이 여러 번 호출되더라도 같은 객체가 재사용됩니다.
✔️ enum도 클래스이다! (Week → Enum → Object)
Java의 enum
은 실제로 특별한 형태의 클래스입니다. 모든 enum
은 기본적으로 java.lang.Enum
클래스를 상속하며, Object
클래스의 메서드를 사용할 수 있습니다. 따라서 enum
의 각 상수는 Enum
클래스의 인스턴스로 취급됩니다. 예를 들어, Week
라는 이름의 enum
은 내부적으로 Week extends Enum<Week>
형태로 동작합니다.
✔️ 데이터 하나하나가 객체다?
enum
내에 정의된 각 상수는 enum
클래스의 객체로 취급됩니다. enum
타입을 사용할 때, 각 상수는 하나의 고유한 인스턴스가 됩니다. 예를 들어, enum Day { MONDAY, TUESDAY, WEDNESDAY }
에서는 MONDAY
, TUESDAY
, WEDNESDAY
가 모두 Day
클래스의 객체입니다.