공부방/JAVA

Enum - 백기선 자바라이브스터디

EVO. 2023. 9. 22. 17:30

Enum이란, 서로 관련된 상수를 여러개 정의할 때 사용한다. 

Enum(열거형)을 써야하는 이유는 다음과 같다.

  • 허용되는 값들을 제한할 수 있다
  • 리펙토링 시 변경범위가 최소화된다. 내용의 추가가 있어도 Enum 코드 외에 수정할 필요가 없다 
  • 자바의 Enum은 그외에 다양한 기능을 제공한다. 
  • 더 자세한 내용은 이펙티브자바에서 다루겠다 

Enum 정의하는 방법

가장 기본적인 방법으로 아래와 같이 상수를 정의한다. 

이제 여기서 각 상수에 가장 관련있는 값인 가격과 한국식 명을 추가하고 싶으면 생성자를 추가한다.

생성자에 변수말고도 각 상수마다 필요한 계산이 있다면 특정 상수에 함수를 관련 시키게 할 수 있다.

 

예를들면 삼성이 후원하는 매장에서 삼성노트북을 사면 할인을 해주는 그런 로직이 필요하다면 다음과 같이 만들면 된다.
추가적으로 가격은 매번 바뀔 수 있기 때문에 상수로 정의하지 않고 입력을 받으면 계산을 하는 식으로 바꾼다.

 

함수만 있어서는 유용하게 사용할 수 없다. 메소드를 추가하여 함수 expression을 사용해야 한다.

Enum이 제공하는 메소드

메서드 설명
T[] values() 해당 enum 타입에 정의된 상수 배열을 반환
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환(0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환

 

바이트 코드 분석

이번 Enum은 바이트 코드를 보면 새롭게 알 수 있는 점이 있다. 다음과 같이 컴파일러는 자동으로 추가해주는게 많다.

컴파일러가 values()/valueOf() 메소드 추가 

 

 

java.lang.Enum

바이트코드를 보면 Enum클래스를 상속받는 데 어떤 기능을 사용할 수 있는지 살펴보겠다

String name()

private final String name;

public final String name() {
   return name;
}

열거형 상수의 이름을 해당 열거형 선언에 선언된 대로 정확하게 반환한다. 

개발자들은 toString()메서드를 사용해야 한다. 이 메서드는 주로 정확성이 중요한 특수한 상황에서 사용하도록 설계된 것이다.

 

public final int ordinal()

public final int ordinal() {
        return ordinal;
    }

대부분의 프로그래머는 이 메서드를 쓸 일이 없다. 이 메서드는 EnumSet과 EnumMap 같이 열거 타입 기반의 범용 자료구조에 쓸 목적으로 설계되었다. 이 메서드를 의존하는 코드를 개발자가 작성하는 것은 안티패턴이다.

 

T valueOf(Class enumType, String name)

지정된 열거형에서 name과 일치하는 열거형을 반환하며 만약 존재하지 않는다면 IllegalArgumentExcpetion이 발생된다.

 

EnumSet

EnumSet의 상속 구조

출처 : https://www.geeksforgeeks.org/enumset-class-java/

특징

  • enum 값만 포함할 수 있고, 모든 값은 동일한 enum 에 속해야 함
  • null 값을 추가하는 것을 허용하지 않으며, 시도하면 NullPointerException 이 발생
  • thread 로부터 안전하지 않으므로, 필요한 경우 외부에서 동기화해야 함
  • HashSet 보다 훨씬 빠른 고성능 구현체
  • iterator 를 사용한 복제에서, fail-safe 하므로 컬렉션을 반복하면서 컬렉션이 수정될 때 ConcurrentModificationException 이 발생하지 않음
  • Enumset 의 모든 메서드는 산술 비트 연산자를 이용하여 구현

사용 이유

  • EnumSet과 HashSet을 비교했을 때 보통 전자가 빠른데, 값을 예측 가능한 순서로 저장하여, 각각의 계산에 단 하나의 비트만 검사하면 되기 때문이다.
  • HashSet과는 달리 정확한 버킷을 찾기 위해 해시코드를 연산할 필요가 없으며, 또한 비트 벡터의 특성으로 인해 EnumSet은 매우 작고 효율적임(메모리 덜 사용)

사용 예제

실행결과

> Task :EnumSetExample.main()
set1 = [BANANA, ORANGE]
set2 = [APPLE]
set3 = [APPLE, BANANA, ORANGE]
set4 = [APPLE, BANANA, ORANGE]
  • of(E e1, E e2) :  지정된 요소를 포함하는 열거형 집합을 처음에 생성
  • complementOf(EnumSet<E> s) : 지정된 열거형 집합과 동일한 요소 유형으로 열거형 집합을 생성하며, 처음에는 지정된 집합에 포함되지 않은 이 유형의 모든 요소를 포함
  • allOf(Class<E> emementType) : 지정된 요소 유형의 모든 요소를 포함는 열거형 집합을 만든다.
  • range(E from, E to) : 지정된 두 엔드포인트에 정의된 범위의 모든 요소를 포함하는 열거형 집합을 처음에 생성

 

 

 

 

 

참고

https://wisdom-and-record.tistory.com/52

 

[Java Study 11주차] Enum

본 포스팅은 백기선님이 진행하시는 자바 스터디 를 진행하며 혼자 공부하고 이해한 내용을 바탕으로 정리한 글입니다. 오류나 지적 사항이 있다면 댓글로 알려주시면 감사하겠습니다. Enum이란

wisdom-and-record.tistory.com

 

https://www.geeksforgeeks.org/enumset-class-java/

 

EnumSet in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org