일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 스케줄링
- 백준 장학금
- JPA
- SpringSecurity
- HTTP
- 강화학습
- 백준장학금
- 알고리즘
- Kruskal
- 자료구조
- posix
- 운영체제
- 멀티프로세서
- jpa n+1 문제
- 완전이진트리
- 점근적 표기법
- JVM
- heapq
- 힙트리
- 연결리스트
- 최소힙
- 최대 힙
- 프로세스
- python
- 이분탐색이란
- spring
- 엔티티 그래프
- 연결리스트 종류
- AVL트리
- MSA
- Today
- Total
KKanging
JAVA enum을 왜 사용하는 걸까? 본문
java 의 enum 이란
상수가 필요해!
public class EnumClient {
private static final int ONE = 1;
public static void main(String[] args) {
System.out.println(ONE);
}
}
우리는 프로그래밍 하는 도중에 상수가 필요하다면 위에 처럼
private static final 키워드를 사용해서 상수 선언을 한다.
추상화 된 상수가 필요해!
public class EnumClient {
private static final int ONE = 1;
private static final int TWO = 2;
private static final int THREE = 3;
public static void main(String[] args) {
System.out.println(ONE);
System.out.println(TWO);
System.out.println(THREE);
}
}
위처럼 상수의 목록이 추상화된 형태로 묶을 수 있고,
다른 client 코드에서 해당 상수를 사용해야한다면 일일해 상수 선언을 해야한다.
따라서 우리는 객체지향적 사고 방식으로 다음과 같이 선언한다.
class NumberConstClass {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
}
public class EnumClient {
public static void main(String[] args) {
System.out.println(NumberConstClass.ONE);
System.out.println(NumberConstClass.TWO);
System.out.println(NumberConstClass.THREE);
}
}
위처럼 선언함으로써 다른 외부 클래스나 패키지에서 해당 클래스의 상수를 사용할 수 있게 되었고 상수 ONE TWO ,.. 들도 하나의 추상화된 단위로 묶일 수 있게 되었다.
해결한거 같지 않나?
클래스 상수 선언에 단점
- 타입 세이프 하지 않다.
- 상태(state) 와 로직이 분리되어 있다.
- 논리적 동등성을 보장하지 않는다.
타입 세이프 하지 않다?
class NumberConstClass {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
public static void outPut(int number1, int number2) {
System.out.println(number1 + number2);
}
}
public class EnumClient {
public static void main(String[] args) {
NumberConstClass.outPut(NumberConstClass.ONE, NumberConstClass.TWO);
}
}
위에 방식으로 메서드를 출력하는 코드에서 인자로 NumberConstClass 를 넣지 않더라도 가능하다.
public class EnumClient {
public static void main(String[] args) {
NumberConstClass.outPut(NumberConstClass.ONE, 1231151515);
}
}
이러한 타입 안정성이 없다는건 컴파일 단계에서 에러를 잡아낼 수 없기에 어떤 에러가 생길지 모른다.
상태와 로직이 분리?
상수를 모아둔 클래스이기 때문에 상태가 동작하는 메서드를 코드에 삽입할 수 없다.
논리적 동등성을 보장하지 않는다.
class NumberConstClass {
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
}
class ShapeConstClass {
public static final int CIRCLE = 1;
public static final int SQUARE = 2;
public static final int TRIANGLE = 3;
}
public class EnumClient {
public static void main(String[] args) {
System.out.println(NumberConstClass.ONE == ShapeConstClass.CIRCLE);
}
}
논리적으로 위의 출력은 false 가 나와야 하지만 아쉽게도 true 가 나온다.
해결
class NumberConstClass {
private final int value;
public static final NumberConstClass ONE = new NumberConstClass(1);
public static final NumberConstClass TWO = new NumberConstClass(2);
public static final NumberConstClass THREE = new NumberConstClass(3);
private NumberConstClass(int value) {
this.value = value;
}
public void print() {
System.out.println("Value: " + value);
}
}
class ShapeConstClass {
private final int value;
public static final ShapeConstClass CIRCLE = new ShapeConstClass(1);
public static final ShapeConstClass SQUARE = new ShapeConstClass(2);
public static final ShapeConstClass TRIANGLE = new ShapeConstClass(3);
private ShapeConstClass(int value) {
this.value = value;
}
public void print() {
System.out.println("Value: " + value);
}
}
class Print{
public static void Print(NumberConstClass numberConstClass) { // 타입 안정성 보장
numberConstClass.print();
}
}
public class EnumClient {
public static void main(String[] args) {
System.out.println(NumberConstClass.ONE == ShapeConstClass.CIRCLE); // 컴파일 에러
NumberConstClass.ONE.print();
ShapeConstClass.CIRCLE.print();
Print.Print(NumberConstClass.ONE);
}
}
싱글톤 디자인 기법을 활용해서 구현하였다.
위처럼 사용하면 우리가 원하는 상수를 추상화한 클래스를 잘 사용할 수 있을 것이다.
타입 안정성이 보장되고
로직이 들어가게 되고
논리적인 동등성을 보장할 수 있게 된다.
근데 너무 불편하다고 생각할 수 있다.
그래서 나온 enum 문법이 있다!
enum
public enum Number {
ONE,TWO,THREE
}

