본문 바로가기
Dev. Handbook/Java

[Java] Enum type(class), 열거형 클래스

by breezyday 2022. 12. 27.

그동안 Java에서 enum을 단순하게 사용해왔는데 최근 검색한 자료에서 enum의 다양한 활용방법들을 읽어보고 나서 java에서 enum을 공부하고 정리해 봤습니다.


1. Enum ( Enumerations : specifically listed )

열거형은 여러 프로그래밍 언어에서 사용하고 있습니다. 다른 언어에서는 단순히 상수 그룹만을 정의하지만, Java에서 enum은 상수(불변의 값, final 변수와 같음)의 그룹을 대표하는 특수 클래스( java.lang.Enum )enum 형(Type)으로 사용할 수 있습니다. 이 enum 클래스는 Java 5에서 도입되었습니다. 또한 enum 형 변수를 선언하면 enum에서 정의한 상수값만을 가질 수 있습니다. 

 

enum을 생성하려면 'enum' 키워드(class 혹은 interface 대신)를 사용하고, 콤마로 구분된 대문자 문자열 값들을 나열하면 됩니다. 그리고 기본 index 값(기본으로 열거된 순서에 따라 0부터 1씩 차례로 증가하는 값)을 가집니다. 마지막 상수값에 세미콜론(;)을 붙이지 않습니다. enum의 상수값을 참조하려면 dot을 사용합니다.

// enum 선언
enum Level {
    LOW,     // 상수값, ordinal : 0
    MEDIUM,  // 상수값, ordinal : 1
    HIGH     // 상수값, ordinal : 2
}

// enum 기본 참조
Level   myLevel  = Level.HIGH;

// enum의 메서드를 사용한 참조
String  strLevel = Level.HIGH.ToString();
Integer intLevel = Level.HIGH.ordinal();

class를 사용하여 상수를 선언하는 경우

아래와 같이 class를 선언하여 상수값으로 사용할 수 있지만 한 가지 데이터 타입으로만 표현할 수 있으며, 여러 개의 데이터 타입을 연결해서 사용할 수 없습니다.

class LevelInt {
    public final static int LOW = 0;
    public final static int MEDIUM = 1;
    public final static int HIGH = 2;
}

class LevelString {
    public final static String LOW = "LOW";
    public final static String MEDIUM = "MEDIUM";
    public final static String HIGH = "HIGH";
}

public class Main {
    public static void main(String[] args) {
        
        Integer intLevel = LevelInt.LOW;
        String  strLevel = LevelString.LOW;
        
        ...
    }
}

 

2. Enum(특수 클래스)과 Class의 차이점

특수 클래스인 Enum은 Class와 마찬가지로 속성(attributes)과 메서드(methods)를 가질 수 있습니다. 차이점은 enum은 항상 public static final이며, 변경하거나 재정의할 수 없습니다.

 

enum은 객체(objects)를 만드는 데 사용할 수 없으며, 다른 클래스(class)를 확장(extend)하는 데 사용할 수 없습니다, 그러나 인터페이스(interface)를 구현(implement)할 수는 있습니다

 

3. Enum을 사용해야 하는 곳

enum은 월(month), 주(week), 카드 덱(1~13), 나침반(동, 서, 남, 북) 등, 미리 정의되어 변경되지 않는 상수값의 집합을 처리할 때 사용합니다.

 

4. enum 사용하기

enum Level {
    LOW,
    MEDIUM,
    HIGH
}
    
public class Main {
    public static void mani(String[] args) {
        Level myLevel = Level.MEDIUM;
        
        System.out.println(Level.HIGH);
        System.out.println(myLevel);
    }
}

 

// 결과
HIGH
MEDIUM

 

5. Switch문에서 enum 사용하기

enum 변수를 선언하고 사용하면 switch문에서는 enum의 값들을 그대로 확인할 수 있습니다.

enum Size {
    SMALL,
    MEDIUM,
    LARGE,
    EXTRALARGE
}

class Pizza {
    Size pizzaSize;
    
    public Pizza(Size pizzaSize) {
        this.pizzaSize = pizzaSize;
    }
    
