[CS - 자바] Enum

Future·2024년 3월 12일
1

CS - 자바

목록 보기
6/6

intro..

원래는 enum을 쓸 때, 단순히

enum Role{
	ROLE_USER, ROLE_ADMIN
}

이런식으로 열거해서 상수로 사용하기만 했었다.
그런데, 생각보다 활용도가 많다는 것을 알고 정리하기로 했다.

Enum

자바에서 enum은 인터페이스와 같이 독릭된 특수한 클래스로 구분된다.
힙 메모리에 저장되고, 각각의 enum 상수는 별개의 메모리 주소를 갖는다.

Enum의 장점

  • 코드의 가독성을 높인다.
  • 허용 가능한 값을 제한하여 type safe 하다.
  • thread-safe한 싱글톤 객체로, 멀티스레딩 환경에서 안전하게 사용될 수 있다.
  • switch문에서 사용할 수 있다.

Enum은 reference type

Enum 객체는 메모리 힙 영역에 생성되어, 참조하여 사용한다.

Week today = Week.SUNDAY;


Enum 상수들을 values()를 통해 배열에 저장할 수 있다.

Week[] days = Week.values();

Enum 내부 구성

Enum은 상수 하나 당 static final 인스턴스를 만든다. 무슨 소리냐면,

public enum Role {
	ROLE_USER, ROLE_ADMIN
}

이렇게 enum을 만들었다면,

final class Role {
	public static final Role ROLE_USER = new Role("ROLE_USER");
    public static final Role ROLE_ADMIN = new Role("ROLE_ADMIN");
   
    private String role;

    private Role(String role){
    	this.role = role;
    }
}

사실은 내부적으로 이렇게 만들어지는 것이다. 생성자가 private이기 때문에 외부에서 인스턴스를 생성할 수 없고, 필드만 get 할 수 있다.

싱글톤

Enum은 싱글톤으로 설계되었기 때문에, 생성자의 접근 제어자는 private으로 설정해야 한다.
Enum은 new를 사용해 인스턴스를 생성할 수 없다. Enum은 컴파일 타임에 모든 값이 고정되기 때문에 외부에서 Enum에 값을 조작하는 것은 불가능하기 때문이다.

Enum 활용

  • 데이터 그룹화
enum CreditCard {

    SHINHAN("신한", Arrays.asList("Mr.Life 카드", "Deep Dream 카드", "Deep Oil 카드")),
    KB("국민", Arrays.asList("톡톡D 카드", "티타늄 카드", "다담 카드")),
    NH("농협", Arrays.asList("올바른 FLEX 카드", "테이크 5 카드", "NH 올원 파이카드"));

    private final String Enterprise;
    private final List<String> cards;

    CreditCard(String name, List<String> cards) {
        this.Enterprise = name;
        this.cards = cards;
    }
	
    String getCard(String cardName) {
        return Arrays.stream(CreditCard.values())
                .filter(creditCard -> creditCard.equals(cardName))
                .findFirst()
                .orElseThrow(Exception::new);
    }
}

카드사별로 여러 카드 종류가 있는데, enum으로 관리하고 싶다면 위와 같이 할 수 있다.

  • 매서드 이용
enum Operation {
    PLUS("+") {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS("-") {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTI("*") {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE("/") {
        public double apply(double x, double y) {
            return x / y;
        }
    };

    // 클래스 생성자와 멤버
    private final String symbol;
    Operation(String symbol) {
        this.symbol = symbol;
    }

    // toString을 재정의하여 열거 객체의 매핑된 문자열을 반환하도록
    @Override
    public String toString() {
        return symbol;
    }

    // 열거 객체의 메소드에 사용될 추상 메소드 정의
    public abstract double apply(double x, double y);
    
}

사용

public static void main(String[] args) {
    double x = 2.5;
    double y = 5.0;

    // Operation 상수집합의 PLUS 상수를 정의
    Operation plus = Operation.PLUS;

    // enum 매핑값 출력
    String name = plus.toString();
    System.out.println(name); // +

    // enum 확장 메소드 실행
    double result = plus.apply(x, y); // 덧셈을 수행하는 메소드 (Operation.PLUS.apply(x, y) 로 해도됨)
    System.out.println(result); // 7.5

    // ------------------------------------------------------------------- //

    // Operation 상수집합의 PLUS 상수를 정의
    Operation multi = Operation.MULTI;

    String name = plus.toString();
    System.out.println(name); // *

    // enum 확장 메소드 실행
    double result2 = multi.apply(x, y); // 곱셈을 수행하는 메소드
    System.out.println(result2); // 12.5
}

enum 안에 추상 매서드를 정의하고, 상수마다 추상 매서드를 오버라이딩하여 상수마다 다른 역할을 하는 매서드를 정의할 수 있다.

profile
Record What I Learned

1개의 댓글

comment-user-thumbnail
2024년 3월 15일

좋은 내용이네요. 감사합니다.

답글 달기