enum 또한 위에 NumberConstClass 처럼 싱글톤으로 구현되어 있다.
처음 클래스가 로드될 때 상수 영역에 적재된다.
ONE,TWO,THREE 모두 하나의 싱글톤 객체이다.
enum도 클래스이고 값은 싱글톤 객체이다.
public enum Number {
ONE(1){
@Override
void print() {
System.out.println(ONE.value);
}
},
TWO(2){
@Override
void print() {
System.out.println(TWO.value);
}
},
THREE(3){
@Override
void print() {
System.out.println(THREE.value);
}
};
private final int value;
Number(int value) {
this.value = value;
}
abstract void print();
}
public enum Number {
ONE(value -> {
System.out.println(value);
return null;
}),
TWO(value -> {
System.out.println(value);
return null;
}),
THREE(value -> {
System.out.println(value);
return null;
});
private final Function<String,Void> function;
Number(Function<String, Void> function) {
this.function = function;
}
public void print(int value){
this.function.apply(String.valueOf(value));
};
}
어떤 상황에 enum을 사용해야 할까?
제일 중요한 enum의 사용 이유와 방법을 봐야한다.
위에서 상수 클래스 코드가 발전하는 걸 보면서 enum 이 만들어진 이유를 대충 확인해 볼 수 있었다.
이렇게 장황하게 설명한 이유는 enum 을 개발하면서 사용할까? 사용한다면 enum 밖에 방법이 없을까라는 생각을 했기 때문이다.
이번에 공부를 통해서 enum 의 존재 이유와 enum의 사용을 알아볼 수 있었다.
Spring 개발자가 enum을 사용하는 예제는 다음과 같다 (경험 했던 영역 내에서..)
데이터의 그룹화
상태와 행동을 한 곳에서 관리
논리적 동등성을 보장해야할 때 ( DB와 애플리케이션 간에, 서로 다른 데이터간에…)
다음은 현재 프로젝트에서 enum을 사용한 예이다.
@Getter
@RequiredArgsConstructor
public enum ExceptionCode {
/* 401xx AUTH */
INVALID_PHONE_NUMBER_OR_PASSWORD(HttpStatus.UNAUTHORIZED, 40101, "전화번호 또는 비밀번호가 일치하지 않습니다.",
"사용자가 제공한 전화번호나 비밀번호가 데이터베이스의 정보와 일치하지 않을 때 발생합니다."),
FORBIDDEN_ACCESS_TOKEN(HttpStatus.FORBIDDEN, 40102, "토큰에 접근 권한이 없습니다."),
EMPTY_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, 40103, "토큰이 포함되어 있지 않습니다."),
EXPIRED_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, 40104, "재 로그인이 필요합니다.",
"해당 애러 발생시, RefreshToken을 통해 AccessToken을 재발급 해주세요. 해당 오류는 권한이 필요한 모든 엔드포인트에서 발생할 수 있습니다."),
private final HttpStatus httpStatus;
private final int errorCode;
private final String message;
private final String description;
ExceptionCode(HttpStatus httpStatus, int errorCode, String message) {
this(httpStatus, errorCode, message, "");
}
}
다양한 enum 활용 예
Java Enum 활용기 | 우아한형제들 기술블로그 (woowahan.com)
요약
- 데이터들 간에 논리적 동등성을 보장 해야할 때
- 상태와 행위를 한 곳에서 관리 해야할 때
- 데이터 그룹을 관리하기 위한 (데이터 끼리의 추상화)
- DB와 객체간에 패러다임 추상화
public class DaysOfWeekBitmask {
private static final byte MIN_VALID_BITMASK = 0x01; // 00000001
private static final byte MAX_VALID_BITMASK = 0x7F; // 01111111
private final byte bitmask;
......
}
'JAVA > 언어' 카테고리의 다른 글
[JAVA] Reflection을 알아보자 (0) | 2024.09.24 |
---|---|
[JAVA] ThreadLocal (0) | 2024.05.18 |