스터디할래 - 11주차 과제: Enum

 https://github.com/whiteship/live-study

 

👍목표

 

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

 

📖학습할 것 (필수)

 

📌 enum 정의하는 방법

 


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

 

 

📌java.lang.Enum

 

 

📌 EnumSet

 


💡  enum 정의하는 방법

 

enum은 enumeration(열거)의 줄임말로 자바5부터 추가된 enum type의 클래스로 자바doc에 따르면 다른 언어의 enum

 

보다 강력하다고 한다.

 

(Java programming language enum types are much more powerful than their counterparts in other languages.)

 

enum을 정의하는 방법은 class 정의하는 방법과 크게 다르지 않다. 첫글자는 대문자로 작성하며 class 키워드 대신

 

enum을 사용하여 정의할 수 있다.

 

ex)
public enum Role {
    USER, MANAGER, ADMIN
}

 

enum은 생성자를 사용하여 값을 부여할 수 있는데 공식 문서에 따르면 다음과 같이 설명 되어있다.

 

(The constructor for an enum type must be package-private or private access. It automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself)

 

enum 타입의 생성자는 'package-private' 또는 'private' 접근(지시자) 이여야 한다.  enum body의 시작 부분에 정의 된

상수를 자동으로 생성한다. enum의 생성자를 직접 호출할 수 없다. 

 

 

Intellij에서 enum의 생성자에 접근 시지자 테스트를 해보았는데 

 

public과 protected에서 다음과 같은 에러 메시지를 출력하였다.

 

 

public Role(String role) {

}

<Modifier 'public' not allowed here>

 

 

 

protected Role(String role) {

}

<Modifier 'protected' not allowed here>

 

 

enum 상수() 사이에 값을 부여할 수 있는데 해당 값에 해당하는 필드를 선언해야 한다. 

 

이에 대한 예시 코드를 작성하던 중 알 수 없는 오류가 발생하였는데

 

 

코드를 다시 작성하고 수정해보니 차이점을 발견 할 수 있었다.

 

 

필드의 위치를 enum 상수 뒤에 작성하면 문제를 해결할 수 있었는데, 이에 대해서는 좀 더 알아봐야 할 것 같다.

 

 

enum의 많은 장점은 개발 시 개발자의 문자 자체의 입력에 대한 오류를 방지 해줄 수 있다. 아래와 같이 Account 클래

 

스를 보면 name와 role을 필드로 갖고 있고, 

 

package me.study.java;

public class Account {
    private String name;
    private Role role;

    public Account() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}

Account 객체를 생성해서 이름과 Role을 set하는 코드를 보면 name의 경우 직접 문자열을 입력해야 하지만 role의 경우

 

IDE의 도움을 받아 직접 enum 상수를 골라서 값을 입력할 수 있기에 입력오류를 방지 할 수 있다. 

 

package me.study.java;

public class TempTest {
    public static void main(String[] args) {
        Account user1 = new Account();
        Account user2 = new Account();

        Account admin1 = new Account();

        user1.setName("회원1");
        user1.setRole(Role.USER);

        user2.setName("회원2");
        user2.setRole(Role.USER);

        admin1.setName("관리자1");
        admin1.setRole(Role.ADMIN);

        System.out.println("user1.getRole() == user2.getRole() =  " + (user1.getRole() == user2.getRole()));
        System.out.println("user1.getRole().equals(user2.getRole()) = " + (user1.getRole().equals(user2.getRole())));

        System.out.println("user1.getRole() == admin1.getRole() = " + (user1.getRole() == admin1.getRole()));
        System.out.println("user1.getRole().equals(admin1.getRole()) = " + (user1.getRole().equals(admin1.getRole())));

        System.out.println(user1.getRole());
        System.out.println(user2.getRole());
    }
}

output:
user1.getRole() == user2.getRole() =  true
user1.getRole().equals(user2.getRole()) = true
user1.getRole() == admin1.getRole() = false
user1.getRole().equals(admin1.getRole()) = false
USER
USER

 

참고로, enum의 값이 같은지 비교하는 ==과 equals 모두 같은 enum 상수라면 true를 출력한다. 

 

 

 

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

 

 

values()

 

values() 는 Enum의 모든 값을 해당 타입의 배열에 담아 반환한다.

 

 

package me.study.java;

