본문 바로가기
java/기타

Java - Enum

by 권성호 2021. 9. 24.

1. Enum이란?

- 상수들의 집합

- 자바에서는 final로 원시 타입 값을 고정할 수 있음

- 상수만으로 작성된 클래스는 class로 선언하지 않고 enum으로 선언할 수 있다.

 

2. Enum이 없다면?

-  우선 enum이 필요한 이유에 대해 생각해 보면, 특정 상수에 명시적인 의미를 부여하기 위함이 크다고 생각한다.

-  위에서 언급했듯, java에서는 final로 원시 타입 값을 고정할 수 있기 때문에 이를 활용하면 된다.

public class tmp {
    private final static int MONDAY = 1;
    private final static int TUESDAY = 2;
    private final static int WEDNESDAY = 3;
    private final static int THURSDAY = 4;
    private final static int FRIDAY = 5;
    private final static int SATURDAY = 6;
    private final static int SUNDAY = 7;

    /*
        생략
    */
}
  • 위 방식은 final을 사용하여 한번 지정하면 바뀌지 않게 설정하면서 동시에 static을 사용하여 메모리에 한 번만 할당되도록 설정되었다.
  • 또한, 변수명을 통해 그 의미를 명확하게 알 수 있다.
  • 이렇게 써도 웬만한 경우는 커버가 될 것 같다.

-  또 하나의 방법으로, 아래와 같은 방법이 있다.

class Day{
    public final static Day MONDAY = new Day();
    public final static Day TUESDAY = new Day();
    public final static Day WEDNESDAY = new Day();
    /*
    생략
     */
}
  • 위 방식 또한 final과 static 키워드를 사용하였고 변수명을 통해 값에 대한 의미를 명시하였다.
  • 각 변수에 할당되는 객체는 모두 각각 생성하고 있으므로 다른 객체로 구분될 수 있다.

 

3. java의 enum 사용하기

- 위 방식으로 많은 부분이 커버되지만 java 1.5부터는 해당 패턴을 문법적으로 지원하여 더욱 편리하고 명시적으로 사용할 수 있도록 하였다.

- 바로 위의 코드는 enum 타입을 써서 아래와 같이 바꿀 수 있다.

//class Day{
//    public final static Day MONDAY = new Day();
//    public final static Day TUESDAY = new Day();
//    public final static Day WEDNESDAY = new Day();
//    /*
//    생략
//     */
//}

enum Day{
    MONDAY,TUESDAY,WEDNESDAY
}
  • 해당 코드가 갖는 의미를 알기 위해 디버깅해 보면

enum 디버깅

  • enum으로 선언된 각각의 필드는 [name, ordinal] 속성을 가지는 것을 확인할 수 있다.
  • name 속성은 선언된 문자열 값 자체이다.
  • ordinal은 선언된 순서에 따라 부여된 번호이다.
  • java의 enum은 name과 ordinal과 관련한 여러 편의 메소드를 제공

enum이 제공하는 편의 메소드

  •  enum은 인스턴스 생성이 안 됨(상수 본연의 의미를 갖기 위함)

enum 인스턴스 생성하려 하면 컴파일 타임에 막힌다.

4. java enum의 확장

-  java enum은 class 개념도 포함한다. -> 추가적인 생성자, 메소드, 필드를 가질 수 있다.

-  주의할 점은, 생성자의 경우 무조건 private 만 가능하다. -> 외부에서 인스턴스 생성 불가능 -> 싱글톤을 강제함

-  그런데, enum을 공부하는 중 조금 이상한 부분을 발견했다.

enum RoadSide{
    Left("왼쪽"),
    Right("오른쪽");

    private String krName;

    private RoadSide(){

    }

    private RoadSide(String krName){
        this.krName = krName;
    }

    public String getKrName(){
        return this.krName;
    }

	// 하면 안되는 부분
    // enum은 컴파일 타임에 고정되는 상수의 의미를 갖는데, 이 코드로 인해 런타임에 바뀔 수 있는 가능성이 생긴다!
    // java 문법에서 public 생성자는 막지만 이 부분은 안막았으니 주의할것
    public void setKrName(String krName){
        this.krName = krName;
    }
}

public class tmp {
    public static void main(String[] args){
        System.out.println(RoadSide.Left.getKrName());
        RoadSide.Left.setKrName("왼쪽foo");
        System.out.println(RoadSide.Left.getKrName());
        /*
        생략
         */
    }
}
  • 해당 코드를 실행해 보니 아래와 같은 결과가 나온다.

  • 즉, enum의 경우 public 생성자를 막아 싱글톤 패턴을 강제하지만, 별도의 필드를 가질 경우 setter에 대한 제약은 없다는 것을 발견했다.
  • 누가 굳이 이런 코드를 작성할까 하지만, enum의 필드를 둘 때 setter를 생성하지 않도록 해야 한다.(개발자의 실수를 java 문법에서 잡아주지는 않기 때문)

5. 정리

- enum의 장점

  • 상수에 대한 명시적인 의미를 부여할 수 있다.
  • 코드가 단순해지며 가독성이 좋아진다.
  • 인스턴스 생성과 상속을 방지한다.
  • 구현의 의도를 명시적으로 표현할 수 있다.
  • 개별 필드와 메소드를 가질 수 있으므로 확장 가능성이 있다.

- 주의할 점

  • enum을 확장하기 위한 메소드를 만들 때 이미 생성된 enum 값을 바꾸는 메소드를 만들지 않도록 유념하기

6.  참고

 

7.  확장

댓글