티스토리 뷰
1. 열거타입(enum)이란?
1-1. 열거타입 정의
💡 관련이 있는 상수의 집합의 클래스.
각각의 열거 상수는 열거 객체로 생성된다.
- 상수란?
- 상수는 변하지 않는 수이다. 예를 들어 하루는 24시간이고 한 시간은 60분이다. 이런 변하지 않는 것을 상수라고 하고 자바에서는 final 이라는 키워드로 선언한다.
- 상수는 값이 한번 정해지면 변경할 수 없다.
- 변수와 다르게 상수명은 모든 문자를 영어 대문자로 작성해야한다.
2. enum 의 등장 배경
2-1. 정수 열거 패턴 단점
- 정수 열거 패턴은 타입 안전을 보장할 방법이 없으며 에러 디버깅이 어렵다.
- 자바에서 별도의 namespace를 지원하지 않아 접두어를 붙여 상수 명을 구분하였어도 실제 프로그램이 기동할 때에 MEAL_AN_BUTTER_KIMCHI_STEW 와 DRINK_RADISH_KIMCHI_LATTE 의 값이 둘 다 0이기 때문에 구분하지 못한다.
- 정수형 상수는 문자열로 출력하기 어렵다.
- 정수형으로 선언된 상수명을 문자열을 출력하고 싶을 때 출력하기 어렵다.
- 정수 열거 그룹에 속한 모든 상수를 순회하는 방법도 쉽지 않다.
- 정수 열거 패턴으로 상수가 선언된 경우 상수에 변경이 발생하면 컴파일을 새로 해야한다.
- 정수 열거 패턴의 경우 해당 값이 클라이언트에 새겨지기 때문에 값이 변경되는 경우 다시 컴파일을 해야한다.
package com.ohgiraffers.section01.intenum;
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
/* 수업목표. 정수 열거 패턴과 이의 단점을 이해할 수 있다.(enum 아닐 떄) */
int subject1 = Subjects.JAVA; // 0
int subject2 = Subjects.HTML; // 0
/* 설명. 1. 둘 다 같은 상수이자 숫자일 뿐 구분할 수 없다.(런타임 시점) */
if (subject1 == subject2) {
System.out.println("두 과목은 같은 과목이다.");
}
/* 설명. 2. 이름 충돌 방지를 위해서는 접두어를 써서 구분해야만 한다.(이름과 번호가 같을 때) */
/* 설명. 3. 변수명에 쓰인 이름(문자열을 출력하기 어렵다.(feat. switch)) */
Scanner sc = new Scanner(System.in);
System.out.print("과목 번호를 눌러주세요(0 ~ 2): ");
int fieldNo = sc.nextInt();
String subName = "";
switch (fieldNo) {
case Subjects.JAVA: subName = "Java"; break;
case Subjects.MARIADB: subName = "MariaDB"; break;
case Subjects.JDBC: subName = "JDBC"; break;
}
System.out.println("선택한 과목명은: " + subName + "입니다.");
/* 설명. 4. 같은 클래스에 속한 상수들을 순회(반복자/반복문)할 수 없다.(필드가 총 몇 개고 어떤 필드들이 있는지) */ // ???????????????????????
/* 설명. 5. 타입 안정성을 보장할 수 없다. */
printSubject(Subjects.JAVA);
printSubject(0); // 그냥 숫자의 개념도 허용이 된다.
}
/* 설명. 매개변수의 의미는 단순히 정수가 넘어온다 밖에 없다.(Subjects라는 개념이 문법적으로 적용되지 X) */
private static void printSubject(int subjectName) {
}
}
package com.ohgiraffers.section01.intenum;
public interface Subjects {
// 열거 패턴에 입각한 상수값(final) 나열
public static final int JAVA = 0;
public static final int MARIADB = 1;
public static final int JDBC = 2;
public static final int HTML = 0;
public static final int CSS = 1;
public static final int JAVASCRIPT = 2;
}
3. 열거 타입의 등장
3-1. 열거타입 선언 및 사용 방법
접근제어자 enum 열거체이름 {
상수명1, 상수명2, ... 상수명XX;
}
3-2. 열거 타입 장점
- 열거 타입은 싱글톤 방식으로 구현되기 때문에 인스턴스의 생성이나 확장이 되지 않는다. 즉, 인스턴스가 통제되며 하나만 존재하는 것이 보장된다.
- 열거 타입은 컴파일 타임 타입 안정성을 높여준다. enumTest() 는 FoodsEnum 타입으로 받도록 선언해 두었기 때문에 다른 타입의 매개변수가 들어오는 경우 컴파일 에러를 발생시켜 준다.
- 열거 타입은 상수 이름을 문자열로 출력할 수 있다.
- 열거 타입에 메소드나 필드를 추가 할 수 있다. 추가로 열거 타입은 근본적으로 불변이라 모든 필드는 final 이어야 한다
- 열거 타입도 클래스이기 때문에 toString() 을 재정의하여 사용할 수 있다.
- 열거 타입에 선언된 상수 하나를 제거하더라도 클라이언트에 영향을 주지 않는다. 혹시나 삭제된 상수를 참조하고 있는 곳이 있다면 컴파일 에러를 출력해주기 때문에 안전하다.
- 열거 타입 내에 선언된 상수들을 순회할 수 있다.
package com.ohgiraffers.section02.enumtype;
public class Application {
public static void main(String[] args) {
/* 수업목표. 열거형(enum)을 이용하여 열거 패턴의 단점을 해결하는 것을 이해할 수 있다. */
Subjects subject1 = Subjects.JAVA;
Subjects subject2 = Subjects.HTML; // 객체 새로 안만들고 만들었던 것을 이용한다. 즉, singleton
Subjects subject3 = Subjects.JAVA;
/* 설명.
* 1. 열거 타입으로 선언된 인스턴스는 싱글톤으로 관리되며 인스턴스가 각각 한 개임을 보장한다.
* 작성한 순서에 따라 각각은 다른 인스턴스가 생성되며 최초 호출 시에 enum의 생성자를 활용해
* 생성된다.(lazy singleton 개념)
* */
if(subject1 == subject2) {
System.out.println("두 과목은 같은 과목이다.");
} else {
System.out.println("서로 다른 과목이다.");
}
/* 설명. 2. 단일 인스턴스임을 보장하기에 == 비교가 가능하다.(동일 객체 비교가 가능하다.) */
if(subject1 == subject3) {
System.out.println("싱글톤이다.");
}
/* 설명. 3. 오버라이딩 되지 않은 toString() 또는 name() 메소드를 활용하여 필드명을 문자열로 변경하기 쉽다.(feat. switch 안씀) */
// 개발할 때 썼던 단어 그대로 사용할 수 있다.
System.out.println(Subjects.JAVA.toString()); // 내가 재정의 할 수 있다.
System.out.println(Subjects.JAVA.name());
/* 설명. 4. values()를 이용하여 상수값 배열을 반환받고 이를 활용하여 연속처리를 해 줄 수 있다. */
Subjects[] subjects = Subjects.values();
for (Subjects sub : subjects) {
System.out.println(sub.toString());
System.out.println(sub.ordinal()); // 인덱스 값으로 먼저 생성된 것을 알려준다.
System.out.println(sub.name());
}
/* 설명. 5. 타입 안정성을 보장한다. */
printSubjects(Subjects.JAVA);
// printSubjects(0); // Subjects 타입이 아니라서 에러 발생
}
private static void printSubjects(Subjects subjects) {
}
}
// 실행 결과
기본 생성자 호출됨...
기본 생성자 호출됨...
기본 생성자 호출됨...
기본 생성자 호출됨...
기본 생성자 호출됨...
기본 생성자 호출됨...
서로 다른 과목이다.
싱글톤이다.
@@@@JAVA@@@@
JAVA
@@@@JAVA@@@@
0
JAVA
@@@@MARIADB@@@@
1
MARIADB
@@@@JDBC@@@@
2
JDBC
@@@@HTML@@@@
3
HTML
@@@@CSS@@@@
4
CSS
@@@@JAVASCRIPT@@@@
5
JAVASCRIPT
package com.ohgiraffers.section02.enumtype;
public enum Subjects {
JAVA, // 0 / = new Subjects(); / Lazy Singleton??????????????????
MARIADB, // 1
JDBC, // 2
HTML, // 3
CSS, // 4
JAVASCRIPT; // 5 / 나열 다 끝나면 세미콜론(;) 찍자!
Subjects() {
System.out.println("기본 생성자 호출됨...");
}
public String toString() {
return "@@@@" + this.name() + "@@@@";
}
}
4. 열거 타입(enum) 문법
package com.ohgiraffers.section03.grammer;
import java.util.EnumSet;
import java.util.Iterator;
public class Application {
public static void main(String[] args) {
/* 수업목표. Enum의 문법에 대해 이해하고 활용할 수 있다.(클래스적인 면모) */
/* 설명.
* enum 타입의 필드를 최초 사용 시에만 열거 타입의 인스턴스를 생성하고 생성자를
* 따로 호출하지 않는다. 또한 enum 타입은 set으로 바꿔 반복시키며 필드들을
* 한번에 확인하고 활용할 수 있다.
* */
UserRole1 admin = UserRole1.ADMIN;
System.out.println(admin.name());
System.out.println(admin.getNameToLowerCase());
UserRole2 consumer = UserRole2.CONSUMER;
System.out.println(consumer.ordinal() + ", " + consumer.name()
+ ", " + consumer.getDescription()); // 클래스적인 면모!!
System.out.println("Set으로 바꿔 반복자를 활용해 보자.");
EnumSet<UserRole2> roles = EnumSet.allOf(UserRole2.class); // UserRole2의 타입(.class)
Iterator<UserRole2> iter = roles.iterator();
while (iter.hasNext()) {
System.out.println(iter.next().name());
}
}
}
// 실행 결과
ADMIN
admin
1, CONSUMER, 구매자
Set으로 바꿔 반복자를 활용해 보자.
GUEST
CONSUMER
PRODUCER
ADMIN
package com.ohgiraffers.section03.grammer;
public enum UserRole1 {
GUEST,
CONSUMER,
PRODUCER,
ADMIN;
/* 설명. 단순한 메소드 하나 추가해 보기 */
public String getNameToLowerCase() {
return this.name().toLowerCase();
}
}
package com.ohgiraffers.section03.grammer;
public enum UserRole2 {
GUEST("게스트"),
CONSUMER("구매자"),
PRODUCER("판매자"),
ADMIN("관리자");
private final String DESCRIPTION;
UserRole2(String description) {
DESCRIPTION = description;
}
public String getDescription() {
return DESCRIPTION;
}
}
'한화시스템 > 백엔드' 카테고리의 다른 글
[BE] Spring AOP (0) | 2024.08.12 |
---|---|
[BE] JAVA_Stream (0) | 2024.07.29 |
[BE] JAVA_컬렉션(Collection)_Map (2) | 2024.07.24 |
[BE] JAVA_컬렉션(Collection)_Set (1) | 2024.07.24 |
[BE] JAVA_컬렉션(Collection)_List (1) | 2024.07.23 |