Enum은 클래스이 이므로 생성자, 필드, 메소드를 가질 수 있다.
public enum Fruit {
APPLE, PEACH, BANANA;
Fruit() {
System.out.println("call constructor " + this);
}
}
public class Main {
public static void main(String[] args) {
Fruit type = Fruit.APPLE;
switch (type) {
case APPLE:
System.out.println("57 kcal");
break;
case BANANA:
System.out.println("30 kcal");
break;
case PEACH:
System.out.println("88 kcal");
break;
}
}
}
call constructor APPLE
call constructor PEACH
call constructor BANANA
57 kcal
Call Constructor가 3번이 출력된 것은 enum Fruit 클래스의 필드 수만큼 호출되었음을 확인할 수 있다. 각 각의 필드가 인스턴스 생성하면서 생성자를 호출했다는 이야기
하지만 enum 생성자의 접근제한자를 public으로 변경하면 에러가 발생한다. 이는 enum 클래스의 생성자의 접근 제한자는 private과 package-private만 허용하고 있기 때문이다. 이는 상속받은 Enum클래스의 생성자가 protected로 제한하고 있기 때문이다.
enum을 == 연산자, equals()를 통한 비교에 대해 살펴보자
Enum의 필드는 static 변수이므로 클래스 로더가 로드 시점에 JVM method영역에 할당된다.
단, Enum을 호출하기 전에 단순 공간만 확보한다고 한다
Week today = Week.SUNDAY; Enum클래스에 값이 할당 되면 Heap영역에 Week객체는 필드별로 고유 객체가 생성된다. Method 영역에 생성된 객체를 바라보게 된다. today변수는 stack영역에 저장되며, today는 method영역에 있는 객체의 주소값을 복사 하므로 today와 Week.SUNDAY는 동일한 객체를 바라본다.위의 enum 클래스의 메모리 생성 설명을 보면 enum 타입은 하나의 인스턴스가 생성됨을 보장한다.
Enum 클래스의 equals도 내부적으로 == 연산을 사용하고 있다.
컴파일 시 타입체크를 하지 않지만, equals를 호출하는 객체가 Null일 경우 NullPointerException이 발생하여 이에대해 처리할 수 있다.
== 연산자는 참조 자료형 비교 시 참조자료형의 객체의 주소값을 비교한다. == 연산자 비교를 통해 runtime 안전성, compile 시 안정성을 보장할 수 있다.
runtime 시 비교하는 객체가 null이어도 nullPointerException이 발생하지않고 객체의 주소값에 대해 비교하여 runtime안전성을 보장할 수 있다.
public class EnumDemo {
public static void main(String[] args)
{
Member mem = new Member("smith", null);
System.out.println(mem.getCompany() == COMPANY.APPLE);//false
}
}
== 비교시 컴파일 시 타입 체크가 일어나므로 다른 타입으로 비교 시 컴파일 에러를 확인할 수 있다.
equals를 통해 비교를 통해 우연히 true값을 가질 수는 있지만 논리적인 측면에서는 맞지 않다.
System.out.println(member.getCompany().equals(FRUIT.APPLE));
대체로 두가지 사용의 의견이 분분하지만, 두가지 측면에서 보장하는 ==비교가 적절한것 같다.
[참고]
https://www.geeksforgeeks.org/comparing-enum-members-java/