스터디/LiveStudy

11주차 과제: Enum

TheWing 2021. 1. 25. 01:50

11주차 과제: Enum

목표

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

학습할 것 (필수)

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

enum 정의하는 방법

  • 먼저 enum 에 대해 알아보자

enum(enumeration) 클래스( 상수의 집합)

  • 열거형 클래스이며, java 1.5 부터 사용이 가능하다
  • 셈, 계산, 열거, 목록, 일람표 (enumeration) 의 앞부분을 딴 예약어

장점

  • 열거체를 비교할 때 실제 값뿐만 아니라 타입까지도 체크한다
  • 열거체의 상숫값이 재정의되더라도 다시 컴파일할 필요가 없다.
  • 데이터들 간의 연관 관계 표현이 가능하다
  • 상태와 행위를 한곳에서 관리가 가능하다
  • 데이터 그룹관리가 가능하다

특징

  • 클래스를 상수처럼 사용이 가능하다
  • Enum 클래스를 구현하는 경우 상수 값과 같이 유일하게 하나의 인스턴스가 생성된다
  • 상속이 안된다

실 사용 경험

  • 실제로 프로젝트를 진행할 때 상태값을 지정하거나 고정된 값들을 지정할때 사용해봤었다
  • 이동욱님의 Java Enum 활용기 포스팅 내용 중 데이터들 간의 연관관계 표현 부분의 코드를 실제로 프로젝트에 적용해보았다.

선언

문법

enum 열거체이름 { 상수1, 상수2, 상수3}

예제

enum Champion {NIDALEE, MASTERYI, YUMI, ...}

사용

문법

 열거체이름.상수이름

예제

Champion.NIDALEE

사용 예제 (switch)

public enum Champion {
    NIDALEE, MASTERYI, YUMI
}
public class ChampionManager {
    public String getSkill(Champion champion){
        String skill = "";
        System.out.println(champion);
        switch (champion) {
            case NIDALEE:
                skill = "창 투척";
                break;
            case MASTERYI:
                skill = "알파 스트라이크";
                break;
            case YUMI:
                skill = "샤르르탄";
                break;
        }
        return skill;
    }

    public static void main(String[] args) {
        ChampionManager manager = new ChampionManager();
        String myAmount = manager.getSkill(Champion.NIDALEE);
        System.out.println(myAmount);
    }
}

결과

NIDALEE
창 투척

사용 예제 (switch 미적용)

public enum Champion2 {
    NIDALEE("창 투척"), MASTERYI("알파 스트라이크"), YUMI("샤르르탄");

    private final String skill;

    Champion2(String skill) {
        this.skill = skill;
    }

    public String getSkill() {
        return skill;
    }
}
public class ChampionManager2 {
    public static void main(String[] args) {
        Champion2 yumi = Champion2.YUMI;
        System.out.println("champion2 = " + yumi);
        System.out.println("champion2.getSkill() = " + yumi.getSkill());

        System.out.println();

        Champion2 masteryi = Champion2.MASTERYI;
        System.out.println("masteryi = " + masteryi);
        System.out.println("masteryi.getSkill() = " + masteryi.getSkill());

        System.out.println();

        Champion2 nidalee = Champion2.NIDALEE;
        System.out.println("nidalee = " + nidalee);
        System.out.println("nidalee.getSkill() = " + nidalee.getSkill());
    }
}

결과

champion2 = YUMI
champion2.getSkill() = 샤르르탄

masteryi = MASTERYI
masteryi.getSkill() = 알파 스트라이크

nidalee = NIDALEE
nidalee.getSkill() = 창 투척

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

Enum클래스에서 선언되어 있는 메소드

  • compareTo(E e)
    • 매개 변수로 enum 타입과의 순서(ordinal) 차이를 리턴한다.
  • getDeclaringClass()
    • 클래스 타입의 enum을 리턴한다.
  • name()
    • 상수의 이름을 리턴한다.
  • ordinal()
    • 상수의 순서를 리턴한다.
  • valueOf(Class enumType, String name)
    • 전달된 문자열과 일치하는 해당 열거체의 상수를 반환한다

valueOf() 예제

public class ChampionManager4 {
    public static void main(String[] args) {
        Champion2 champion2 = Champion2.valueOf("YUMI");
        System.out.println(champion2);
    }
}

결과

YUMI
  • values()메소드
    • 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환한다

values() 예제

public class ChampionManager3 {
    public static void main(String[] args) {
        Champion2[] list = Champion2.values();
        Arrays.stream(list).forEach(System.out::println);
    }
}

결과

NIDALEE
MASTERYI
YUMI

java.lang.Enum

enum 클래스의 부모는 무조건 java.lang.Enum이다

  • enum은 extends를 이용하여 선언할 수는 없다.

