자바가 제공하는 열거형(Enum Type). 이놈은 왜 생긴걸까?
간단한 예제를 통해 알아보자.
public class DiscountService {
public int discount(String grade, int price) {
int discountPercent = 0;
switch(grade) {
case "BRONZE" -> discount = 10;
case "SILVER" -> discount = 20;
case "GOLD" -> discount = 30;
default -> discount = 0;
}
return price * discountPercent / 100;
}
등급에 따라 할인율이 다른 경우가 있다. 이렇게 String
을 직접 입력하게 되면
존재하지 않는 DIAMOND
등급이나 오타, 대소문자 구분에서 아주 취약하다.
내가 이 코드를 작성할 때는 브론즈,실버,골드 등급만을 생각했는데 다른 개발자가 해당 코드를 사용하려고 보니 discount(String grade, int price)
"어라 등급은 그냥 String
을 사용하잖아?" 하고 discount("DIAMOND", 10000)
이라던가 discount("gold", 10000)
같은 식으로 코드를 작성할 수 있다.
흠.... 실무에서 다른 개발자가 실수하는걸 보고 상수를 사용하기로 했다!
public class Grade {
public static final String BRONZE = "BRONZE";
public static final String SILVER = "SILVER";
public static final String GOLD = "GOLD";
}
//DiscountService.discount() 수정
public int discount(String grade, int price) {
int discountPercent = 0;
switch(grade) {
case Grade.BRONZE -> discount = 10;
case Grade.SILVER -> discount = 20;
case Grade.GOLD -> discount = 30;
default -> discount = 0;
}
return price * discountPercent / 100;
좋아! 이제는 실수하지 않겠지??
그러나... 이렇게 코드를 작성해도 여전히 discount(String grade, int price)
해당 메서드는 String
을 받고 있기 때문에 DIAMOND
,gold
와 같은 값을 전달해서 오류가 발생할 수 있다... ㅠㅠ
public enum Grade {
BRONZE, SILVER, GOLD
}
띠용? 이렇게만 작성하면 된다고? 이걸 내가 직접 작성을 한다면 아래의 코드와 비슷하다
public class Grade {
public static final Grade BRONZE = new Grade();
public static final Grade SILVER = new Grade();
public static final Grade GOLD = new Grade();
//private 생성자
private Grade() {}
}
public static final Grade
와 private Grade()
부분을 작성해야하는 번거로움이 있는데
public enum
으로 생성하면 자바가 알아서 다 만들어준다. 그리고 아래와 같은 장점이 있다.
- 타입 안정성 향상
- 간결성 및 일관성
- 확장성
또, 열거형을 사용하는 경우 static import
를 사용해서 코드를 더 읽기 쉽게 만들 수 있다.
import static Grade.*;
//DiscountService.discount() 수정
public int discount(Grade grade, int price) {
int discountPercent = 0;
switch(grade) {
case BRONZE -> discount = 10;
case SILVER -> discount = 20;
case GOLD -> discount = 30;
default -> discount = 0;
}
return price * discountPercent / 100;
import static
을 사용해서 코드를 수정해봤다. 아주 간결하고 한눈에 딱 들어온다!
여기서 또 하나의 장점은 enum 을 사용하면 switch()
를 사용할 수 있다는 것이다.
만약 public class Grade
이렇게 class로 구현했다면 switch()
를 사용하지 못하고 그냥 if
를 사용해야한다.. ㅠ
public enum Grade {
BASIC(10), GOLD(20), DIAMOND(30);
private final int discountPercent;
Grade(int discountPercent) {
this.discountPercent = discountPercent;
}
public int getDiscountPercent() {
return discountPercent;
}
}
Enum을 생성할 때 필요한 값을 추가로 넣었다. 이렇게 하면 등급과 할인율을 같이 관리할 수 있게 되는데 해당 값이 필요한 경우 grade.getDiscountPercent()
로 가져올 수 있다.
또한 enum 클래스에는 values()
라는 메서드가 있는데 이 메서드는 enum 클래스의 모든 값을 배열로 반환해준다.
public static Grade findByName(String name) {
Grade[] values = values();
for (Grade grade : values) { // {BAISC, GOLD, DIAMOND}
if (grade.name().equals(name)) {
return grade;
}
}
return null;
}
그래서 위와 같이 String
값을 가지고 거기에 맞는 Grade
값을 가져올 수 있는 코드를 작성할 수 있는 것이다.
위의 Grade
클래스는 discountPercent
만 가지고 있지만 내가 원한다면 더 많은 필드를 가질 수도 있다.
- 김영한의 실전 자바 - 중급 1편