열거형(Enum)

Joy🌱·2023년 4월 5일
0

☕ Java

목록 보기
38/40
post-thumbnail

💁‍♀️ Enum이란,
컴퓨터 프로그래밍에서 Enumerated Type(열거형 타입)을 줄여 보통 Enum이라고 지칭하며 요소, 멤버라 불리는 명명된 값의 집합을 이루는 자료형

👀 int Enum VS Enum

👉 int Enum의 사용

◼ Subjects interface

/* 상수필드 : 이 값에 대한 의미를 부여하기 위함 */
public static final int JAVA = 0; 
public static final int ORACLE = 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; 

◼ Application class

public static void main(String[] args) {
		
	/* 정수 열거 패턴(enum이 생기기 전의 패턴)의 문제점 */
		
	/* 1. 정수 값 만을 저장하고 있는 필드일 뿐임 */
	int subject1 = Subjects.JAVA; // 0
	int subject2 = Subjects.HTML; // 0
		
	/* 둘 다 상수 0을 가지기 때문에 구분이 불가능 */
	if(subject1 == subject2) {
		System.out.println("두 과목은 같은 과목 ^^");
	}
		
	/* 2. 변수명 충돌 방지를 위해 접두어를 써서 구분해야함 
	 * BACKEND_JAVASCRIPT = 0; 
	 * FRONTEND_JAVASCRIPT = 0;
	 * */
		
	/* 3. 문자열로 출력하기 까다로움(따로 가공처리가 필요) */
	int num = 0;
	String subjectText = "";
		
	switch(num) {
	case Subjects.JAVA : subjectText = "JAVA"; break;
	case Subjects.ORACLE : subjectText = "ORACLE"; break;
	case Subjects.JDBC : subjectText = "JDBC"; break;
	}
		
	System.out.println("subjectText : " + subjectText);
		
	/* 4. 같은 그룹에 속한 상수들을 순회(반복문 사용) 할 수 없고 전체 상수의 개수 확인도 불가능 */
		
	/* 5. 타입 안정성을 보장할 수 없음 */
	printSubject(Subjects.ORACLE);
	printSubject(1); // Subjects 뿐만 아니라 int 타입으로도 인자 전달 가능
		
}
	
public static void printSubject(int subjectNumber) {
		
	String subjectText = "";
		
	switch(subjectNumber) {
	case Subjects.JAVA : subjectText = "JAVA"; break;
	case Subjects.ORACLE : subjectText = "ORACLE"; break;
	case Subjects.JDBC : subjectText = "JDBC"; break;
	}
		
	System.out.println("subjectText : " + subjectText);
}

👉 Enum의 사용

◼ Subjects enum

/* 작성한 순서대로 0부터 값이 자동으로 부여됨 */
JAVA,		// 0
ORACLE,		// 1
JDBC,		// 2
HTML,		// 3
CSS,		// 4
JAVASCRIPT	// 5

◼ Application class

== toSting() values()

public static void main(String[] args) {
		
	/* 1. 열거 타입(Enum)으로 선언 된 인스턴스는 싱글톤으로 관리되며 인스턴스가 한 개임을 보장 */
	Subjects subject1 = Subjects.JAVA;
	Subjects subject2 = Subjects.HTML;
		
	if(subject1 == subject2) {
		System.out.println("두 과목은 같은 과목이에요!");
	} else {
		System.out.println("두 과목은 다른 과목이에요!"); // 출력
	}
		
	/* 단일 인스턴스임을 보장하기에 == 비교가 가능 */
	System.out.println(subject1 == Subjects.JAVA);	// true
		
	/* 2. 변수명 충돌 방지를 위해 접두사를 쓰지 않아도 Enum 타입별로 네임 스페이스를 가짐
		* 동일한 이름의 상수가 필요하면 Enum 타입별로 네임스페이스를 다르게 하면 됨 
	 * public enum Backend { JAVA, ORECLE, JDBC, JAVASCRIPT }
	 * public enum Frontend { HTML, CSS, JAVASCRIPT }
	 * */
		
	/* 3. toSting()을 이용하여 문자열로 변경하기 쉬움(따로 switch문으로 가공 필요X) */
	System.out.println(Subjects.JAVA.toString());	// JAVA
		
	/* 4. values()를 이용하여 상수 값 배열을 반환하고 이를 통해 연속 처리 가능 */
	Subjects[] subjects = Subjects.values(); // Subjects의 모든 과목 목록이 순회되며 출력
	for(Subjects s : subjects) {
		System.out.println(s);
	}
		
	/* 5. 타입 안정성을 보장 */
	printSubject(Subjects.HTML);
//	printSubject(3); // 정수 열거 패턴에서 확인한 것 처럼 int 타입으로 전달 불가 (타입 안정성 보장)

}

public static void printSubject(Subjects subject) { // int가 아닌 Subjects라는 Enum 타입으로 동작
	System.out.println(subject.toString());
}

👀 Enum 문법

