2025. 4. 1. 01:27ㆍJava
◎ 문자열과 타입 안정성
-> 어떤 서비스에서 고객의 등급을 BASIC, GOLD, DIAMOND로 나누고 각 등급에 따라 할인율을 다르게 적용한다.
-> 다음은 위 요구 사항에 대한 코드이다.
public class DiscountService {
public int discount(String grade, int price) {
int discountPercent = 0; // 할인율
// 각 등급에 따라 할인율 적용
if (grade.equals("BASIC")) {
discountPercent = 10;
}
else if (grade.equals("GOLD")) {
discountPercent = 20;
}
else if (grade.equals("DIAMOND")) {
discountPercent = 30;
} else {
System.out.println(grade + " : 할인 X");
}
return price * discountPercent / 100;
}
}
-> 각 회원의 등급을 String으로 받아 해당 문자열과 각 등급(문자열)을 비교해서 등급에 따른 할인율을 적용하도록 했다.
public class StringGradeEx0_1 {
public static void main(String[] args) {
int price = 10000;
DiscountService discountService = new DiscountService();
int basic = discountService.discount("BASIC", price);
int gold = discountService.discount("GOLD", price);
int diamond = discountService.discount("DIAMOND", price);
System.out.println("BASIC 등급의 할인 금액 : " + basic);
System.out.println("GOLD 등급의 할인 금액 : " + gold);
System.out.println("DIAMOND 등급의 할인 금액 : " + diamond);
}
}
-> 결과
-> 등급에 따라 할인율이 적용된 금액에 출력되었다.
-> 그런데 이 방식에는 문제가 있다. 등급을 String으로 받았기 때문에 만약 오타가 발생한다고 해도 오타가 난 그대로 코드가 실행이 될 것이다. 만약 GOLD를 GOLF라고 입력한다면 에러가 발생하지 않고 그대로 코드가 실행이 되고, 원래대로 실행을 했을 때 GOLD 등급의 고객을 해당 등급에 맞게 할인율을 적용을 해야 할 것이 제대로 할인율이 적용도지 않게 된다.
-> 현재 방식의 문제점을 정리하자면 아래와 같다.
- 타입 안정성 부족 : 문자열은 오타가 발생하기 쉽다. 유효하지 않은 값이 들어갈 수 있다.
- 데이터 일관성 : 문자열로 받기 때문에 다양한 형시의 문자열을 입력할 수 있어 일관성이 떨어진다.
- 컴파일 시 오류 감지 불가 : 가장 큰 문제다. 오타로 인해 제대로 된 등급이 입력도지 않은 채로 코드가 실행되어 의도와 다른 결과가 나온다.
◎ 열거형(Enum Type)
-> 자바에서는 enum이라는 타입을 지원하여 위의 등급과 같은 열거형 패턴을 쉽고 안전하게 사용할 수 있도록 한다.
-> 다음은 등급을 enum type으로 나타낸 것이다.
public enum Grade {
BASIC,
GOLD,
DIAMOND
;
}
-> 열거형은 class 대신 enum을 사용한다. 또한 위의 코드는 아래의 코드와 같다.
public class Grade {
public static final Grade BASIC = new Grade();
public static final Grade GOLD = new Grade();
public static final Grade DIAMOND = new Grade();
// 현재 선언된 클래스 이외의 클래스가 new 키워드를 통해 만들어지지 않도록 private으로 생성자를 제한
private Grade() {
}
}
-> 열거형도 클래스이며 외부에서 임의로 생성할 수 없다.
-> 위와 같이 열거형은 클래스이며 각각의 참조값을 가진다.
public class EnumRefMain {
public static void main(String[] args) {
System.out.println("class BASIC = " + Grade.BASIC.getClass());
System.out.println("class GOLD = " + Grade.GOLD.getClass());
System.out.println("class DIAMOND = " + Grade.DIAMOND.getClass());
System.out.println();
System.out.println("ref BASIC = " + refValue(Grade.BASIC));
System.out.println("ref GOLD = " + refValue(Grade.GOLD));
System.out.println("ref DIAMOND = " + refValue(Grade.DIAMOND));
}
private static String refValue(Object grade) {
return Integer.toHexString(System.identityHashCode(grade));
}
}
-> 결과
-> 결과를 통해 상수들이 열거형으로 선언한 타입인 Grade 타입을 사용하는 것을 확인할 수 있으며 각 인스턴스도 서로 다른 것을 알 수 있다.
-> 또한 Grade에 정의된 필드(BASIC, GOLD, DIAMOND) 이외에 다른 값이 들어가면 컴파일 시 오류가 발생한다.
-> 다음은 자바의 열거형을 사용해서 기존의 만들었던 DiscountService를 수정한 코드다.
public class DiscountService {
public int discount(Grade grade, int price) {
int discountPercent = 0; // 할인율
// 각 등급에 따라 할인율 적용
if (grade == Grade.BASIC) {
discountPercent = 10;
}
else if (grade == Grade.GOLD) {
discountPercent = 20;
}
else if (grade == Grade.DIAMOND) {
discountPercent = 30;
} else {
System.out.println(grade + " : 할인 X");
}
return price * discountPercent / 100;
}
}
public class EnumEx3_1 {
public static void main(String[] args) {
int price = 10000;
DiscountService discountService = new DiscountService();
int basic = discountService.discount(Grade.BASIC, price);
int gold = discountService.discount(Grade.GOLD, price);
int diamond = discountService.discount(Grade.DIAMOND, price);
System.out.println("BASIC 등급의 할인 금액 : " + basic);
System.out.println("GOLD 등급의 할인 금액 : " + gold);
System.out.println("DIAMOND 등급의 할인 금액 : " + diamond);
}
}
-> 결과
-> 이렇게 열거형을 사용하면 문자열을 사용했을 때 발생하는 오타 문제나 컴파일 시 오류 감지를 할 수 없는 문제를 해결할 수 있다. 열거형의 장점은 아래와 같이 정의할 수 있다.
- 타입 안정성 향상 : 열거형은 정의된 상수들로만 구성되므로 유효하지 않은 값(열거형에 정의되지 않은 상수)은 입력될 가능성이 없다. 입력된다면 컴파일 오류가 발생한다.
- 간결성 및 일관성 : 코드가 간결해지고 열거형에 정의된 상수만 사용되기 떄문에 데이터의 일관성이 보장된다.
- 확장성 : 만약 새로운 회원 등급을 추가한다면 열거형에 그냥 추가하고자 하는 상수만 추가하면 된다.
※ 열거형은 java.lang.Enum을 자동으로 상속받는다. 따라서 다른 클래스를 추가로 상속받을 수 없다.
※ 열거형은 인터페이스를 구현할 수 있으며 추상 메서드를 선언하고, 구현할 수 있다.
★ 참고 및 출처
'Java' 카테고리의 다른 글
중첩 클래스 ,내부 클래스1 (0) | 2025.04.07 |
---|---|
래퍼, Class 클래스 (0) | 2025.03.27 |
String 클래스 (0) | 2024.11.18 |
불변객체 (0) | 2024.10.31 |
Object 클래스 (0) | 2024.10.29 |