티스토리 뷰
포스팅에 앞서 내용이 틀릴 수 있습니다.
해당 부분 지적 감사히 받습니다.
이번에는 타입 안전 열거형 + Enum에 대해 알아보자.
자바에서는 if문을 사용하거나 switch문을 사용하여 케이스 별로 처리할 일이 정말 많다.
하지만 이곳에 숫자의 범위가 아닌 문자열을 통해 케이스를 나누는 경우도 존재할 것이다.
하지만 개발자가 개발 중 문자에 오타를 내, if문을 정상적으로 타지 않게 될 경우가 있을 수 있다.
물론 꼼꼼히 개발하면 일어나지 않을 문제 이긴 하지만, 그래도 사람이기에 실수가능성을 배제할 순 없다.
이런 문제를 컴파일 단에서 점검하고, 방지하기 위해 자바는 Enum Class를 제공한다.
그렇다면 Enum Class의 역할이 무엇일지 소스코드를 보며 먼저 생각해 보자.
public class Grade {
public static final Grade BRONZE = new Grade();
public static final Grade SILVER = new Grade();
public static final Grade GOLD = new Grade();
public static final Grade DIAMOND = new Grade();
private Grade(){
}
}
위 코드는 실제 Enum 클래스가 아니다.
자바에서 제공하는 Enum 클래스는 개발자가 편하게 사용하게 하기 위해 위와 같은 코드를 생략하고, 아주 간단히 쓸 수 있게 해 준다.
아래 코드가 실제 자바에서 제공하는 Enum 클래스이며, 위 코드와 기능이 거의 같다.
public enum Grade2 {
BRONZE, SILVER, GOLD, DIAMOND
}
public static final을 사용하여 상수로 값을 지정했다.
타입은 Grade로 Class 객체를 담는 변수이며, new Grade()를 통해 객체 생성 후 참조값을 보관한다.
클래스 자체는 public이라 외부에서 접근하여 사용이 가능하지만, 생성자에 private을 붙여 Enum 클래스 외부에선 새로운 Grade 객체의 인스턴스 생성이 불가능하다.
따라서 Enum 클래스 내부에서 선언된 상수값만 참조하여 사용할 수 있다.
public class Main2 {
public int discount(Grade classGrade, int price) {
int discountPercent = 0;
if (classGrade == Grade.BRONZE) {
discountPercent = 10;
} else if (classGrade == Grade.GOLD) {
discountPercent = 20;
} else if (classGrade == Grade.DIAMOND) {
discountPercent = 30;
} else {
System.out.println("할인X");
}
return price * discountPercent / 100;
}
}
매개변수로 참조값을 받아 값을 처리하는 외부 메서드이다.
위와 같이 사용하면 개발자가 조건에 오타를 내도 컴파일 단에서 오류를 잡아준다.
마찬가지로 없는 상수값을 참조하려 해도 컴파일 오류를 내준다.
이러면 Runtime 에러를 방지할 수 있어 잠재적인 버그차단에 도움이 된다.
이러한 Enum의 장점은 바로 타입 안정성에 해당한다.
Enum 클래스의 장점을 모두 알아보자.
- 타입 안정성 향상 : 사전정의된 상수만 사용가능
- 간결성 및 일관성 : 개발자가 코드를 읽고 해석하기 쉬워짐
- 확장성 : 새로운 조건발생 시 Enum 클래스와 if문에서만 추가하면 됨
추가로 import static을 사용하여 Grade. 을 제거하여 상수가 담긴 변수이름만 그대로 사용할 수 있다.
이는 다른 개발자가 더욱 코드를 쉽게 해석하는데 도움을 준다.
import static middle.clazz.Grade.*;
+++++++++++++++++++++++++++++++++++
if (classGrade == BRONZE) {
discountPercent = 10;
}
Enum 클래스는 기본적으로 java.lang.Enum을 상속받고 있다.
이 Enum클래스 내부에 추상 클래스를 사용할 수도 있다. ( 익명 클래스와 방법이 같은데, 추후 다룰 예정)
Enum클래스는 toString()이 오버라이딩 되어있어 참조값을 확인할 수가 없다.
참조값을 확인하고 싶으면 아래 코드를 사용하면 된다.
Integer.toHexString(System.identityHashCode(Grade.BRONZE));
또한 기본 메서드들도 제공된다.
간단하게 이름과 기능에 대해서 알아보자
values() : 모든 Enum상수 배열 반환
valueOf() : 주어진 이름과 일치하는 Enum 상수 반환
name() : Enum 상수이름 문자열로 반환
ordinal() : 상수 선언순서 반환
toString() : 문자열 반환( 오버라이딩 가능하며 name()과 비슷하게 쓰인다)
추가로 리팩토링까지 진행 완료된 소스코드를 보며 이해하는 시간을 가져보자.
Main 클래스
public class Main {
public static void main(String[] args) {
int price = 10000;
for (Grade g : Grade.values()) {
printDiscount(g,price);
}
}
private static void printDiscount(Grade grade, int price){
System.out.println(grade.name() + "등급의 할인 금액 : " + grade.discount(price));
}
}
Grade(Enum) 클래스
public enum Grade {
BASIC(10), GOLD(20), DIAMOND(30), VIP(40);
private final int discountPercent;
Grade(int discountPercent) {
this.discountPercent = discountPercent;
}
public int discount(int price) {
return this.discountPercent * price / 100;
}
}
valueOf("문자열") 메서드는 주어진 문자열과 동일한 이름을 가진 열거형 상수의 참조값을 반환한다.
중요하니 잘 알아두자.
문제풀이 3번
최대한 리팩토링 해봤다.
열거형 클래스
public enum AuthentificationGrade {
GUEST(1,"손님"),LOGIN(2,"로그인 회원"),ADMIN(3, "관리자");
public final int level ;
public final String description ;
private AuthentificationGrade(int level, String description){
this.level = level;
this.description = description;
}
public void getMo(){
System.out.println("당신의 등급은 " + description + "입니다.");
getMo2(level);
}
private void getMo2(int level){
System.out.println(" == 메뉴 목록 == ");
if(level > 0){
System.out.println(" - 메인 화면");
if (level > 1) {
System.out.println(" - 이메일 관리 화면");
if (level > 2) {
System.out.println(" - 관리자 화면");
}
}
}
}
}
메인 클래스
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("당신의 등급을 입력하세요 [GUEST, LOGIN, ADMIN]: ");
String inputGrade = s.nextLine().toUpperCase();
AuthentificationGrade auth = AuthentificationGrade.valueOf(inputGrade);
auth.getMo();
}
}
와 근데 리팩토링 자바한테 맡겨보니까 메인 클래스를 두줄로 줄여주더라..
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.print("당신의 등급을 입력하세요 [GUEST, LOGIN, ADMIN]: ");
AuthentificationGrade.valueOf(new Scanner(System.in).nextLine().toUpperCase()).getMo();
}
}
이해는 된다.. ㅋㅋ
코드 유지보수를 위해 저렇게 까진 하지 말자.
보기 귀찮다
'기술스택 > 자바(Spring)' 카테고리의 다른 글
자바 익명 클래스 + 람다식(간단) (1) | 2025.02.18 |
---|---|
자바 중첩 클래스, 내부 클래스 (2) | 2025.02.17 |
자바 래퍼 클래스 (Wrapper Class) (1) | 2025.02.15 |
자바 String Class (2부) (1) | 2025.02.13 |
자바 불변 객체 (with String Class) (1) | 2025.02.13 |
- Total
- Today
- Yesterday
- los 15
- 프로그래머스 상품을 구매한 회원 비율 구하기
- 상품을 구매한 회원 비율 구하기 파이썬
- 상속
- Los
- webhacking.kr
- 코딩테스트
- 김영한 실전 자바 기본
- 김영한 실전 자바 중급
- 코딩테스트 준비
- 김영한 실전 자바 기초
- java
- zixem
- los 15단계
- static
- 백준 피보나치 수열
- samron
- spring
- 스프링
- 김영한
- 백준
- extends
- 기술스택
- 프로그래머스 상품을 구매한 회원 비율 구하기 파이썬
- lord of sql
- 자바
- ys.k
- 프로그래머스
- samron3
- 백준 피보나치
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |