자바 기본 복습 11. Enum

26079 단어 JavaJava

11주차 과제 Enum


📌 목표

자바의 열거형에 대해 학습하세요.


📌 학습할 것

  • enum 정의하는 방법
  • enum이 제공하는 메소드 (values()와 valueOf())
  • java.lang.Enum
  • EnumSet

📜 시작에 앞서

  • 백기선 님의 라이브 스터디(2020년 11월부터 2021년 3월까지) 커리큘럼을 따라 진행한 학습입니다
  • 뒤늦게 알게 되어 스터디 참여는 못했지만 남아있는 스터디 깃허브 주소유튜브 영상을 참고했습니다

📑 enum 정의하는 방법


enum 이란?

  • 열거형: 관련된 여러 상수를 정의하고, 그 외 값을 허용하지 않는다 -> 관련된 상수 집합 구성을 컴파일타임에 다 알고 있을 때 사용
  • 자바 열거형완전한 형태의 클래스기 때문에 생성자, 메서드, 필드 추가 가능

자바에서 열거형 지원하기 전에는?

  • 정수 열거 패턴 사용
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER; = 2;
public static final int SEASON_FALL = 3;
public static final int SEASON_WINTER = 4;

public static final int BACKEND_FRAMEWORK_SPRING = 1;
public static final int BACKEND_FRAMEWORK_DJANGO = 2;
public static final int BACKEND_FRAMEWORK_EXPRESS = 3;
public static final int BACKEND_FRAMEWORK_LARAVE = 4;
  • 모두 int이므로 타입 안전성 X (위의 경우 두 SPRING이 모두 int 1이기 때문에 == 비교시 true 반환)
  • 위와 같이 SPRING의 의미가 여럿일 경우 변수명에 직접 이름 구분 필요
  • 열겨형 enum은 이러한 문제점을 해결하고, 여러 장점을 가져오는데...

열거형 정의

enum 열거형명 { 상수명1, 상수명2 ...}

enum BackendFramework { SPRING, DJANGO, EXPRESS, LARAVE }

enum Season { SPRING, SUMMER, FALL, WINTER;
             
    Season(){ // private 생성자만 가능
        System.out.println(this + " init");
    }
}

public class Enum {

    public static void main(String[] args) {

        System.out.println("=====before=====");
        System.out.println(Season.SPRING);
        System.out.println("=====after=====");
        System.out.println();

        Season season1 = Season.SPRING;
        Season season2 = Season.SPRING;
        System.out.println("season1 == season2 :" + season1 == season2);
        System.out.println();

        BackendFramework bf1 = BackendFramework.SPRING;
        // System.out.println(season1 == bf1); 컴파일 에러! 타입 안전

    }

}
/*
실행결과
=====before=====
SPRING init
SUMMER init
FALL init
WINTER init
SPRING
=====after=====

season1 == season2 :true
*/
  • 자바 열거형은 상수 하나당 자신의 인스턴스를 public static final로 하나씩 생성
  • 자바 열거형은 생성자는 private만 가능
    • 따라서 열거형은 밖에서 접근할 수 없다
  • 각 열거형에 대해 타입 안전성

열거 타입 상수 각각을 틍정 데이터와 연결하고 싶다면?

  • 열거 타입 상수 각각을 특정 데이터와 연결지으려면 생성자에서 데이터를 받아 인스턴스 필드에 저장
// <이펙티브 자바 3/E> 코드 34-3 데이터와 메서드를 갖는 열거 타입
public enum Planet {
    MERCURY(3.302e+23, 2.439e6),
    VENUS  (4.869e+24, 6.052e6),
    EARTH  (5.975e+24, 6.378e6),
    MARS   (6.419e+23, 3.393e6),
    JUPITER(1.899e+27, 7.149e7),
    SATURN (5.685e+26, 6.027e7),
    URANUS (8.683e+25, 2.556e7),
    NEPTUNE(1.024e+26, 2.477e7);

