[Java] Enum

케이·2022년 10월 9일
0

JAVA

목록 보기
15/17
post-thumbnail

학습한 내용을 정리한 포스팅입니다. 틀린 내용이 있다면 지적해주시면 감사하겠습니다.🙇🏻‍♀️

Enum?

상수를 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다.

값뿐만 아니라 타입도 체크하기 때문에 안전하다고 볼 수 있다(타입에 안전한 열거형 - typesafe enum)

enum 정의하는 방법

아래와 같이 정의하면 된다.

enum 이름 {상수이름1, 상수이름2, 상수이름3, ...}
public enum PizzaStatus {
		ORDERED,
		READY,
		DELIVERED;
}

위처럼 PizzaStatus를 정의했다. 사용할 때는 ‘이름.상수명’으로 사용할 수 있다. (PizzaStatus.ORDERED 등)

커스텀 Enum 메소드, ==와 Eqauls()

아래의 예시는 baeldung에 나와있는 예시를 보고 이해한 대로 다시 써보았습니다. 틀린 내용이 있다면 지적해주시면 감사하겠습니다

public class Pizza {
	private PizzaStatus status;
	public enum PizzaStatus {
		ORDERED,
		READY,
		DELIVERED;
	}

	public boolean isDeliverable(){
		if (getStatus() == PizzaStatus.READY) {
			return true;
		}
		return false;
	}

//아래에 getter와 setter가 있다고 하자.
}

위의 예시처럼 enum을 활용하는 메서드를 정의할 수도 있다. 여기에서 눈여겨 봐야하는 점은 isDeliverable 메소드에서 열거형 상수간 비교는 equals()가 아닌 ==로 비교 한다는 것이다. enum 타입은 JVM안에서 상수의 인스턴스로 존재하기 때문에 == 오퍼레이터를 사용한다. 사실 == 오퍼레이터는 컴파일 타임, 런타임 안전성을 제공한다.

if(testPizza.getStatus().equals(Pizza.PizzaStatus.DELIVERED)); 
if(testPizza.getStatus() == Pizza.PizzaStatus.DELIVERED);

==를 사용했을 경우 비교하는 두 값 모두 null일 수 있고 그렇게 된다면 NullPointerException이 발생하지 않는다. 이와 다르게 equals 메소드를 사용하면 NullPointerException이 발생할 것이다. 그렇기 때문에 == 오퍼레이터를 사용했을 때 런타임 안전성을 보장한다고 할 수 있다. 컴파일 시에도 만약 위와 같은 두 가지 경우가 있다고 한다면…

equals 메소드로 비교할 경우 enum의 값과 getStatus 메소드의 값이 우연히 같을 수 있다(true). 하지만 논리적으로는 false여야 한다. ‘==’ 오퍼레이터를 사용하면 이런 상황을 피할 수 있기 때문에 컴파일 타임 안전성이 보장된다.

아래와 같은 경우에는 비교할 수 없기 때문에 에러가 발생할 것이다. (비교할 대상인 TestColor라는 enum을 갖고 있지 않기 때문에)

if(testPizza.getStatus().equals(TestColor.RED));
if(testPizza.getStatus() == TestColor.RED);

enum이 제공하는 메소드 (values()와 valueOf())

values(): Enum 클래스가 가지고 있는 상수를 배열에 담아 리턴한다. 모든 열거형이 가지고 있는 것으로 컴파일러가 자동으로 추가 해준다.

static T valueOf(Class enumType,String name): 지정된 열거형에서 이름이 일치하는 열거형 상수를 리턴한다.


java.lang.Enum

Class Declaration

public abstract class Enum<E extends Enum> extends Object 
implements Comparable, Serializable

위에서 볼 수 있다시피 Enum은 추상 클래스로 우리는 Enum 클래스의 객체를 생성할 수 없다.

Enum 클래스는 10개의 유용한 메소드를 제공한다. 대부분은 오브젝트 클래스에서 오버라이딩 된 것이고 final로 선언되어 있어 프로그래머가 수정 할 수 없다. 아래는 해당 메소드들이다.

  • final String name(): Enum 상수의 이름을 리턴한다
  • final int ordinal(): Enum 상수가 정의된 순서를 정수로 반환한다.
  • String toString()
  • final boolean equals(Object obj): 특정한 객체가 Enum 상수를 가지고 있을 때 true를 리턴하고 그렇지 않으면 false를 리턴한다.
  • final int hasCode(): Enum 상수의 해시 코드를 리턴한다.
  • final int compareTo(E obj): 특정한 객체의 enum 순서를비교한다. 순서가 같으면 0, 높으면 양수, 낮으면 음수 반환.
  • static T valueOf(Class enumType,String name)
  • final Class getDeclaringClass(): Enum 상수의 타입에 해당하는 클래스 객체를 반환한다
  • final Object clone(): enum들이 복제되지 않도록 보장한다.
  • final void finalize(): enum 클래스들이 finalize 메소드를 가질 수 없음을 보장한다.

EnumSet

Enum 타입을 사용하기 위한 특화된 Set이다.

Enum 상수를 특정한 Set으로 표현하는 것은 내부의 비트 벡터 표현이 사용되기 때문에 효율적이라고 할 수 있다 == 산술 비트 연산을 사용하기 때문에 메모리를 적게 쓰고 연산이 빠르다. (이 부분은 내가 잘 이해한건지… 그리고 그게 왜..? 인지 아직 잘 모르겠어서 앞으로도 계속 찾아봐야 할 것 같다)

EnumSet은 RegularEnumSet과 JumboEnumSet, 2개의 구현체를 가지고 있는 추상 클래스인데 enum의 상수의 숫자에 따라 둘 중 알맞는 것이 선택된다. long으로 표현 가능한 경우는 RegularEnumSet이 사용되고 그렇지 않으면 JumboEnumSet이 사용된다.


참고

profile
삽질하며 깨닫고 배웁니다. (a.k.a 프로삽질러) + 이 구역의 회고왕

0개의 댓글