    public void order() {
        switch(pizzaSize) {
            case SMALL:
                System.out.println("Order Small size pizza");
                break;
            case MEDIUM:
                System.out.println("Order Medium size pizza");
                break;
            case LARGE:
                System.out.println("Order Large size pizza");
                break;
            case EXTRALARGE:
                System.out.println("Order Extra Large size pizza");
                break;
        }
    }
}
    
public class Main {
    public static void main(String[] args) {
        Pizza myPizza = new Pizza(Size.LARGE);
        myPizza.order();
    }
}

 

// 결과
Order Large size pizza

 

6. Loop(반복문)에서 enum

Java에서 enum은 특수 클래스( java.lang.Enum )로 몇 가지 method를 제공합니다. 그중에서 values() 메서드enum의 모든 값을 배열로 반환하며, 이는 반복문에서 사용할 수 있습니다.

enum Level {
    LOW,
    MEDIUM,
    HIGH
}

public class Main {
    public static void main(String[] args) {
        ...
        
        for (Level curLevel : Level.values()) {
            System.out.println(curLevel)
        }
        
        ...
    }
}

 

// 결과
LOW
MEDIUM
HIGH

 

7. Enum Class 사용하기 

enum은 class처럼 메서드를 가질 수 있습니다. 

enum Size {
    SMALL,
    MEDIUM,
    LARGE,
    EXTRALARGE;
    
    public String getSize() {
        switch(this) {
            case SMALL:
                return "small size";
            case MEDIUM:
                return "medium size";
            case LARGE:
                return "large size";
            case EXTRALARGE:
                return "extr large size";
            default:
                return null;
        }
    }
}

class Main {
    public static void main(String[] args) {
        Size pizzaSize = Size.SMALL;
        System.out.println(pizzaSize.getSize());
    }
}

 

// 결과
large size

 

8. Enum (Class) 생성자 

enum은 속성과 메서드를 가질 수 있습니다. enum에 속성을 부여할 경우, enum 상수를 선언할 때 호출하는 enum 생성자가 필요합니다. enum 생성자는 접근 제어자를 반드시 private로 지정해야 합니다. 이는 enum은 고정된 상수의 집합이므로 런타임(run-time)이 아닌 컴파일타임(compile-time)에 모든 값이 정해집니다. 즉 동적으로 값을 생성해줄 수 없습니다. 덕분에 컴파일 타임 시 타입 안정성이 보장됩니다. enum 생성자는 private으로 지정해야 하므로 외부에서 접근 가능한 생성자가 없어서 실제적으로 final과 다름이 없습니다.   

enum Size {
    // enum 생성자를 호출하는 enum 상수
    SMALL("small size"),
    MEDIUM("medium size"),
    LARGE("large size"),
    EXTRALARGE("extra large size"); // enum 생성자 사용 시 세미콜론 필요
    
    private final String pizzaSize; // enum 속성
    
    // private enum 생성자
    private Size(String pizzaSize) {
        this.pizzaSize = pizzaSize;
    }
    
    // public enum 메서드
    public String getSize() {
        return this.pizzaSize;
    }
}

class Main {
    public static void main(String[] args) {
        Size pizzaSize = Size.LARGE;
        System.out.println(pizzaSize.getSize());
    }
}

 

// 결과
large size

여러 개의 속성을 가지는 경우 : 예제는 2개

enum Size {
    SMALL("small size", 10),
    MEDIUM("medium size", 13),
    LARGE("large size", 15),
    EXTRALARGE("extra large size", 18);
    
    // enum 속성
    private final String pizzaSize; 
    private final int diameter;     // 지름, 인치
    
    // enum 생성자
    private Size(String pizzaSize, int diameter) {
        this.pizzaSize = pizzaSize;
        this.diameter  = diameter;
    }
    
    // enum 메서드
    public String getSize() {
        return this.pizzaSize;
    }
    
    public int getDiameter() {
        return this.diameter;
    }
}

class Main {
    public static void main(String[] args) {
        Size pizzaSize = Size.LARGE;
        System.out.println("Size : " + pizzaSize.getSize());
        System.out.println("Diameter : " + pizzaSize.getDiameter());
    }
}

 

