목차
- enum이란?
- enum을 사용하여 상수 정의하기
- enum과 생성자
- enum JVM메모리 구조
- enum 메소드
- EnumSet
- enum 활용하기
1. enum이란?
- enum(enumeration)은 관련이 있는 상수들의 집합이다.
- enum은 자바 1.5버전부터 새롭게 추가되었다.
- 자바에서는 final로 String과 같은 문자열이나 숫자들을 나타내는 기본 자료형의 값을 고정할 수 있는데, 그 고정된 값을 상수(constant)라고 한다.
- 자바의 Enum은 상수 그룹을 정의하는 데 쓰이는 특수한 자바 클래스이다.
- enum도 클래스고 객체이기 때문에, object클래스를 상속받고, object클래스의 메소드를 사용할 수 있다.
- java의 컴파일러는 enum을 아래와 같은 형태로 바꾼다.
enum{
}
final class Week extends java.lang.Enum<Week>{
}
- final클래스이므로 enum클래스를 다른 클래스가 상속받을 수 없다.
- 자바는 다중 상속을 허용하지 않는데, java.lang.Enum을 상속받고 있으므로 다른 클래스를 상속받을 수 없다.
- 인터페이스 구현은 가능하다.
2. enum을 사용하여 상수 정의하기
- 열거형을 만들기 위해선 class, interface 대신 enum키워드를 사용하고 상수를 쉼표로 구분하면 된다.
enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
SUNDAY
}
→ 7개의 요일을 열거 타입으로 상수화 해 놓은 것이다. MONDAY부터 SUNDAY까지를 ‘열거 상수라고 한다. 열거 상수들은 대문자로 표기한다.
- 위의 코드에서 선언된 열거 상수들은 모두 하나의 객체로 사용할 수 있다.
- enum을 사용하지 않고 class를 이용하여 상수들을 정의하면 아래의 코드와 같다.
class Week {
public static final Week MONDAY = new Week();
public static final Week TUESDAY = new Week();
public static final Week WEDNESDAY = new Week();
public static final Week THURSDAY = new Week();
public static final Week FRIDAY = new Week();
public static final Week SATURDAY = new Week();
public static final Week SUNDAY = new Week();
→ class와 enum의 코드를 비교해 보면 enum을 사용하는 이유를 알 수 있다.
- 코드가 단순해지고 가독성이 좋아집니다.
- 인스턴스의 생성과 상속을 방지합니다.
- 키워드 enum을 사용하기 때문에 구현의 의도가 열거임을 분명하게 나타낼 수 있습니다.
3. enum과 생성자
- enum은 클래스이므로 생성자를 가질 수 있다.
- 생성자를 만들지 않으면 다른 클래스와 마찬가지로 디폴트 생성자가 만들어지지만, 차이점은 생성자의 접근 제어자가 private라는 것이다.
- 위와 같은 이유로 enum클래스에서 선언한 상수들은 클래스가 로드될 때 하나의 인스턴스만 생성되어 사용된다.
- enum클래스 내에서 까지도 new키워드로 인스턴스 생성이 불가능하고, newInstance(), clone() 등의 메소드도 사용불가하다.
- enum클래스의 원소에 추가 속성 부여
enum Week {
MONDAY("월요일"),
TUESDAY("화요일"),
WEDNESDAY("수요일"),
THURSDAY("목요일"),
FRIDAY("금요일"),
SATURDAY("토요일"),
SUNDAY("일요일");
private final String name;
Week(String name) {
this.name = name;
}
public String getName(){
return this.name;
}
}
→ 추가 속성을 enum클래스의 필드에 설정해주고 생성자의 파라미터를 통해 초기화할 수 있다. getter메소드를 통해 해당 속성을 필요할 때에 사용할 수 있게 합니다.
4. enum과 JVM메모리 구조

Week today = Week.SUNDAY;

→ today는 스택 영역에 생성되고, today에 저장되는 값은 Week.SUNDAY 열거 상수가 참조하는 객체의 번지이다. 그래서 Week.SUNDAY와 today는 같은 객체를 참조한다.
today == Week.SUNDAY; //true
5. Enum 메소드
- enum은 컴파일 타임에 Enum이라는 클래스를 상속한다. 즉, enum에서 사용할 수 있는 메소드는 Enum의 메소드이다.
- name()
- 열거 객체가 가지고 있는 문자열을 반환하는데, 이때 문자열은 열거 객체를 선언할 때 명시한 상수 이름이다.
Week today = Week.MONDAY;
System.out.println(today.name()); //결과: MONDAY
- ordinal()
- 해당 열거 객체가 열거 타입에서 몇 번째 순번인지 반환한다. 이때, 순번이란 열거 타입을 정의할 때 명시된 순서로 0부터 시작한다.
public enum Week {
MONDAY, // 0
TUESDAY, // 1
WEDNESDAY, // 2
THURSDAY, // 3
FRIDAY, // 4
SATURDAY, // 5
SUNDAY // 6
}
System.out.println(Week.MONDAY.ordinal()); // 0
System.out.println(Week.SUNDAY.ordinal()); // 6
- compareTo()
- 두 열거 객체간의 순번을 비교하여 상대적 순번 차이를 반환하는 메소드이다.
System.out.println(Week.MONDAY.compareTo(Week.SUNDAY)); // -6
System.out.println(Week.SATURDAY.compareTo(Week.WEDNESDAY)); // 3
- valueOf()
- 열거 객체의 상수명과 동일한 문자열을 입력받아, 일치하는 열거 객체를 반환한다. 외부에서 문자열을 입력받아 열거 객체로 변환할 때 사용한다.
Week today = Week.valueOf("WEDNESDAY");
System.out.println(today); // WEDNESDAY
- values()
- enum에 선언된 모든 열거 객체를 순서대로 배열을 만든다.
for (Week day : Week.values()) {
System.out.println(day);
}
/*
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
*/
6. EnumSet
- EnumSet은 enum클래스로 작동하기 위해 특화된 Set 컬렉션이다.
- EnumSet은 Set인터페이스를 구현하고 AbstractSet을 상속하고 있다.
- EnumSet을 사용할 때 고려할 사항
- 열거형 값만 포함 할 수 있고, 모든 값은 동일한 열거형이어야 한다.
- null을 추가할 수 없다.
- 스레드에 안전하지 않으므로, 필요한 경우 외부에서 동기화한다.
enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
SUNDAY
}
- allOf()
EnumSet<Week> set = EnumSet.allOf(Week.class);
→ allOf()메소드를 통해 EnumSet을 만들 수 있다.
- noneOf()
EnumSet<Week> set = EnumSet.noneOf(Week.class);
→ of()를 사용하면, 들어갈 요소를 직접 입력하여 EnumSet을 생성할 수 있다.
- complementOf()
EnumSet<Week> set = EnumSet.complementOf(EnumSet.of(Week.BLACK,Week.BLUE));
→원하는 요소를 제거하고 EnumSet을 생성할 수 있다.
7. enum 활용하기
- 같은 의미이지만, 여러 개의 표현(타입)으로 나눠질 경우 Enum으로 묶어주면 명시적으로 활용이 가능하다.
public enum TableStatus {
Y("1", true);
N("0", false);
private String tableValue1;
private boolean tableValue2;
TableStats(String tableValue1, boolean tableValue2) {
this.tableValue1 = tableValue1;
this.tableValue2 = tableValue2;
}
public String getTableValue1() {
return this.tableValue1;
}
public String getTableValue2() {
return this.tableValue2;
}
}
→ (Y, “1”, true), (N, “0”, false)은 같은 의미를 지닌 값들을 묶어놓은 것이다. TableStatus의 enum타입을 전달받기만 한다면, 그에 맞춘 table1, table2값을 바로 얻을 수 있다.
- @Getter를 이용하면 get메소드도 제거할 수 있어 매우 깔끔해진다.
- Enum을 사용하지 않을 경우
public class Case {
public String toTable1Value(String originValue) {
if("Y".equals(originValue)){
return 1;
} else{
return 0;
}
}
public String toTable2Value(String originValue) {
if("Y".equals(originValue)){
return true;
} else{
return false;
}
}
}
→ 위 코드와 같이 같은 의미를 지니지만 다른 타입의 값을 원할 경우마다 메소드를 만들어 if문을 사용해 주어야 한다. 그러면 너무 불필요한 코드량이 많아지기 때문에 enum을 사용하는 것이 훨씬 효율적입니다.
- 비즈니스 로직 자체를 종류별로 타입화
- Java8부터 도입된 함수형 인터페이스를 통해서 조금 더 깔끔한 비즈니스 로직 처리를 기대할 수 있다.
public enum CalcType {
CALC_A(value->value),
CALC_B(value->value*2);
Function<Long,Long> expression;
CalcType(Function<Long,Long> expression) { this.expression = expression; }
public long calculate(long value) {
return expression.apply(value);
}
}
CALC_A.calculate(2000);
[Reference]
https://www.nextree.co.kr/p11686/
https://techblog.woowahan.com/2527/
https://scshim.tistory.com/253
질문 답변
1) 내부적으로 어떤 식으로 데이터를 저장하고 있나?
정수 값으로 매핑
예를 들어, 첫 번째 상수는 0, 두 번째 상수는 1, 세 번째 상수는 2와 같이 순차적으로 매핑될 수 있습니다.
enum Weekday {
MONDAY, // 0
TUESDAY, // 1
WEDNESDAY, // 2
}
즉, 대부분의 언어에서 Enum 클래스는 내부적으로 정수 값을 사용하여 각 상수를 나타내며, 이 값들은 메모리에 해당 정수 값으로 저장됩니다
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
→ Enum클래스 인스턴스를 만들어 낼 때 생성자에서 열거 상수의 이름(name)과 순서(ordinal)를 초기화하고 내부적으로 저장합니다.
2) enum 클래스 필드에 추가할 수 있는 속성에는 어떤 것들이 있나요?
- enum 클래스 필드에 추가할 수 있는 속성에는 제한이 없다.
'JAVA' 카테고리의 다른 글
Enum 조회 성능 향상하기(feat. Map) (1) | 2025.01.21 |
---|---|
Arrays.asList()와 List.of()의 차이 (0) | 2024.09.30 |
stream.toList() 와 .collect(Collectors.toList()) 차이 (0) | 2024.09.30 |
equals()와 hashcode() (1) | 2023.09.06 |