    private final double mass;           // 질량(단위: 킬로그램)
    private final double radius;         // 반지름(단위: 미터)
    private final double surfaceGravity; // 표면중력(단위: m / s^2)

    // 중력상수(단위: m^3 / kg s^2)
    private static final double G = 6.67300E-11;

    // 생성자
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
        surfaceGravity = G * mass / (radius * radius);
    }

    public double mass()           { return mass; }
    public double radius()         { return radius; }
    public double surfaceGravity() { return surfaceGravity; }

    public double surfaceWeight(double mass) {
        return mass * surfaceGravity;  // F = ma
    }
}

출저: 이펙티브 자바 3/E


상수별 메서드 구현

  • 하나의 메서드가 상수별로 다르게 동작해야 할때 -> switch문 대신 상수별 메서드 구현 고려
enum Enum { 
	VAL1 {@Override public void info() { ... }},
	VAL2 {@Override public void info() { ... }},
	VAL3 {@Override public void info() { ... }},
	VAL4 {@Override public void info() { ... }};

    public abstract void info(...));
}

이외 고려사항 예시

  • 열거 타입 상수 일부가 같은 동작을 공유할 때 -> 전략 열거 타입 패턴 고려
    • 필요할 때 사용후 예시 추가 하기
  • 기존 열거 타입에 상수별 동작을 혼합할 때 -> switch문 고려
    • 필요할 때 사용후 예시 추가 하기

Enum 활용 예시


📑 java.lang.Enum

  • java.lang.Enum은 추상 클래스로, 열거형이 자동으로 상속받는 부모 클래스
    • Enumimpelements는 가능하나 extends는 불가
  • 인터페이스 Comparable<E>, Serializable 구현

java.lang.Enum 메서드

MethodDescription
clone()CloneNotSupportedException 예외 던짐
compareTo(E o)비교 가능한 타입일시 각 ordinal의 차이를 반환
getDeclaringClass()열거형의 Class 객체 반환
name()열거형 상수의 이름을 문자열로 반환
ordinal()열거형 상수의 순서 반환(0부터 시작)
valueOf(Class<T> enumType, String name)지정된 열거형(param1)에서 이름(param2)과 일치하는 열거형 상수 반환
  • 열거형 상수의 순서가 필요하다고 ordinal()을 사용하지 말자, 순서에따라 자동으로 부여하기때문에 유지보수 어렵다
    • 열거 타입 상수에 연결된 값이 필요하다면 인스턴스 필드에 저장
  • 메서드 전체는 java8 docs: Enum 참고
  • 외에도 열거형에 컴파일러가 추가하는 두 메서드는 다음 파트에서

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

  • values()valueOf(String name)은 컴파일러가 모든 열거형에 자동으로 추가
MethodDescription
values()열거형의 모든 상수를 배열에 담아 반환
valuesOf(String name)열거형 상수의 이름으로 문자열 상수에 대한 참조 반환
Planet.valueOf("EARTH") == Planet.EARTH

📑 EnumSet

  • EnumSet을 사용하면 열거형 상수의 값으로 구성된 집합을 간단히 생성할 수 있다
  • Set 인터페이스를 구현한 클래스며 이에 대한 다형성 활용 가능
  • 생성자를 클라이언트가 호출할 수 없다, 대신 EnumSet.of() 등 메서드 사용

생성 예시

import java.util.EnumSet;

enum Planet {
    MERCURY,
    VENUS,
    EARTH,
    MARS,
    JUPITER,
    SATURN,
    URANUS,
    NEPTUNE;
}

public class EnumSetEx {
    public static void main(String[] args) {

        EnumSet<Planet> planets = EnumSet.allOf(Planet.class);
        EnumSet<Planet> planetsHasRing = EnumSet.of(Planet.JUPITER, Planet.SATURN, Planet.URANUS, Planet.NEPTUNE);

        System.out.println("planets : " + planets);
        System.out.println("planetsHasRing : " + planetsHasRing);
    }
}

📑📌📜✏️

좋은 웹페이지 즐겨찾기