최근 토비의 스프링을 공부하는데 enum을 사용하는 경우를 가끔씩 볼 수 있다. enum을 사용할 줄은 알지만 정확히 잘 사용하지는 못하는지라 이참에 enum에 대해서 제대로 숙지하기 위해 블로그 포스팅을 하면서 고찰을 해보고자 한다.
이러한 고찰을 하는 이유는 드라마 브레인에서 이강훈의 대사처럼 할 수 있는것과 잘하는 것은 다르기 때문이다. 잘 숙지하고 의식적으로 필요할 경우 enum을 사용하여 할 수 있는경지가 아닌 잘하는 경지가 되도록 하겠다.
열거 자료형(enumerated type)은 고정 개수의 상수들로 값이 구성되는 자료형이다. 상수들의 모임이라면 내 개인적인 생각으로는 그냥 클래스에 아래와 같이 상수를 넣으면 되지 않을까 생각하였다.
ex)
public static final int USER_ADMIN=1;
public static final int USER_DEFAULT=2;
public static final int USER_CLIENT =3;
public static final int ROLE_ADMIN=1;
public static final int ROLE_DEFAULT=2;
public static final int ROLE_CLIENT =3;
그러나 Effective JAVA에서는 이 기법을 int enum 패턴이라고 부르는데 안전성 관점과 편의성 관점에서 단점이 많다고 한다.
단점
-
별도의 이름공간을 제공하지 않기 때문에 접두어를 붙이게 된다.
-
컴파일 시점 상수이기 때문에 상수를 사용하는 클라이언트 코드와 함꼐 컴파일 되어서 깨지기 쉽다.
-
인쇄 가능한 문자열로 변환하기 쉽지 않다.
이러한 문제점을 해결한 것이 자바 1.5에 나온 enum 자료형이다.
ex)
public enum User {ADMIN, DEFAULT, CLIENT}
public enum Role {ADMIN,DEFAULT,CLIENT}
자바의 enum 자료형은 완전한 기능을 갖춘 클래스로 열거 상수별로 하나의 객체를 public static final 필드 형태로 제공하는 것이다. enum 자료형은 실질적으로는 final로 선언된 것이나 마찬가지인데, 클라이언트가 접근할 수 있는 생성자가 없기 때문이다. 참고로 안에 있는 자료형들은 String이나 int등의 자료형이 아닌 enum 자료형 그 자체이다.
ex)
enum 자료형의 자료형 확인해 보기예제이다.
public class MyTest {
enum User {ADMIN, DEFAULT, CLIENT}
public static void main(String[] args) {
for(User user : User.values()) {
System.out.println(user.name()+" "+user.getClass().getTypeName());
}
System.out.println("문자열"+" "+"문자열".getClass().getTypeName());
}
}
결과)
enum 자료형의 특징
-
enum자료형으로는 새로운 객체를 생성하거나 계승을 통한 확장을 할 수 없기때문에 이미 선언된 enum상수 이외의 객체는 사용할 수 없다.
-
enum 자료형은 컴파일 시점 형 안전성을 제공한다. 만약 USER형 인자를 받는다면 3개의 인자중 하나만 받는다.
-
싱글턴 패턴을 일반화 한 것으로 열거 상수가 하나뿐이다.
-
enum 자료형은 같은 이름의 상수가 공존할 수 있도록 한다. 네임스페이스가 이들을 분리시켜 주기 때문이다.
-
int enum패턴과 달리 상수의 값이 클라이언트 코드와 함께 컴파일되는 일이 생기지 않는다.
-
enum 자료형은 toString 메서드를 호출하면 인쇄 가능 문자열로 쉽게 변환할 수 있다.
-
enum자료형은 상수묶음에서 시작해서 점차로 완전한 기능을 갖춘 추상화 단위로 진화할 수 있다.
enum 사용하기
enum 상수에 데이터를 넣으려면 객체 필드를 선언하고 생성자를 통해 받은 데이터를 그 필드에 저장하면 된다.
ex)
각 enum 상수의 객체필드를 선언 후, 생성자를 통해 데이터를 저장 후 사용하는 예제이다. 각 필드는 private로 두고 public 접근자 메서드를 이용해서 접근하도록 하는 관례를 따라 소스코드를 작성하였다.
public class MyTest {
enum Planet{
MERCURY(1,2), SUN(1,3), EARTH(2,2);
private final double width;
private final double height;
private final double PI=3.14;
private Planet(double w,double h) {
this.width=w;
this.height=h;
}
public double getWidth() {
return this.width;
}
public double getHeight() {
return this.height;
}
public double widheiPI() {
return width*height;
}
}
public static void main(String[] args) {
for(Planet p : Planet.values()) {
System.out.println(p);
}
}
}
enum 자료형은 메서드 안에서 실제 메서드를 재정의 하는 기능을 갖고있는데 이를 상수별 메소드 구현이라고 부른다.
ex)
상수별 메소드 구현을 이용하여 사칙연산을 구하는 열거형 만들기
public class OperationTest {
enum Operation{
PLUS("+"){
@Override
double apply(double x, double y) {
return x+y;
}
},
MINUS("-"){
@Override
double apply(double x,double y) {
return x-y;
}
},
TIMES("*"){
@Override
double apply(double x,double y) {
return x*y;
}
},
DIVIDE("/"){
@Override
double apply(double x,double y) {
return x/y;
}
};
private final String symbol;
private Operation(String symbol) {
this.symbol=symbol;
}
@Override
public String toString() {
return symbol;
}
abstract double apply(double x,double y);
}
public static void main(String[] args) {
double a=1;
double b=2;
for(Operation op:Operation.values()) {
System.out.printf("%f %s %f = %f %n",a,op,b,op.apply(a, b));
}
}
}
결과)
'IT > JAVA' 카테고리의 다른 글
Java 람다 표현식, 람다 함수란? (0) | 2019.12.25 |
---|---|
이클립스(Eclipse) 거의 모든 단축키 모음 (0) | 2019.12.24 |
[JSP] 한글 깨짐 처리방법 (0) | 2019.11.27 |
STS(스프링 편집툴)에 톰캣 서버 추가하기 (0) | 2019.11.27 |
XML 파일정보를 읽기위한 Java API JAXB(Java Architecture for XML binding) (0) | 2019.11.15 |