public static final로 선언한 변수
type safety하지 않음public class NotTypeSafety {
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int APPLE = 1;
public static final int BANANA = 2;
public static final int PEACH = 3;
static void printDay(int day) {
if (day == 1) {
System.out.println("오늘은 월요일입니다.");
}
if (day == 2) {
System.out.println("오늘은 화요일입니다.");
}
if (day == 3) {
System.out.println("오늘은 수요일입니다.");
}
}
static void printFruit(int fruit) {
if (fruit == 1) {
System.out.println("사과입니다.");
}
if (fruit == 2) {
System.out.println("바나나입니다.");
}
if (fruit == 3) {
System.out.println("복숭아입니다.");
}
}
public static void main(String[] args) {
int day = MONDAY;
int fruit = APPLE;
printDay(day);
printDay(fruit);
printFruit(day);
printFruit(fruit);
if (day == fruit) {
System.out.println("날짜는 과일입니다.");
} else {
System.out.println("날짜는 과일이 아닙니다.");
}
// 출력 : 날짜는 과일입니다.
}
}상수들의 모아놓은 클래스 =
열거형 클래스
enum 객체를 모아놓은 클래스enum 객체는 public static final
public enum BasicEnum {
FIRST, SECOND, THIRD
}

enum 객체는 필드와 메소드를 가질 수 있음
⇒ enum 객체는 불변 객체이지만 필드는 final로 막지 않으면 바뀔 수도 있음
type safety를 보장하기 위해 사용함public class TypeSafety {
enum Day {MONDAY, TUESDAY, WEDNESDAY}
enum Fruit {APPLE, BANANA, PEACH}
private static void printDay(Day day) {
if (day == Day.MONDAY) {
System.out.println("오늘은 월요일입니다.");
}
if (day == Day.TUESDAY) {
System.out.println("오늘은 화요일입니다.");
}
if (day == Day.WEDNESDAY) {
System.out.println("오늘은 수요일입니다.");
}
}
private static void printFruit(Fruit fruit) {
if (fruit == Fruit.APPLE) {
System.out.println("사과입니다.");
}
if (fruit == Fruit.BANANA) {
System.out.println("바나나입니다.");
}
if (fruit == Fruit.PEACH) {
System.out.println("복숭아입니다.");
}
}
public static void main(String[] args) {
Day day = Day.MONDAY;
Fruit fruit = Fruit.APPLE;
printDay(day);
// printDay(fruit); -> 타입 체크로 인한 컴파일 에러
// printFruit(day); -> 타입 체크로 인한 컴파일 에러
printFruit(fruit);
if (day.equals(fruit)) {
System.out.println("날짜는 과일입니다.");
} else {
System.out.println("날짜는 과일이 아닙니다.");
}
// 출력 : 날짜는 과일이 아닙니다.
}
}선언만으로 기본 생성자를 통해 enum 객체를 만듦
enum의 생성자는 무조건 private
enum BasicEnum {
ONE, TWO, THREE;
}
enum 클래스.상수 이름으로 참조값을 가져올 수 있음 → staticpublic class Test {
public static void main(String[] args) {
BasicEnum one = BasicEnum.ONE;
if (one.equals(BasicEnum.ONE)) {
System.out.println(true);
}
enumParamMethod(BasicEnum.TWO);
}
static void enumParamMethod(BasicEnum param) {
System.out.println(param);
}
}타입 비교가 가능하여 타입 세이프함유지보수가 용이함순회하기 편해짐enum 객체와 연관된 데이터를 상수 객체 자체에 포함시킴
일반적으로 private final로 선언
생성자를 통해 값을 초기화할 수 있음
생성자
private만 가능 → 생성자를 enum 클래스 내부에서만 사용할 수 있음