public class TempTest {
    public static void main(String[] args) {
        Role[] values = Role.values();
        for (Role value : values) {
            System.out.println("value = " + value);
        }
    }
}

output:
value = USER
value = MANAGER
value = ADMIN

 

 

valueOf()

 

 

package me.study.java;

public class TempTest {
    public static void main(String[] args) {
        System.out.println("Role.valueOf(\"USER\") = " + Role.valueOf("USER"));
        System.out.println("Role.valueOf(\"USER\").getRole() = " + Role.valueOf("USER").getRole());
    }
}
output:
Role.valueOf("USER") = USER
Role.valueOf("USER").getRole() = ROLE_USER

 

만약 enum에 정의되어 있지 않은 값을 valueOf의 인자로 넘길 경우

 

Exception in thread "main" java.lang.IllegalArgumentException: No enum constant me.study.java.Role.NO!!
	at java.base/java.lang.Enum.valueOf(Enum.java:240)
	at me.study.java.Role.valueOf(Role.java:3)
	at me.study.java.TempTest.main(TempTest.java:7)

 

IllegalArgumentException이 발생한다.

 

💡  java.lang.Enum


Enum 클래스는 javadoc에 따르면 공통 기초 클래스(열거형의 최상위 타입) 이라고 한다.

(This is the common base class of all Java language enumeration types.) 

 

 

 

Enum 클래스에 선언된 대표적인 메서드는 다음과 같다.

 

메서드 설명
static E values() 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환한다.
static E valueOf(String name) 전달된 문자열과 일치하는 해당 열거체의 상수를 반환한다.
protected void finalize() 해당 Enum 클래스가 final 메서드를 가질수 없게 된다.
String name()

해당 열거체 상수의 이름을 반환한다.
int ordinal() 해당 열거체 상수가 열거체 정의에서 정의된 순서(0부터 시작)을 반환한다.

 

 

 

💡 EnumSet

 

 

EnumSet은 자바5에 추가된 enum 타입에 사용하기 위한 특수한 Set 구현이다.

 

이름에서 알 수 있듯이  Set 인터페이스를 상속받은 abstractset을 상속받아 Set 자료구조의 특징을 갖도록 하여 지정해

 

놓은 요소들을 가장 쉽고 빠르게 배열처럼 요소들을 다룰수 있는 기능을 제공한다




메서드   설명
static <E extends Enum<E>>
EnumSet<E> allOf(Class<E> elementType)
지정된 요소 유형의 모든 요소를 ​​포함하는 열거 형 set을 생성.
EnumSet<E> clone() 해당 set의 복사본을 반환한다.
static <E extends Enum<E>>
EnumSet<E> complementOf(EnumSet<E> s)
처음에 지정된 집합에 포함 되지 않은 해당 형식의 모든 요소를 ​​포함하는 지정된 열거 형 set과 동일한 요소 형식을 사용하여 열거 형 set을 생성.
static <E extends Enum<E>>
EnumSet<E> copyOf(EnumSet<E> s)
지정된 열거 형 set과 동일한 요소 유형을 사용하여 처음에 동일한 요소 (있는 경우)를 포함하는 열거 형 set을 생성.
static <E extends Enum<E>>
EnumSet<E> noneOf(Class<E> elementType)
지정된 요소 유형을 사용하여 빈 열거 형 set을 생성.
static <E extends Enum<E>>
EnumSet<E> of(E e)
처음에 지정된 요소를 포함하는 열거 형 set을 생성.
static <E extends Enum<E>>
EnumSet<E> range(E from, E to)
지정된 두 끝점에서 정의한 범위의 모든 요소를 ​​처음에 포함하는 열거 형 set을 생성.

 

 

 

package me.study.java;

import java.util.EnumSet;

public class TempTest {
    public static void main(String[] args) {
        EnumSet<Role> enumSet;
        enumSet = EnumSet.of(Role.USER, Role.ADMIN, Role.USER);

        for (Role role : enumSet) {
            System.out.println("role = " + role);
        }
    }
}
output:
role = USER
role = ADMIN

 

EnumSet의 코드 예시를 보면 EnumSet.of로 enumset에 데이터를 저장하지만 출력 결과에는 중복 저장한 USER가 하나

 

만 출력하는 것을 볼 수 있다.

 

References

이것이 자바다(신용권 저)
TCP School