본문 바로가기

개발 스토리/Java live study

Java 11주차 : Enum

목표

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

학습할 것 (필수)

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

Enum 이란?

  • Enum(열거형)은 프로그래밍 언어에서 명명 된 상수 그룹을 나타내는 목적으로 사용된다.

enum 정의하는 방법


  • 열거형을 정의하는 방법은 괄호안에 상수의 이름을 나열하기만 하면 된다.
  • Enum선언은 클래스 외부 또는 클래스 내부에서 수행 할 수 있지만 메서드 내부에서는 수행 할 수 없다.
enum 열거형이름 { 상수명1, 상수명2, ... }

enum Color {
	RED, GREEN, BLUE
}

 

결과 : RED

Enum의 중요 사항


  • 모든 enum은 클래스를 사용해서 내부적으로 정의된다.
/ * 내부적으로 위의 enum은 아래처럼 변환됩니다.
class Color
{
     public static final Color RED = new Color ();
     public static final Color BLUE = new Color ();
     public static final Color GREEN = new Color ();
} * /
  • 모든 enum 상수들은 객체 타입의 enum이다.
  • enum 타입은 switch구문의 인수로 넣을 수 있다.
enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY
}

public class Test{
    Day day;

    public Test(Day day) {
        this.day = day;
    }

    public void dayIsLike() {
        switch(day) {
            case MONDAY:
                System.out.println("Mondays are bad.");
                break;
            case FRIDAY:
                System.out.println("Fridays are better.");
                break;
            case SATURDAY:
            case SUNDAY:
                System.out.println("Weekends are best.");
                break;
            default:
                System.out.println("Midweek days are so-so");
                break;
        }
    }

    public static void main(String[] args) {

        String str = "MONDAY";
        Test t1 = new Test(Day.valueOf(str));
        t1.dayIsLike();
    }
        /** 출력 : Mondays are bad. **/
}
  • 모든 enum의 상수는 내부적으로 public static final로 정의되고, enum 이름으로 사용할 수 있다. 또한 final이므로 자식 enum을 만들 수는 없다.
  • enum 안에 main() 메소드를 선언 할 수 있다. 따라서 명령 프롬프트에서 직접 enum을 호출 할 수 있다.
enum Color {
	RED, GREEN, BLUE
    
    public static void main(String[] args) {
    	Color c1 = Color.RED;
        System.out.println(c1);
    }
}

// 출력 : RED

 

Enum과 상속

  • 모든 enum들은 내부적으로 java.lang.Enum 클래스에 의해 상속된다. 클래스는 하나의 부모 클래스에 의해서만 상속되므로, enum은 다른것을 상속할 수가 없다.
  • toString() 메서드는 java.lang.Enum 클래스에서 오버라이드 된다. 이것은 enum상수 이름을 리턴한다.
  • enum은 다양한 인터페이스들을 상속 할 수 있다.

values(), ordinal(), valueOf() 메서드

  • 이 메서드들은 java.lang.Enum 내부에 존재한다.
  • values() 메소드는 enum안에 존재하는 모든 값들을 반환한다.
  • enum안에서 순서는 중요하다. ordinal() 메소드를 사용하여 배열 인덱스처럼 각 enum 상수 인덱스를 찾을 수 있다.
  • valueOf() 메소드는 존재한다면 특정 enum 상수의 스트링 값을 반환한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color arr[] = Color.values();

        for (Color color : arr) {
            System.out.println(color + " at index " + color.ordinal());
        }

        System.out.println(Color.valueOf("RED"));
    }
}

/*** 출력 
RED at index 0
GREEN at index 1
BLUE at index 2
RED
**/

 

java.lang.Enum

Enum클래스의 메서드

  • name() : enum에 선언 된 것과 정확히 일치하는 enum상수의 이름을 리턴한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.RED;

        System.out.println("Name of enum constant : " + c1.name());
    }
}

/*** 출력
 Name of enum constant : RED
**/

 

  • ordinal() : 이 메서드는 enum 상수의 인덱스를 반환한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.GREEN;
        System.out.print("ordinal of enum constant "+c1.name()+" : ");

        System.out.println(c1.ordinal());
    }
}

/*** 출력
 ordinal of enum constant GREEN : 1
**/

 

  • toString() : 이 메서드는 enum상수를 나타내는 String 객체를 반환한다. name() 메서드와 동일하다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.GREEN;

        String str = c1.toString();

        System.out.println(str);
    }
}


/*** 출력
 GREEN
**/

 

  • equals(Object obj) : 이 메서드는 지정된 객체가 enum상수와 같으면 true, 그렇치 않으면 false를 반환한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.RED;
        Color c2 = Color.GREEN;
        Color c3 = Color.RED;

        boolean b1 = c1.equals(c2);
        boolean b2 = c1.equals(c3);
        boolean b3 = c2.equals(null);

        System.out.println("is c1 equal to c2 : " + b1);
        System.out.println("is c1 equal to c3 : " + b2);
        System.out.println("is c2 equal to null : " + b3);
    }
}


/*** 출력
 is c1 equal to c2 : false
 is c1 equal to c3 : true
 is c2 equal to null : false
**/

 

  • hashCode() : 이 메서드는 enum상수에 대한 해시 코드를 반환한다. 실제로 이 메서드에는 "return super.hashCode()"라는 명령문이 하나만 포함되어 있으며 차례로 object 클래스 hashCode() 메서드를 호출한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.RED;
        System.out.print("hashcode of enum constant "+ c1.name() +" : ");

        System.out.println(c1.hashCode());

        Color c2 = Color.GREEN;
        System.out.print("hashcode of enum constant "+ c2.name() +" : ");

        System.out.println(c2.hashCode());
    }
}


