그동안 Java로 문제 풀이를 할 때 enum을 몰라서 string 배열 등을 사용했었는데
enum을 여러 번 듣게 되어서 한 번 정리 및 공부해보려고 한다.
enum
이러한 상수를 단순히 정수로 치부하지 말고 객체 지향적으로 객체화해서 관리하자는 취지
Java에서는 enum을 인터페이스와 같이 독립된 특수한 클래스로 구분
reference 타입으로 분류되며, enum 상수값은 힙 영역에 저장됨
일종의 클래스이지만 인스턴스화는 불가능: 고정된 정수들의 집합으로써 컴파일 타임에 모든 값을 알고 있어야 하기 때
- 장점
- 코드가 단순해지며 가독성이 좋아짐
- 허용 가능한 값들을 제한하여 유형 안전을 제공
- 구현의 의도가 열거임을 분명하게 나타낼 수 있음
- switch문에서도 사용할 수 있음
- 단순 상수와 비교해 IDE의 적극적인 지원을 받을 수 있음
- enum 선언
enum Week{
MONDAY, TUESDAY, WEDNESDAY, TURSDAY, FRIDAY, SATURDAY, SUNDAY
}
enum명은 클래스와 같이 첫 문자를 대문자로 하고 나머지는 소문자로 구성
관례적으로 열거 상수는 모두 대문자로 작성
- enum 참조 방식
// 열거타입 변수 = 열거타입.열거상수;
Week monday = Week.MONDAY;
Week sunday = Week.SUNDAY;
- enum 메소드 종류
- String name(): 열거 객체의 문자열을 리턴
- int ordinal(): 열거 객체의 순번을 리턴
- int compareTo(): 열거 객체를 비교해서 순번 차이를 리턴
- enum valueOf( String name ): 문자열을 입력받아서 일치하는 열거 객체를 리턴
- enum[] values(): 모든 열거 객체들을 배열로 리턴
Week w = Week.FRIDAY;
// 열거 객체의 문자열을 리턴
String weekName = w.name();
System.out.println(weekName); // Spring
Week w = Week.FRIDAY;
// 열거 객체의 순번(0부터 시작)을 리턴
// 전체 열거 객체 중 몇 번째 열거 객체인지 알려준다
int weekNum = w.ordinal();
System.out.println(weekNum); // 4
// 열거 객체를 비교해서 순번 차이를 리턴 (시작점을 어느 열거 객체의 기준으로 몇번째 위치하는지)
Week w1 = Week.TUESDAY; // 2
Week w2 = Week.SATURDAY; // 6
// 열거 객체가 매개값의 열거 객체보다 순번이 빠르다 → 음수를 리턴
int compare1 = w1.compareTo(w2); // SATURDAY 기준으로 TUESDAY 위치 (6에서 2가 되기 위한 값)
System.out.println(compare1); // -4
// 열거 객체가 매개값의 열거 객체보다 순번이 늦다 → 양수를 리턴
int compare2 = w2.compareTo(w1); // TUESDAY 기준으로 SATURDAY 위치 (2에서 6가 되기 위한 값)
System.out.println(compare2); // 4
// 문자열을 입력받아서 일치하는 열거 객체를 리턴
Week w3 = Week.valueOf("SUNDAY"); // w3 변수는 Week.SUNDAY 열거 객체를 참조하게 됨
System.out.println(w3); // SUNDAY
// 모든 열거 객체들을 배열로 리턴
Week[] w4 = Week.values();
System.out.println(Arrays.toString(w4)); // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
for (Week type : Week.values()) { // 열거 순회
System.out.println(type); // 순서대로 열거 객체 출력
}
- java.lang.Enum 클래스
Enum 클래스는 java.lang.Enum이라는 클래스의 상속을 받음
java.lang.Enum 클래스도 Object 클래스를 자동 상속해서 enum에서듀 Object 클래스의 메소드를 그대로 사용 가능
하지만 다음 4개의 메소드를 오버라이딩하지 못함
- clone()
- finalize()
- hashCode()
- equals()
- enum 매핑: 상수를 가져올 때 상수의 고유의 값(value)를 출력하게 만들고 싶을 때 사용
// enum 매핑 클래스
enum Season {
SPRING("봄"),
SUMMER("여름"),
FALL("가을"),
WINTER("겨울");
// 문자열을 저장할 필드
private String season;
// 생성자 (싱글톤)
private Season(String season) {
this.season = season;
}
// Getter
public String getSeason() {
return season;
}
}
public static void main(String[] args) throws Exception {
Season s = Season.SUMMER;
System.out.println(s.name()); // 열거 객체명 출력 : SUMMER
System.out.println(s.getSeason()); // 매핑된 열거 데이터 출력 : 봄
}
- enum 확장
단순히 상수 값을 넘어서 상수 메소드로서도 이용이 가능
추상 메소드를 정의해서 각 상수마다 익명 클래스처럼 메소드 재정의를 하게 해서 각 상수마다 다른 역할을 하는 메소드를 갖게 되는 원리
-> 상수 상태와 행위를 한 곳에서 관리 가능.
-> 상수마다 다르게 동작하는 로직이 필요할 때 객체 지향적인 코드로 유지 보수하기 용이함
enum Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
MULTI("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
// 클래스 생성자와 멤버
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
// toString을 재정의하여 열거 객체의 매핑된 문자열을 반환하도록
@Override
public String toString() {
return symbol;
}
// 열거 객체의 메소드에 사용될 추상 메소드 정의
public abstract double apply(double x, double y);
}
- 람다식으로 더 깔끔하게
// 함수형 인터페이스 임포트
import java.util.function.DoubleBinaryOperator;
enum Operation {
PLUS("+", (x, y) -> x + y),
MINUS("-", (x, y) -> x - y),
TIMES("*", (x, y) -> x * y),
DIVIDE("/", (x, y) -> x / y);
private final DoubleBinaryOperator op; // 람다식을 저장할 필드
private final String symbol;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
@Override
public String toString() { return symbol; }
public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}
public static void main(String[] args) {
double x = 2.5;
double y = 5.0;
// Operation 상수집합의 PLUS 상수를 정의
Operation plus = Operation.PLUS;
// enum 매핑값 출력
String name = plus.toString();
System.out.println(name); // +
// enum 확장 메소드 실행
double result = plus.apply(x, y); // 덧셈을 수행하는 메소드 (Operation.PLUS.apply(x, y) 로 해도됨)
System.out.println(result); // 7.5
// ------------------------------------------------------------------- //
// Operation 상수집합의 PLUS 상수를 정의
Operation multi = Operation.MULTI;
String name = plus.toString();
System.out.println(name); // *
// enum 확장 메소드 실행
double result2 = multi.apply(x, y); // 곱셈을 수행하는 메소드
System.out.println(result2); // 12.5
}
+++ 익명 클래스: 재사용할 필요가 없는 일회성 클래스를 기존의 자식 클래스와 같이 상속시켜 사용하지 않고 익명으로 인라인으로 한방에 선언하여 사용
++++ 익명 클래스 예시
// 부모 클래스
class Animal {
public String bark() {
return "동물이 웁니다";
}
}
public class Main {
public static void main(String[] args) {
// 익명 클래스 : 클래스 정의와 객체화를 동시에. 일회성으로 사용
Animal dog = new Animal() {
@Override
public String bark() {
return "개가 짖습니다";
}
}; // 단 익명 클래스는 끝에 세미콜론을 반드시 붙여 주어야 한다.
// 익명 클래스 객체 사용
dog.bark();
}
}
'프로그래밍 언어 > Java' 카테고리의 다른 글
정규표현식 (0) | 2023.10.17 |
---|---|
포함관계와 추상화 구현 순서 (0) | 2023.10.16 |
추상 클래스와 인터페이스 비교 (0) | 2023.10.16 |
자주 쓰는 함수 (0) | 2023.10.10 |
자료형 String (0) | 2023.09.21 |