// 선언
enum Seasons { SPRING, SUMMER, FALL, WINTER}
enum Language { C, JAVA, PYTHON, JAVASCRIPT}
public class Main {
public static void main(String[] args) {
// 다양한 방식의 Enum 참조
Seasons seasons1 = Seasons.SPRING;
Seasons seasons2 = Seasons.valueOf("SPRING");
Seasons seasons3 = Enum.valueOf(Seasons.class, "SPRING");
System.out.println("Seasons.SPRING == Seasons.SPRING : " + (seasons1 == seasons2));
// System.out.println("Seasons.SPRING > Seasons.SPRING : " + (seasons1 > seasons2)); : 대소비교 불가능
System.out.println("Seasons.SPRING.compareTo(Seasons.SPRING) : " + (seasons1.compareTo(seasons2)));
switch (seasons1) {
// case 문에 열거형 이름 없이 상수 이름만 적어야하는것에 유의
case SPRING:
System.out.println("봄");
break;
case SUMMER:
System.out.println("여름");
break;
case FALL:
System.out.println("가을");
break;
case WINTER:
System.out.println("겨울");
break;
}
}
}
// 다음과 같이 비유될 수 있다.
class Seasons {
static final Seasons SPRING = new Seasons("SPRING");
static final Seasons SUMMER = new Seasons("SUMMER");
static final Seasons FALL = new Seasons("FALL");
static final Seasons WINTER = new Seasons("WINTER");
private String name;
private Seasons(String name) {
this.name = name;
}
}
static final Seasons SPRING = new Seasons(”SPRING”);
처럼 비유될 수 있다.int compareTo()
는 사용 가능// 열거형 상수의 값을 가지기 위해서는 맴버와 생성자가 필요하다.
enum Direction{
EAST(1), SOUTH(5), WEST(-1), NORTH(10)
// 정수를 저장할 맴버(인스턴스 변수) 추가
// 상수이므로 final (제약은 없으나 상수라는 의미상 있는게 맞다.)
private final int value;
// 생성자
// 열거형의 생성자는 제어자가 묵시적으로 private 이다.
Direction(int value){
this.value = value;
}
// getter 를 통해 값을 획득
public int getValue(){
return value;
}
}
enum Coffees {
// 끝에 세미콜론 유의
AMERICANO(10, 150), CAPPUCCINO(110, 75), CAFFELATTE(180, 75), CAFFEMOCHA(290, 95);
// 상수의 값을 담기위한 변수 선언 : private final
private static final Coffees[] COFFEES_ARR = Coffees.values();
private final int kcal;
private final int caffeine;
private static final int dailyMaxCaffeine = 400;
// 생성자 : 열거형은 묵시적 private
Coffees(int kcal, int caffeine) {
this.kcal = kcal;
this.caffeine = caffeine;
}
// 인스턴스 메서드 : 하루 권장섭취량 출력
public void recommendDailyMax(){
System.out.println("섭취한 커피 : " + this);
System.out.println("섭취한 카페인 양 : " + this.caffeine + " mg");
System.out.println("하루 권장 섭취량은 " + dailyMaxCaffeine + "mg 입니다.");
System.out.println("권장 섭취량으로부터 " + (dailyMaxCaffeine - this.caffeine) + "mg 남았습니다.");
System.out.println("***참고 " + this + " 칼로리 정보 : " + kcal + " kcal");
}
// static 변수 : 카페인이 가장 낮은 커피 return
public static Coffees getLowestKcalCoffee(){
int index = 0;
int temp = COFFEES_ARR[0].kcal;
for (int i = 0; i < COFFEES_ARR.length; i++) {
if (temp > COFFEES_ARR[i].kcal){
index = i;
temp = COFFEES_ARR[i].kcal;
}
}
return COFFEES_ARR[index];
}
// getter
public int getKcal() {
return kcal;
}
public int getCaffeine() {
return caffeine;
}
}
public class Main {
public static void main(String[] args) {
// Test2
Coffees latte = Coffees.CAFFELATTE;
// 인스턴스 메서드 출력 : 권장 섭취량 대비 섭취량 출력
latte.recommendDailyMax();
System.out.println();
Coffees americano = Coffees.getLowestKcalCoffee(); // static 메서드 호출
// 인스턴스 메서드 출력 : 권장 섭취량 대비 섭취량 출력
americano.recommendDailyMax();
}
}
// 상수들에 메서드구현에 대한 부분을 추가해야한다.
AMERICANO(10, 150){
boolean isIncludeMilk(){
System.out.println("추상메서드 구현 : private static 필드 사용 : " + dailyMaxCaffeine);
// private 필드는 사용 불가
// System.out.println("추상메서드 구현 : private final 필드 사용 : " + basicValuePrivate);
System.out.println("추상메서드 구현 : protected final 필드 사용 : " + basicValueProtected);
return false;}
},
CAPPUCCINO(110, 75){
boolean isIncludeMilk(){
System.out.println("추상메서드 구현 : private static 필드 사용 : " + dailyMaxCaffeine);
// private 필드는 사용 불가
// System.out.println("추상메서드 구현 : private final 필드 사용 : " + basicValuePrivate);
System.out.println("추상메서드 구현 : protected final 필드 사용 : " + basicValueProtected);
return true;}
},
CAFFELATTE(180, 75){
boolean isIncludeMilk(){
System.out.println("추상메서드 구현 : private static 필드 사용 : " + dailyMaxCaffeine);
// private 필드는 사용 불가
// System.out.println("추상메서드 구현 : private final 필드 사용 : " + basicValuePrivate);
System.out.println("추상메서드 구현 : protected final 필드 사용 : " + basicValueProtected);
return true;}
},
CAFFEMOCHA(290, 95){
boolean isIncludeMilk(){
System.out.println("추상메서드 구현 : private static 필드 사용 : " + dailyMaxCaffeine);
// private 필드는 사용 불가
// System.out.println("추상메서드 구현 : private final 필드 사용 : " + basicValuePrivate);
System.out.println("추상메서드 구현 : protected final 필드 사용 : " + basicValueProtected);
return true;}
};
// ,,, 생략,,,,,,,,,,,,,,,,,,,,,,,,,,
// 추상메서드 선언
abstract boolean isIncludeMilk();
// ,,, 생략,,,,,,,,,,,,,,,,,,,,,,,,,,
private final int basicValuePrivate = 99999;
protected final int basicValueProtected = 77777;
String name()
int compareTo()
열거형 valueOf(String name)
static E valuesOf(String name)
열거형배열 values()
static E values()
Season[] allSeason = Season.values();
int ordinal()
enum 클래스와 함께 동작하는 특수한 Set 컬렉션이다.
java.util.EnumSet
enum 클래스와 함께 동작하는 특수한 Set 컬렉션이다.
컬렉션 Set 의 특징을 가진다.
AbstractSet 및 AbstractCollection이 Set 및 Collection 인터페이스의 거의 모든 메서드에 대한 구현을 제공하지만 EnumSet은 대부분을 재정의한다.
내부적으로 비트벡터로 구현되어있다.
메모리를 적게 효율적으로 사용한다.
***비트벡터란
- 중복되지 않는 정수 집합을 비트로 나타내는 방식이다.
- 최소의 저장공만만으로 정수집합을 표현 가능
- 0~7 의 범위의 정수를 담고자 한다면 1바이트만 있으면 표현 가능
- https://cjh5414.github.io/bit-vector/
- https://velog.io/@jimmy48/비트-벡터Beat-Vector
---
열거형 값을 Set 에 저장할 때 다른 Set 구현체보다 항상 우선시 되어야한다.
이펙티브 자바, 비트 필드 대신 EnumSet을 사용하라
열거할 수 있는 타입을 한데 모아 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다.
EnumSet 클래스가 비트 필드 수준의 명료함과 성능을 제공하고 열거 타입의 장점까지 선사하기 때문이다.
EnumSet의 유일한 단점이라면 불변 EnumSet을 만들 수 없다는 것이다.
그래도 향후 릴리스에서 수정되리라 본다. 그때까지는 Collections.unmodifiableSet으로 EnumSet을 감쌀 수 있다.
// 생성
EnumSet<Coffees> coffees1 = EnumSet.noneOf(Coffees.class);
EnumSet<Coffees> coffees2 = EnumSet.allOf(Coffees.class);
EnumSet<Coffees> coffees3 = EnumSet.of(Coffees.CAFFELATTE, Coffees.AMERICANO);
// 복사
EnumSet<Coffees> coffees4 = EnumSet.copyOf(coffees3);
// 조회
Iterator<Coffees> iterator = coffees2.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println();
// 특정 값 제외
EnumSet<Coffees> complCoffees = EnumSet.complementOf(coffees3);
System.out.println(complCoffees);
iterator = complCoffees.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println();
// 추가
coffees4.add(Coffees.CAPPUCCINO);
iterator = coffees4.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println();
// 포함 확인
System.out.println("카푸치노 포함여부 : " + coffees4.contains(Coffees.CAPPUCCINO));
System.out.println();
// 삭제
coffees4.remove(Coffees.CAPPUCCINO);
System.out.println("카푸치노 포함여부 : " + coffees4.contains(Coffees.CAPPUCCINO));
System.out.println();
noneOf()
allOf()
of()
copyOf()
complementOf()
add()
contains()
remove()