/*** 출력
 hashcode of enum constant RED : 649734728
 hashcode of enum constant GREEN : 1595953398
**/

 

  • compareTo(E obj) : enum과 지정된 객체의 순서를 비교한다. 지정된 객체보다 작은 경우 음의 정수, 동일하면 0, 크면 양의 정수를 반환한다.
enum Color {
  RED, GREEN, BLUE
}

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

        Color c1 = Color.RED;
        Color c2 = Color.GREEN;
        Color c3 = Color.RED;
        Color c4 = Color.BLUE;

        System.out.print("Comparing "+c1.name()+" with "+ c2.name() +" : ");

        System.out.println(c1.compareTo(c2));

        System.out.print("Comparing "+c1.name()+" with "+ c3.name() +" : ");

        System.out.println(c1.compareTo(c3));

        System.out.print("Comparing "+c4.name()+" with "+ c2.name() +" : ");

        System.out.println(c4.compareTo(c2));
    }
}


/*** 출력
 Comparing RED with GREEN : -1
 Comparing RED with RED : 0
 Comparing BLUE with GREEN : 1
**/

 

  • getDeclaringClass() : 이 메서드는 enum상수의 enum유형에 해당하는 Class객체를 반환한다.
enum Color {
  RED, GREEN, BLUE
}

enum Day {
    MONDAY, TUESDAY;
}

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

        Color c1 = Color.valueOf("RED");
        Color c2 = Color.valueOf("GREEN");
        Day d1 = Day.valueOf("MONDAY");
        Day d2 = Day.valueOf("TUESDAY");

        System.out.print("Class corresponding to "+ c1.name() +" : ");

        System.out.println(c1.getDeclaringClass());

        System.out.print("Class corresponding to "+ c2.name() +" : ");

        System.out.println(c2.getDeclaringClass());

        System.out.print("Class corresponding to "+ d1.name() +" : ");

        System.out.println(d1.getDeclaringClass());

        System.out.print("Class corresponding to "+ d2.name() +" : ");

        System.out.println(d2.getDeclaringClass());
    }
}


/*** 출력
 Class corresponding to RED : class Color
 Class corresponding to GREEN : class Color
 Class corresponding to MONDAY : class Day
 Class corresponding to TUESDAY : class Day
**/

 

  • clone() : 이 메서드는 enum이 복제되지 않도록 보장하며, 이는 "싱글 톤"상태를 유지하는데 필요하다. enum상수를 만들기 위해 컴파일러에서 내부적으로 사용된다.
enum Color {
  RED, GREEN, BLUE
}

public class Test{
    public static void main(String[] args) throws CloneNotSupportedException{
        System.out.println("Enums are never cloned");

        Test t = new Test(){
            protected final Object clone() throws CloneNotSupportedException{
                return new CloneNotSupportedException();
            }
        };
        System.out.println(t.clone());
    }
}


/*** 출력
 Enums are never cloned
 java.lang.CloneNotSupportedException
**/

 

  • finalize() : 이 메서드는 enum클래스가 final메서드를 가질 수 없게 한다.
enum Color {
  RED, GREEN, BLUE;
}

public class Test{
    public static void main(String[] args) throws Throwable{
        System.out.println("enum classes cannot have finalize methods");

        Test t = new Test(){
            protected final void finalize() throws Throwable {
                
            }
        };
    }
}


/*** 출력
 enum classes cannot have finalize methods
**/

 

EnumSet

 

EnumSet이란 Set인터페이스를 기반으로 열거형 타입으로 지정해놓은 요소들을 가장 쉽고 빠르게 배열처럼 요소들을 다룰수 있는 기능을 제공한다.

 

import java.util.EnumSet;

enum Gfg {
    CODE, LEARN, CONTRIBUTE, QUIZ, MCQ
}

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

        EnumSet<Gfg> set1, set2, set3, set4;

        set1 = EnumSet.of(Gfg.QUIZ, Gfg.CONTRIBUTE, Gfg.LEARN, Gfg.CODE);
        set2 = EnumSet.complementOf(set1);
        set3 = EnumSet.allOf(Gfg.class);
        set4 = EnumSet.range(Gfg.CODE, Gfg.CONTRIBUTE);
        System.out.println("Set 1: " + set1);
        System.out.println("Set 2: " + set2);
        System.out.println("Set 3: " + set3);
        System.out.println("Set 4: " + set4);
    }
}


/*** 출력
 Set 1: [CODE, LEARN, CONTRIBUTE, QUIZ]
 Set 2: [MCQ]
 Set 3: [CODE, LEARN, CONTRIBUTE, QUIZ, MCQ]
 Set 4: [CODE, LEARN, CONTRIBUTE]
**/

 

메서드 이름 설명
copyOF(EnumSet s) 매개변수로 들어온 EnumSet을 복사한다.
nonOf(Class elementType) 빈, EnumSet을 반환한다.
of(E e1, E e2) 열거형 상수2개를 입력받아 새로운 EnumSet에 넣어 반환한다.
complementOf(EnumSet s) 매개변수에 들어온 EnumSet의 열거형 상수들을 제외한 열거형 상수들을 새로운 EnumSet에 넣어 반환한다.
range(E from, E to) 인자로 받은 열거형 상수 사이의 범위를 인덱스의 순서대로 새로운 EnumSet에 넣어 반환한다.
단, 앞선 매개변수의 인덱스가 빠르면 런타임에 에러가 난다.

 

- 참고 자료

www.geeksforgeeks.org/enum-in-java/

velog.io/@pop8682/Enum-27k067ns4a

velog.io/@kwj1270/Enum#enumset