728x90
enum이 뭘까??
enum이란 Enumeration의 앞 글자로 열거라는 의미를 갖습니다.
자바에서는 보통 static final을 사용해 상수를 선언하는 데, 상수만을 정의하는 클래스가 필요하다면 enum을 사용할 수 있습니다.
enum은 다음과 같이 사용될 수 있습니다.
public enum LevelOfXp {
ONE(1L,100),
TWO(2L,300),
THREE(3L,600),
FOUR(4L,1000),
FIVE(5L,999999999);
private final Long level;
private final Integer requiredXp;
LevelOfXp(Long level, Integer requiredXp) {
this.level = level;
this.requiredXp = requiredXp;
}
}
Enum의 특징은 다음과 같습니다.
- LevelOfXp.ONE와 같은 형태로 상수처럼 사용할 수 있습니다.
- 여기서 LevelOfXp.ONE, LevelOfXp.TWO등은 힙 영역에 저장되어있습니다.
- enum 클래스의 상수들은 힙 영역에 저장되어 있는 주솟값을 가리킵니다.
- enum은 고정된 상수들의 집합으로써, 런타임이 아닌 컴파일 타임에 모든 값을 알고있어야합니다.
- 생성자가 private 접근 제어자를 가집니다.
- 싱글톤을 보장합니다.
- Enum 클래스는 상속을 지원하지 않습니다. -> 이미 java.lang.enum 클래스에서 상속을 받기 때문이다.(자바는 다중상속 지원x)
만약, 아래와 같이 Enum 클래스의 속성으로 count라는 변수가 추가되었다면, 멀티 쓰레드 환경에서 count가 공유되고 있기 때문에 조심해야합니다.
public enum LevelOfXp {
ONE(1L,100),
TWO(2L,300),
THREE(3L,600),
FOUR(4L,1000),
FIVE(5L,999999999);
private final Long level;
private final Integer requiredXp;
private int count;
LevelOfXp(Long level, Integer requiredXp) {
this.level = level;
this.requiredXp = requiredXp;
}
public void plusCount(){
count++;
}
}
그런데… 왜 Enum을 공부해야할 까??
Enum을 사용하면 아래와 같은 장점을 취할 수 있습니다.
- Enum을 사용하면, 서로 관련된 상수를 정의하기에 유용하다.
- IDE의 적극적인 지원을 받을 수 있다.
- 상태와 행위를 한 곳에서 관리할 수 있다.
- 자바의 열거형은 타입에 안전한 열거형이라서 실제 값과 타입을 동시에 체크한다.
- Enum의 열거형 상수 하나하나가 객체이다!
서로 관련된 상수를 정의하기 유용하다.
아래 코드는 제 프로젝트(sleeper) 코드의 일부입니다.
public enum XpPerLevel {
ONE(1L,100),
TWO(2L,300),
THREE(3L,600),
FOUR(4L,1000),
FIVE(5L,999999999),
;
private final Long level;
private final Integer requiredXp;
XpPerLevel(Long level, Integer requiredXp){
this.level = level;
this.requiredXp = requiredXp;
}
public static Long getCurrentLevel(Integer cumulativeXp, Long level){
return Arrays.stream(XpPerLevel.values())
.filter(x -> x.requiredXp <= cumulativeXp)
.reduce((first,second) -> second)
.map(XpPerLevel::getLevel)
.orElse(level);
}
}
레벨과 각각의 레벨의 최대 경험치 데이터가 관련되어 있다고 생각하여, enum을 사용하여 정의하였습니다.
상태와 행위를 한 곳에서 관리할 수 있다.
아래 코드는 제 프로젝트(sleeper) 코드의 일부입니다.
public enum RewardPerLevel {
ONE(1L, x -> x*1),
TWO(2L, x->x*2),
THREE(3L, x->x*3),
FOUR(4L, x-> x*4),
FIVE(5L, x -> x*5);
private final Long level;
private final Function<Integer,Integer> rewardEquation;
RewardPerLevel(Long level,Function<Integer,Integer> rewardEquation){
this.level = level;
this.rewardEquation = rewardEquation;
}
public static Integer calculateReward(Long level, Integer baseReward){
return Arrays.stream(RewardPerLevel.values())
.filter(x -> x.level == level)
.findAny()
.orElse(ONE)
.rewardEquation
.apply(baseReward);
}
}
레벨에따라서, 리워드가 달라지기때문에 레벨에 따른 리워드를 나타낼 책임을 RewardPerLevel에 두었습니다.
그래서, 케릭터의 레벨 당 받을 수 있는 리워드를 enum을 사용해 정의했습니다.
그리고, ONE,TWO…가 각각 본인만의 계산식을 갖도록 하였습니다.
(Function 인터페이스 사용!)
이상입니다!!
728x90
'JAVA' 카테고리의 다른 글
정적 팩토리 메서드 (1) | 2023.05.23 |
---|---|
인터페이스 default 메서드와 static 메서드 (0) | 2023.04.27 |
Date, Callender 클래스 LocalDateTime 클래스 + mysql과의 연결 (0) | 2022.09.26 |
람다식에 관하여 (0) | 2022.09.23 |
Optional<T>에 관하여 (0) | 2022.09.01 |