enum 객체 선언 시 생성자 사용해서 객체를 생성함
각 enum 객체가 각각 다른 동작을 하고 반드시 구현하도록 하려면 추상 메소드를 추가해서 구현하면 됨
public enum Operation {
PLUS('+') {
@Override
int operate(int left, int right) {
return left + right;
}
},
MINUS('-') {
@Override
int operate(int left, int right) {
return left - right;
}
},
MULTIPLY('*') {
@Override
int operate(int left, int right) {
return left * right;
}
},
DIVIDE('/') {
@Override
int operate(int left, int right) {
if (right == 0) {
throw new ArithmeticException("0으로 나눌 수 없습니다.");
}
return left / right;
}
};
private final char operationSign;
Operation(char operationSign) {
this.operationSign = operationSign;
}
public char getOperationSign() {
return operationSign;
}
abstract int operate(int left, int right);
}
다른 클래스의 상속을 받을 수 없음 
모든 enum 객체를 저장한 배열을 생성하여 리턴이 메소드는 java.lang.Enum 클래스에 있는 메소드가 아니라 컴파일 시 추가되는 메소드

InitializeEnum[] values = InitializeEnum.values();
for (InitializeEnum value : values) {
System.out.println("value = " + value);
}
[출력]
value = ONE
value = TWO
value = THREE
enum 객체를 리턴InitializeEnum findEnum = InitializeEnum.valueOf("ONE");
System.out.println("findEnum = " + findEnum);[출력]
findEnum = ONE선언된 순서(int)를 리턴int ordinal = InitializeEnum.THREE.ordinal(); // 순서는 0부터 시작
System.out.println("ordinal = " + ordinal);[출력]
ordinal = 2int gap = InitializeEnum.THREE.compareTo(InitializeEnum.TWO);
System.out.println("gap = " + gap);[출력]
gap = 1String nameMethod = InitializeEnum.ONE.name();
String toStringMethod = InitializeEnum.ONE.toString();
System.out.println("nameMethod = " + nameMethod);
System.out.println("toStringMethod = " + toStringMethod);[출력]
nameMethod = ONE
toStringMethod = ONEname() 메소드는 오버라이딩 불가능함문자열로 출력 시 커스텀하고 싶으면 toString() 메소드를 오버라이딩 해야함

enum 클래스가 반드시 상속받아야 하는 클래스
다른 클래스를 상속받을 수 없음protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

오버라이딩 할 수 없는 메소드개발자가 사용하지 말 것개발자가 사용하지 말 것오버라이딩 가능한 메소드Enum을 위해 고안된 틀별한
Set 인터페이스 구현체
enum 클래스를 담을 Set를 쉽게 정의하기 위해 사용추가하거나 삭제하면 자동으로 반영됨다양한 편의 메소드가 있음public class EnumSetExample {
public static void main(String[] args) {
Set<BasicEnum> realSet = new HashSet<>();
realSet.add(BasicEnum.ONE);
realSet.add(BasicEnum.TWO);
realSet.add(BasicEnum.THREE);
EnumSet enumSet1 = EnumSet.allOf(BasicEnum.class);
System.out.println("enumSet1 = " + enumSet1);
EnumSet enumSet2 = EnumSet.of(BasicEnum.THREE, BasicEnum.TWO);
System.out.println("enumSet2 = " + enumSet2);
EnumSet enumSet3 = EnumSet.complementOf(enumSet2); // BasicEnum.ONE
System.out.println("enumSet3 = " + enumSet3);
EnumSet enumSet4 = EnumSet.range(BasicEnum.TWO, BasicEnum.THREE);
System.out.println("enumSet4 = " + enumSet4);
// 범위가 잘못되면 IllegalArgumentException 발생
// EnumSet enumSet5 = EnumSet.range(BasicEnum.THREE, BasicEnum.ONE);
// System.out.println("enumSet5 = " + enumSet5);
// EnumMap 이라는 것도 있음
EnumMap enumMap = new EnumMap(BasicEnum.class);
enumMap.put(BasicEnum.ONE, 1);
enumMap.put(BasicEnum.THREE, "삼");
System.out.println("enumMap = " + enumMap);
}
}[출력]
enumSet1 = [ONE, TWO, THREE]
enumSet2 = [TWO, THREE]
enumSet3 = [ONE]
enumSet4 = [TWO, THREE]
enumMap = {ONE=1, THREE=삼}