백엔드/JAVA_이론공부

JAVA_열거형

반 불혹 2022. 9. 28. 16:36

열거형

열거형은 서로 연관된 상수의 집합을 의미한다. 

상수는 변하지 않는 값으로, final 키워드로 선언 할 수 있다.

열거형은 상수들을 간편하게 관리할 때 유용하게 사용될 수 있고, 변하지 않는 데이터를 다룰 때 사용된다.

열거형을 사용하지 않고 상수를 설정하게 되면

코드예시

public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int FALL   = 3;
public static final int WINTER = 4;

public static final int DJANGO  = 1;
public static final int SPRING  = 2; // 계절의 SPRING과 중복 발생!
public static final int NEST    = 3;
public static final int EXPRESS = 4;

위의 코드처럼 final 키워드로 int형 데이터를 상수로 지정 한 것을 볼 수 있다.

여기서 문제점이 있는데, 변수명에 따라 중복될 수 있어 컴파일 에러가 발생할 수 있다. 

물론, 이 경우 인터페이스를 사용해서 상수를 구별해서 사용하면 어느정도 해결된다.

interface Seasons {
	int SPRING = 1, SUMMER = 2, FALL = 3, WINTER = 4;
}

interface Frameworks {
	int DJANGO = 1, SPRING = 2, NEST = 3, EXPRESS = 4;
}

하지만 이 경우 또또 문제가 생긴다. 

인터페이스로 별도로 만들어놓은 변수이기 때문에 타입 안정성이 떨어진다는 것이다. 

if (Seasons.SPRING == Frameworks.SPRING) {...생략...}

계절의 SPRING(봄) , 프레임워크의 SPRING은 서로 의미가 다른데도 비교가 가능해지는 것이다. (인터페이스에서 그냥 따로 선언한 것 뿐이지 사실 둘다 int형 자료이기 때문에)

쉽게 말하면 이 사진과 비슷하다.

 

매생이 전복죽과 의미가 전혀 다른 번역

 

이 문제를 해결하려면, 저 위의 변수들을 서로 다른 클래스에 저장해서 상수로 선언하면 된다. 

그런데, 이러면 코드도 길어지고, switch문을 못쓴다.

class Seasons {
    public static final Seasons SPRING = new Seasons();
    public static final Seasons SUMMER = new Seasons();
    public static final Seasons FALL   = new Seasons();
    public static final Seasons WINTER = new Seasons();
}

class Frameworks {
    public static final Frameworks DJANGO  = new Frameworks();
    public static final Frameworks SPRING  = new Frameworks();
    public static final Frameworks NEST    = new Frameworks();
    public static final Frameworks EXPRESS = new Frameworks();
}

변수 8개를 주제에 맞게만 저장하면 되는데, 인터페이스로는 타입 안정성이 떨어지고, 클래스로 하면 코드 개판나고 스위치문 못쓴다. 
(클래스로 선언하면 스위치문 못쓰는 이유: 스위치문은 정해진 타입만 넣어서 돌릴 수 있는데, 클래스로 선언하면 사용자 정의타입이기 때문이다. (사전에 자바 안에 정해져 있지 않다.)

아주 뭐 답답한 상황이다.

이를 해결하기 위해 열거형 enum이 있다!

작성예시

enum Seasons { SPRING, SUMMER, FALL, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, EXPRESS }

간단히 다른 변수명을 선언하는것 처럼 enum (변수명) {내용} 으로 처리하면 된다.

이렇게 하면 타입안정성이 확보되고, 코드도 짧아져서 가독성도 높고, 스위치문도 사용 가능하다!

enum을 switch 문에 적용 한 예시 

enum chicken{
    fried,
    sauce,
    onion
}


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

        chicken menu = chicken.sauce; // 열거형 상수에 접근 ( 열거형이름.상수명)
                                      // menu에 chicken.sauce을 담음

        chicken[] allchicken = chicken.values(); //열거형 자료에 정의된 상수들을 배열로 반환
        for(chicken x : allchicken){
            System.out.printf("%s = %d%n",x.name(), x.ordinal());
            //name, ordinal 메서드 사용, 이름과 순서 반환

        }
        chicken findchicken = chicken.valueOf("onion"); 
        // valueOf 메서드로 열거형에서 이름과 일치하는 열거형 상수 반환 상수가 의도한 상수랑 같은지 확인
        System.out.println(findchicken);
        System.out.println(chicken.onion == chicken.valueOf("onion"));

        switch (menu){
            case fried:
                System.out.println("fried");
                break;
            case sauce:
                System.out.println("sauce");
                break;
            case onion:
                System.out.println("onion");
                break;

        }


    }
}
//출력
fried = 0
sauce = 1
onion = 2
onion
true
sauce

여기서 참고해야 하는것은 열거형은 선얼 될 때 내부에 선언되는 상수에 0부터 정수값을 할당한다.

enum Seasons { 
SPRING, //정수값 0 할당
SUMMER,  //정수값 1 할당
FALL, //정수값 2 할당
WINTER //정수값 3 할당
}

또한 열거형에서 적용되는 메서드들이 있다. 

String name() 열거 객체가 가지고 있는 문자열을 리턴하며, 리턴되는 문자열은 열거타입을 정의할 때 사용한 상수 이름과 동일합니다.
int ordinal() 열거 객체의 순번(0부터 시작)을 리턴합니다.
int compareTo(비교값) 주어진 매개값과 비교해서 순번 차이를 리턴합니다.
열거
타입
valueOf(String name) 주어진 문자열의 열거 객체를 리턴합니다.
열거
배열
values() 모든 열거 객체들을 배열로 리턴합니다.

 

 

'백엔드 > JAVA_이론공부' 카테고리의 다른 글

JAVA_애너테이션  (0) 2022.09.28
JAVA_제네릭  (0) 2022.09.28
JAVA_인터페이스  (0) 2022.09.22
JAVA_ final 키워드  (0) 2022.09.22
JAVA_추상화 , 추상 클래스, abstract 제어자  (0) 2022.09.22