◼ UserRole1 enum

name() toLowerCase()

/* Enum은 상수 하나 하나가 인스턴스화 될 수 있음 */
GUEST,
CONSUMER,
PRODUCER,
ADMIN;	// 생성자 작성 시 열거형 상수 선언 마지막에 세미콜론 붙여야함
	
/* 기본 생성자를 가질 수 있음 
 * default와 private 접근 제한 사용 가능하지만 외부에서 호출은 불가능 (묵시적으로 private)
 * enum 타입은 고정된 상수들의 집합으로 런타임이 아닌 컴파일 시에 모든 값이 결정되어 있어야 함
 * 따라서 다른 클래스에서 enum 타입에 접근해 동적으로 생성자를 이용해 어떤 값을 전달 해줄 수 없기 때문 */
UserRole1() {}
	
/* 필요하다면 메소드도 만들 수 있음 */
public String getNameToLowerCase() {
	return this.name().toLowerCase();
}

◼ UserRole2 enum

/* 각각의 요소들이 특정한 값을 가지게 할 수도 있음 */
GUEST("게스트"), 		// String 값으로 생성자를 호출하기 때문에 생성자를 반드시 생성해야함
CONSUMER("구매자"),
PRODUCER("판매자"),
ADMIN("관리자");
	
private final String description; // description 필드 생성
	
/* 이런 경우에는 매개변수가 있는 생성자가 반드시 필요 
 * enum 상수의 괄호 안에 넣은 값이 해당 생성자 쪽으로 전달 되며 enum 인스턴스가 생성됨 
 * 생성 된 인스턴스는 '싱글톤 객체' */
UserRole2(String description) {
	System.out.println("description : " + description); // 언제 호출되는지 확인하기 위한 출력문
		
	this.description = description; // 받은 String값을 이 생성자가 호출될 때 마다 필드에 초기화
}
	
/* 요소들이 가지는 기본 네임과 정수 값 외의 값을 !외부에서 사용하려고 할 때! 필드로 작성한 값을 반환하도록
 * 메소드를 작성할 수 있음 */
public String getDescription() {
	return this.description;
}

◼ Application class

EnumSet ordinal() getDescription() iterator() hasNext() next() allOf() of()

UserRole1 admin = UserRole1.ADMIN;
System.out.println(admin);
System.out.println(admin.getNameToLowerCase());

/* 최초 enum 타입을 사용할 시 생성자가 호출 됨. 하지만 이것이 동적으로 생성되는 것을 의미하는 것은 아님 */
UserRole2 consumer = UserRole2.CONSUMER;
System.out.println(consumer.ordinal() + " " + consumer.name() + " " + consumer.getDescription()); /* ordinal() : 가지고 있는 숫자 반환 */
/* description : 게스트
   description : 구매자
   description : 판매자
   description : 관리자
   1 CONSUMER 구매자		//	바로 위의 출력문을 통해 출력된 결과
*/
		
/* 최초 사용 시에만 열거 타입의 인스턴스를 생성하고 이후에는 생성자를 호출하지 않음 (두 번째 호출 시에는 생성자 호출 X) */
UserRole2 consumer2 = UserRole2.CONSUMER;
/* 인스턴스는 싱글톤으로 관리되기 때문에 동일 비교 연산으로 비교 가능 */
System.out.println(consumer == consumer2);	// 주소값이 같으므로 true 반환

System.out.println("==========================================================================");
		
/* EnumSet을 활용하여 여러 열거형 타입들을 set(순서 X, 중복 저장 X)으로 취급 가능 */
EnumSet<UserRole2> roles = EnumSet.allOf(UserRole2.class); // allOf() : Enum으로 선언 된 모든 것을 가져옴
/* Iterator로 set 형태인 roles의 순서를 배치 후 순서대로 값 가져옴 */
Iterator<UserRole2> iter = roles.iterator();
while(iter.hasNext()) {
	System.out.println(iter.next().name());
}
		
System.out.println("==========================================================================");
		
/* 특정 상수만 골라서 set에 추가 가능 */
EnumSet<UserRole2> users = EnumSet.of(UserRole2.CONSUMER, UserRole2.PRODUCER); // of() : 특정 상수만 고를 수 있음

Iterator<UserRole2> userIter = users.iterator();
while(userIter.hasNext()) {
	System.out.println(userIter.next().name());
}
		
System.out.println("==========================================================================");
		
/* 특정 상수만 골라서 제거하고 set에 추가 가능 */
EnumSet<UserRole2> exceptGuest = EnumSet.complementOf(EnumSet.of(UserRole2.GUEST)); // complementOf() : 특정 상수만 제외한 나머지만 고를 수 있음

Iterator<UserRole2> exceptGuestIter = exceptGuest.iterator();
while(exceptGuestIter.hasNext()) {
	System.out.println(exceptGuestIter.next().name());
}
profile
Tiny little habits make me

0개의 댓글

관련 채용 정보