일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 불변객체
- HTTP프로토콜
- fcmv1
- 프로세스 생성
- HttpServlet
- rest api 검증
- DispatcherServlet
- equals
- 스프링요청반응
- 옵티마이저
- 클라이언트요청반응
- 왜불변객체인가
- multipart바인딩
- httpservlet기술
- java enum
- 동기비동기블로킹논블로킹
- Wrapper class
- 중첩클래스
- rest api
- 동등성동일성
- 래퍼클래스
- 옵티마저
- 데이터베이스파서
- multiparfile데이터
- fcm데이터구조
- 검증 실패 예외처리
- 공유기작동방식
- 디스패처서블릿
- biblecash
- fcm성능비교
- Today
- Total
개발은 아름다워
[ Java ] 열거형은 어떻게 생겨난거고 왜 ENUM타입을 쓰는걸까? 본문
자바가 제공하는 열거형을 제대로 이해하려면 먼저 열거형이 생견나 이유를 알아야 한다. 열거형이 만들어진 근본적인 이유를 알아야한다.
문자열과 타입 안정성
String 사용 시 타입 안전성 부족 문제
예를 들어 고객의 등급에 따라 할인 가격을 차등하도록 코드를 짠다고 하면
public class DiscountService{
public int discount(String grade, int price){
int disocuntPercent = 0;
if(grade.equals("BASIC")){
discountPercent = 10;
} else if(grade.equals("GOLD")){
discountPercent = 20;
} else {
System.out.println(grade + "는 존재하지 않습니다.")
}
return price*discountPercent/100;
}
}
위의 discountService를 사용하면, discountService.discount("BASIC",1000);
그런데 만약 discountService.discount("BASIc",1000); 일 경우 런타임에러가 발생하는 것이다.
- String으로 상태나 카테고리를 표현하면, 잘못된 문자열을 실수로 입력할 가능성이 있다.
- 컴파일 시 오류 감지 불가 : 이러한 잘못된 값은 컴파일 시에는 감지되지 않고, 런타임에서만 문제가 발견되기 때문에 디버깅이 어려워질 수 있다.
이러한 문제를 해결하기 위해서는 특정 범위로 값을 제한해야 한다. 하지만 String은 어떤 문자열이든 받을 수 있기 때문에 자바 문법 관점에서는 아무런 문제가 없다. 결국 String 타입을 사용해서는 문제를 해결할 수 없다.
문자열 상수를 사용한다면?
public class StringGrade{
public static final String BASIC = "BASIC";
public static final String GOLD = "GOLD";
}
이 경우 discountService에서
public class DiscountService{
public int discount(String grade, int price){
int disocuntPercent = 0;
if(grade.equals(StringGrade.BASIC)){
discountPercent = 10;
} else if(grade.equals(StringGrade.GOLD)){
discountPercent = 20;
} else {
System.out.println(grade + "는 존재하지 않습니다.")
}
return price*discountPercent/100;
}
}
discountService.discount(StringGrade.BASIC,1000);
문자열 상수를 사용하면 문자열을 직접 사용하는 것보다는 안전하다. 하지만 문자열 상수를 사용해도 직접 문자열을 사용한다면 막을 수 있는 방법이 없다.
예를 들어
discountService.discount("BASIC",1000);을 그대로써도 문제 없다는 것이다.
타입 안전 열거형 패턴
위의 설명한 문제를 해결하기 위해 많은 개발자들이 오랜기간 고민하고 나온 결과가 바로 타입 안전 열거형 패턴이다. 여기서 영어인 enum은 enumeration의 줄임말인데, 번역하면 열거라는 뜻이고, 어떤 항목을 나열하는 것을 뜻한다. 타입 안전 열거형 패턴을 사용하면 나열한 항목만 사용할 수 있다는 것이 핵심이다. 나열한 항목이 아닌 것은 사용할 수 없다. 나열한 항목만 안전하게 사용할 수 있다는 것이다.
어떤 아이디어로 만들면 될까? 위의 문제는 String 타입의 어떤 값이든 매개변수로 받을 수 있다는 것이다. 그렇다면 매개변수로 받는 값들을 제한 시켜두는 방법을 만드는 것이다. 값이 정해진 항목들을 매개변수로 쓰도록 만드는 것이다.
public class ClassGrade{
public static final ClassGrade BASIC = new ClassGrade(); // x001
public static final ClassGrade GOLD = new ClassGrade(); // x002
}
public class DiscountService{
public int discount(ClassGrade classGrade, int price){
int disocuntPercent = 0;
if(classGrade == ClassGrade.BASIC){
discountPercent = 10;
} else if(classGrade == ClassGrade.GOLD){
discountPercent = 20;
} else {
System.out.println(classGrade + "는 존재하지 않습니다.")
}
return price*discountPercent/100;
}
}
이 경우 discountService(ClassGrade.BASIC, 1000); 로 쓰이며 매개변수로는 ClassGrade.BASIC과 ClassGrade.GOLD 밖에 쓸 수 없다. 제한 시키는 것이다. String의 논리 값을 비교했던 위의 방법과 달리 메소드 영역이 이미 생성된 ClassGrade.BASIC과 ClassGrade.GOLD의 참조값을 비교하게 된다.
더 나아가 혹시 ClassGrade를 인스턴스를 만들 수 있으므로 private 생성자로 다른 클래스에서는 객체를 생성할 수 없도록 막으면 된다.
public class ClassGrade{
public static final ClassGrade BASIC = new ClassGrade(); // x001
public static final ClassGrade GOLD = new ClassGrade(); // x002
private ClassGrade(){};
}
ClassGrade의 인스턴스를 사용할 때는 ClassGrade 내부에 정의한 상수를 사용해야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 즉 ClassGrade 타입에 값을 전달할 때는 열거한 BASIC,GOLD 상수만 사용할 수 있게된 것이다.
타입 안전 열거형 패턴의 장점
- 타입 안정성 향상 : 정해진 객체만 사용할 수 있기 때문에, 잘못된 값을 입력하는 문제를 근본적으로 방지할 수 있따.
- 데이터 일관성 : 정해진 객체만 사용하므로 데이터의 일관성이 보장된다.
단점
이 패턴을 구현하려면 많은 코드를 구현해야하고 private 생성자를 추가하는 등 유의해야 하는 부분들이 있다.
열거형 - ENUM Type
자바는 타입 안전 열거형 패턴을 매우 편리하게 사용할 수 있는 열거형을 제공한다. 영어인 ENUM은 enumeration의 줄임말인데, 번역하면 열거라는 뜻이고, 어떤 항목을 나열하는 것을 뜻한다. “Enumeration”은 일련의 명명된 상수들의 집합을 정의하는 것을 의미하며, 프로그래밍에서는 이러한 상수들을 사용하여 코드 내에서 미리 정의된 값들의 집합을 나타낸다.
쉽게 이야기해서 상수로 정의한 값들만 사용할 수 있다는 뜻이다. 자바의 enum은 타입 안전성을 제공하고, 코드의 가독성을 높이며, 예상 가능한 값들의 집합을 표현하는 데 사용된다.
Enum도 클래스인데 열거 기능이 추가된 클래스라고 생각하면 된다.
public enum Grade {
BASIC, GOLD, DIAMOND
}
너무나도 간결하게 코드가 바뀌었다. 위 코드는 사실 밑에 코드와 거의 같다.
public class Grade extends Enum {
public static final Grade BASIC = new Grade();
public static final Grade GOLD = new Grade();
public static final Grade DIAMOND = new Grade();
//private 생성자 추가
private Grade() {}
}
- enum은 열거형 내부에서 상수로 지정하는 것 외에 직접 생성이 불가능하다. 생성할 경우 컴파일 오류가 발생한다. enum은 이미 private 생성자가 있다고 보면 된다.
열거형의 장점
- 타입 안정성 향상 : 열거형은 사전에 정의된 상수들도만 구성되므로, 유효하지 않은 값이 입력될 가능성이 없다. 이런 경우 컴파일 오류가 발생한다.
- 간결성 및 일관성 : 열거형을 사용하면 코드가 더 간결하고 명확해지며, 데이터의 일관성이 보장된다.
- 확장성 : 새로 추가하고 싶을때, 새로운 상수를 추가하기만 하면 된다.
참고로 열거형을 사용하는 경우 static import를 적절하게 사용하면 더 읽기 좋은 코드를 만들 수 있다.
정리
좋은 프로그래밍은 적절한 제약이 있는 프로그래밍이다. 정해진 값들이 나열되어 사용할 필요가 있었고, 문자열이나 문자열 상수를 쓰면 타입 안정성이 낮아지므로 타입 안전 열거형 패턴을 사용했다. 타입 안전 열거형 패턴은 각 객체들의 참조값을 바라보는 변수들을 정의함으로써 타입 안정성을 높였다. 더 나아가 자바에서는 타입 안전 열거형 패턴을 지원하는 enum 클래스를 활용함으로써 코드를 간결하며 타입 안정성을 높일 수 있었다. 위의 단계들은 결국 미리 정해진 값들을 제약을 둠으로써 안전하고 간편하게 쓸 수 있게 만드는 과정이였다.
'자바' 카테고리의 다른 글
[ Spring ] 고대의 서블릿을 찾아서(4) 수문장인 FrontController의 등장 (0) | 2024.10.12 |
---|---|
[ Java ] 제네릭은 무엇이며 왜 쓰는걸까? (1) | 2024.10.12 |
[ Java ] equals는 왜 쓰는거고 어떻게 쓰는걸까? - 동일성과 동등성 (0) | 2024.10.12 |
[ Java ] 중첩 클래스, 내부 클래스란? (0) | 2024.10.12 |
[ Java ]왜 Wrapper 클래스가 있는걸까? (0) | 2024.10.12 |