본 게시글은 백기선 님의 live-study 과제를 수행하면서 작성한 글입니다.
목표
자바의 열거형에 대해 학습하세요.
학습할 것 (필수)
- enum 정의하는 방법
- enum이 제공하는 메서드 (values()와 valueOf())
- java.lang.Enum
- EnumSet
열거형(Enum)이란?
열거형은 서로 관련이 있는 여러 상수를 편리하게 선언하기 위한 것으로, C언어와 달리 자바에서는 원래 열거형이 존재하지 않았지만 JDK1.5부터 새로 추가되었다.
C언어의 열거형은 타입이 달라도 값이 같다면 == 비교에서 true를 리턴 하지만, 자바의 열거형은 '타입에 안전한 열거형'이라서 값이 같더라도 타입이 다르면 컴파일 에러가 발생한다.
enum 정의하는 방법
enum 열거형이름 {상수명1, 상수명2, ... }
예를 들어 학점을 나타내는 열거형을 정의하면 다음과 같다.
enum Grade { A, B, C, D, F }
열거형에 정의한 상수는 '열거형이름.상수명' 형태로 사용할 수 있다.
public class Main {
public static void main(String[] args) {
Student kim = new Student("kim", Grade.A);
if(kim.getGrade() == Grade.A) {
System.out.println("열거형은 == 비교 가능");
}
//<, >과 같은 비교연산자는 사용할 수 없고,
//compareTo() 메서드로 비교한다.
//같으면 0, 왼쪽이 크면 양수, 오른쪽이 크면 음수 반환
System.out.println(Grade.A.compareTo(Grade.B));
}
static class Student {
private String name;
private Grade grade;
public Student(String name, Grade grade) {
this.name = name;
this.grade = grade;
}
public String getName() {
return name;
}
public Grade getGrade() {
return grade;
}
}
}
열거형에 멤버 추가하기
Enum 클래스에 정의된 ordinal() 메서드가 열거형 상수가 정의된 순서를 반환해주긴 하지만, 상수 값이 불연속적이거나 필요에 따라 열거형에 멤버를 추가해 값을 따로 지정해 줄 수 있다.
public enum Grade {
//()안에 상수 값 지정.
A(100),B(80),C(60),D(50),F(30);
//지정된 값을 저장할 수 있는 인스턴스 변수와 생성자를 추가해야한다.
private final int minScore;
//열거형 생성자의 접근 제어자는 묵시적으로 private이기 때문에 객체를 생성할 수 없다.
Grade(int minScore) {
this.minScore = minScore;
}
//외부에서 값을 불러오기위한 용도
public int getMinScore() {
return minScore;
}
}
예제에는 인스턴스 변수를 minScore 1개 사용했지만, 클래스와 마찬가지로 여러 개를 사용할 수 있다.
열거형에 추상 메서드 추가하기
열거형에 추상 메서드를 선언하는 일은 거의 없으므로 가볍게 참고만 하자.
public enum Grade {
A(100) {
@Override
void abstractMethod() { /*code*/ }
}
},
B(80){
@Override
void abstractMethod() { /*code*/ }
}
},
C(60){
@Override
void abstractMethod() { /*code*/ }
},
...생략
abstract void abstractMethod();
}
enum이 제공하는 메소드 (values()와 valueOf())
열거형에는 컴파일러가 자동으로 추가해주는 메서드가 있다.
- values() : 열거형의 모든 상수를 배열에 담아 반환.
- valueOf() : 열거형 상수의 이름으로 문자열 상수에 대한 참조를 얻을 수 있다.
Grade[] grades = Grade.values();
for (Grade grade : grades) {
System.out.println("grade = " + grade);
}
/*
결과
grade = A
grade = B
grade = C
grade = D
grade = F
*/
System.out.println(Grade.valueOf("A") == Grade.A); //결과 : true
java.lang.Enum
java.lang.Enum 클래스는 모든 열거형의 조상 클래스로 다음과 같은 메서드들이 정의되어 있다.
- Class getDeclaringCase() : 열거형의 class객체를 반환.
- String name() : 열거형 상수의 이름을 반환.
- int ordinal() : 열거형 상수가 저장된 순서를 반환.(0부터 시작)
- static <T extends Enum <T>> T valueOf(Class enumType, String name) : 지정한 열거형에서 name과 일치하는 열거형 상수를 반환
Grade grade = Grade.A;
System.out.println(grade.getDeclaringClass()); //결과: 패키지명.Grade
System.out.println(grade.name()); //결과 : A
System.out.println(grade.ordinal());// 결과 : 0, 열거형을 선언할 떄 가장 먼저 선언한 상수이기 떄문에 0.
System.out.println(Enum.valueOf(Grade.class, "A")); //결과 : A
EnumSet
java.util 패키지에 있으며, Set인터페이스를 상속하고 있다.
//지정한 열거형의 모든 상수를 포함한 set 생성.
EnumSet<Grade> allOfSet = EnumSet.allOf(Grade.class);
//지정한 열거형 상수를 포함하는 set 생성.
EnumSet<Grade> partitionGrade = EnumSet.of(Grade.B, Grade.C);
//열거형의 모든 상수 중 지정한 열거형 set에 포함되지 않은 열거형 상수 set 생.
EnumSet<Grade> complementOfSet = EnumSet.complementOf(partitionGrade);
//지정 열성거형의 비어있는 set 생성.
EnumSet<Grade> noneOfSet = EnumSet.noneOf(Grade.class);
//지정한 범위의 열거형 상수 set 생성.
EnumSet<Grade> rangeSet = EnumSet.range(Grade.B, Grade.D);
System.out.println("allOfSet = " + allOfSet);
System.out.println("partitionGrade = " + partitionGrade);
System.out.println("complementOfSet = " + complementOfSet);
System.out.println("noneOfSet = " + noneOfSet);
System.out.println("rangeSet = " + rangeSet);
/*
결과
allOfSet = [A, B, C, D, F]
partitionGrade = [B, C]
complementOfSet = [A, D, F]
noneOfSet = []
rangeSet = [B, C, D]
*/
Enum의 내부 구현
열거형의 상수는 내부적으로 객체로 구현되어 있다. 즉 A, B, C, D, F 상수 하나하나가 모두 Grade의 객체라는 뜻이다.
enum Grade { A, B, C, D, F }
위의 enum을 클래스로 정의하면 다음과 같다.
public class Grade {
static final Grade A = new Grade("A");
static final Grade B = new Grade("B");
static final Grade C = new Grade("C");
static final Grade D = new Grade("D");
static final Grade F = new Grade("F");
private String name;
public Grade(String name) {
this.name = name;
}
}
열거형 상수 하나 하나가 static 상수이고 객체이기 때문에 '==' 비교가 가능했던 것이다.
참고
- 자바의 정석 3판(남궁성 저)
'자바 > 스터디' 카테고리의 다른 글
[자바 스터디] 13주차 과제 - I/O (0) | 2021.02.19 |
---|---|
[자바 스터디] 12주차 과제 - 애노테이션(Annotation) (0) | 2021.02.05 |
[자바 스터디] 10주차 과제 - 쓰레드 (0) | 2021.01.23 |
[자바 스터디] 9주차 과제 - 예외 처리 (0) | 2021.01.15 |
[자바 스터디] 8주차 과제 - 인터페이스 (0) | 2021.01.08 |
댓글