// 결과
Size : large size
Diameter : 15

 

9. Enum 메서드 

enum은 java.lang.Enum을 상속받아서 생성이 되기에 아래의 메서드들을 사용할 수 있습니다.

메소드 설명
static E values() enum의 모든 값을 저장한 Enum형 배열을 생성하여 반환
static E valueOf(String name) name과 일치하는 enum의 상수를 반환
protected void finalize() 해당 Enum 클래스가 final 메서드를 가질 수 없게 됨
String name() 상수의 이름(문자열)을 반환
override하지 않을 경우 toString과 동일.
int ordinal() enum에 정의된 상수의 순서(index 기반)를 반환
0부터 시작
String toString() 상수의 이름(문자열)을 반환
toString을 오버라이드 하지 않으면 name()과 동일한 결과를 반환
int compareTo(E) E와 ordinal의 차이를 반환
ex) Size.SMALL.compareTo(Size.MEDIUM)
    return ordinal(SMALL) - ordinal(MEDIUM)
boolean equals(E) E와 같은지 비교하고, 결과를 boolean으로 반

enum 메서드 사용 예

enum Size {
    SMALL("small size", 10),
    MEDIUM("medium size", 13),
    LARGE("large size", 15),
    EXTRALARGE("extra large size", 18);
    
    // enum 속성
    private final String pizzaSize; 
    private final int diameter;     // 지름, 인치
    
    // enum 생성자
    private Size(String pizzaSize, int diameter) {
        this.pizzaSize = pizzaSize;
        this.diameter  = diameter;
    }
    
    // enum 메서드
    public String getSize() {
        return this.pizzaSize;
    }
    
    public int getDiameter() {
        return this.diameter;
    }
    
    // override
    public String toString() {
    	return "[" + this.pizzaSize + ", " +this.diameter + "]";
    }
}

class Main {
    public static void main(String[] args) {
    	System.out.println("ENUM Size ---------------------------------");
        System.out.println("valueOf() : " + Size.valueOf("LARGE"));
        
        Size[] arrSize = Size.values();
        System.out.println("values() : " + arrSize);
        for (Size curSize : arrSize) {
        	System.out.println("-- " + curSize.toString());
        }

        System.out.println("");
    	System.out.println("ENUM Variable : pizzaSize = Size.LARGE ----");
        Size pizzaSize = Size.LARGE;
        
        System.out.println("Size : " + pizzaSize.getSize());
        System.out.println("Diameter : " + pizzaSize.getDiameter());
        
        System.out.println("name() : " + pizzaSize.name());
        System.out.println("toString: " + pizzaSize.toString());
        System.out.println("ordinal() : " + pizzaSize.ordinal());
        System.out.println("compareTo(Size.SMALL) : " 
                + pizzaSize.compareTo(Size.SMALL));
        System.out.println("compareTo(Size.MEDIUM) : " 
                + pizzaSize.compareTo(Size.MEDIUM));
        System.out.println("compareTo(Size.LARGE) : " 
                + pizzaSize.compareTo(Size.LARGE));
        System.out.println("compareTo(Size.EXTRALARGE) : " 
                + pizzaSize.compareTo(Size.EXTRALARGE));
    }
}

 

// 결과
ENUM Size ---------------------------------
valueOf() : [large size, 15]
values() : [Lenumtest.Size;@6d06d69c
-- [small size, 10]
-- [medium size, 13]
-- [large size, 15]
-- [extra large size, 18]

ENUM Variable : pizzaSize = Size.LARGE ----
Size : large size
Diameter : 15
name() : LARGE
toString: [large size, 15]
ordinal() : 2
compareTo(Size.SMALL) : 2
compareTo(Size.MEDIUM) : 1
compareTo(Size.LARGE) : 0
compareTo(Size.EXTRALARGE) : -1

 

참조

https://www.w3schools.com/java/java_enums.asp

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

https://www.programiz.com/java-programming/enums

https://www.programiz.com/java-programming/enum-constructor

 

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

https://www.geeksforgeeks.org/enum-customized-value-java/

https://www.geeksforgeeks.org/java-lang-enum-class-java/

 

 

 

 

 

댓글