열거체를 조작하기 위한 메서드

  • protected

    • Enum(String name, int ordinal)
      • 컴파일러에서 자동으로 호출되도록 해놓은 생성자다. 하지만, 개발자가 이 생성자를 호출할 수는 없다.
  • Enum 클래스의 부모 클래스는 Object 클래스이기 때문에, Object 클래스의 메소드들은 모두 사용할 수 있다. 하지만, Enum 클래스는 개발자들이 Object 클래스 중 4개의 메소드를 Overring하지 못하도록 막아놓았다.

  • clone()

    • 객체를 복제하기 위한 메소드다. 하지만, 이 메소드는 enum 클래스에서 사용하면 안 된다. 만약 호출될 경우엔 CloneNotSupportedException이라는 예외를 발생시키도록 되어 있다.

EnumSet

  • EnumSet은 java.util 패키지 내에 정의 되어 있는 추상 클래스이다

특징 및 고려사항

  • Enum 값만 포함할 수 있으며 모든 값은 동일한 Enum 에 속해야한다
  • Null 값을 추가 할 수 없다
  • Thread-safe 하지 않으므로 필요한 경우 외부에서 동기화해야한다
  • Enum 에 선언된 순서에 따라 저장된다

장점

  • EnumSet의 모든 메서드는 산술 비트 연산을 사용하여 구현된다. 이러한 계산은 매우 빠르기 때문에 모든 기본 작업이 일정한 시간에 실행된다.
  • HashSet과 다르게 버킷을 찾기 위해 해시코드를 계산할 필요가 없다
  • 비트 벡터의 특성으로 인해서 EnumSet은 매우 간결하고 효율적이고, 모든 이점과 함께 적은 메모리를 사용한다

AbstractSet과 Cloneable, Serializable을 구현하고 있으며 상속 및 구현 구조는 아래와 같다

사용 메소드

allOf

  • Enum 클래스 전체를 담는다

noneOf

  • 빈 컬렉션을 만들 수 있다

range

  • Enum의 하위 집합을 만든다

complementOf

  • 매개 변수로 전달된 요소를 제외한다

copyOf

  • 다른 EnumSet의 모든 요소를 복사하여 EnumSet을 만들 수 있다

예제

import java.util.EnumSet;

public class EnumSetSample {
    public static void main(String[] args) {
        // Champion2 Enum 클래스 전체를 담는다
        EnumSet<Champion2> enumSetAllOf = EnumSet.allOf(Champion2.class);
        System.out.println("enumSet values = " + enumSetAllOf);

        EnumSet<Champion2> enumSetNoneOf = EnumSet.noneOf(Champion2.class);
        System.out.println("enumSetNoneOf = " + enumSetNoneOf);

        EnumSet<Champion2> enumSetRange = EnumSet.range(Champion2.MASTERYI, Champion2.YUMI);
        System.out.println("enumSetRange = " + enumSetRange);

        EnumSet<Champion2> enumSetComplementOf = EnumSet.complementOf(EnumSet.of(Champion2.NIDALEE, Champion2.MASTERYI));
        System.out.println("enumSetComplementOf = " + enumSetComplementOf);

        EnumSet<Champion2> enumSetCopyOf = EnumSet.copyOf(EnumSet.of(Champion2.NIDALEE, Champion2.YUMI));
        System.out.println("enumSetCopyOf = " + enumSetCopyOf);
    }
}

결과

enumSet values = [NIDALEE, MASTERYI, YUMI]
enumSetNoneOf = []
enumSetRange = [MASTERYI, YUMI]
enumSetComplementOf = [YUMI]
enumSetCopyOf = [NIDALEE, YUMI]

EnumMap

  • Enum을 키로 독점적으로 사용하는 Map의 구현이다

장점

  • 대응하는 HashMap에 비해 효율적이고 간결한 구현이며 내부적으로 배열로 표시된다.

사용 예제

import java.util.EnumMap;

public class EnumMapSample {
    public static void main(String[] args) {
        EnumMap<Champion2, String> enumMap = new EnumMap<>(Champion2.class);
        System.out.println("enumMap = " + enumMap);

        enumMap.put(Champion2.NIDALEE, "숨통 끊기");
        enumMap.put(Champion2.MASTERYI, "명상");
        enumMap.put(Champion2.YUMI, "너랑 유미랑");

        System.out.println("enumMap put after= " + enumMap);

        enumMap.entrySet().forEach(System.out::println);
    }
}

결과

enumMap = {}
enumMap put after= {NIDALEE=숨통 끊기, MASTERYI=명상, YUMI=너랑 유미랑}
NIDALEE=숨통 끊기
MASTERYI=명상
YUMI=너랑 유미랑

Reference

'스터디 > LiveStudy' 카테고리의 다른 글

13주차 과제 : I/O  (0) 2021.02.08
12주차 과제 : 애노테이션  (0) 2021.01.31
10주차 과제: 멀티쓰레드 프로그래밍  (6) 2021.01.18
9주차 과제: 예외 처리  (0) 2021.01.11
8주차 과제: 인터페이스  (0) 2021.01.04