열거형
열거형은 서로 연관된 상수들의 집합을 의미하며 final 키워드를 사용하여 선언할 수 있다. 열거형은 이러한 상수들을 보다 간편하게 관리할 때 유용하게 사용할 수 있는 자바의 문법 요소이며 주로 몇 가지로 한정된 변하지 않는 데이터를 다룰 때 사용한다.
초기 버전의 자바에서는 enum 문법을 지원하지 않아서 public static final을 통해 전역변수로 상수를 설정하여 아래와 같이 사용했다.
// 여러 상수를 정의하기 위한 예전 방식
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int FALL = 3;
public static final int WINTER = 4;
다만 이러한 경우 상수 명이 중복되는 경우가 종종 발생할 수 있다.
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int FALL = 3;
public static final int WINTER = 4;
public static final int DJANGO = 1;
public static final int SPRING = 2; // 계절의 SPRING과 중복 발생!
public static final int NEST = 3;
public static final int EXPRESS = 4;
상수 이름이중복되면 컴파일 에러가 발생한다. 위의 문제는 인터페이스를 사용하여 상수를 구분함으로써 아래와 같이 일차적으로 해결할 수 있다.
interface Seasons {
int SPRING = 1, SUMMER = 2, FALL = 3, WINTER = 4;
}
interface Frameworks {
int DJANGO = 1, SPRING = 2, NEST = 3, EXPRESS = 4;
}
다만 위의 경우 중복 상수는 피할 수 있지만 타입의 안정성이라는 새로운 문제가 생긴다. 예를 들면 위의 예시 코드에서 Seasons.SPRING의 정수값 1과 Frameworks.SPRING 정수값 2는 상수를 열거하기 위한 임의의 숫자임에도 아래와 같이 비교하는 코드를 작성할 수 있다.
if (Seasons.SPRING == Frameworks.SPRING) {...생략...}
숫자는 전혀 의미가 있는 값이 아니며 두 SPRING은 의미로 다른 개념임에도 불구하고 둘을 비교하면 에러가 발생하지 않아 타입의 안정성이 떨어진다. 이런 문제를 해결하기 위해서는 다시 아래와 같이 서로 다른 객체로 만들어주어야 한다.
class Seasons {
public static final Seasons SPRING = new Seasons();
public static final Seasons SUMMER = new Seasons();
public static final Seasons FALL = new Seasons();
public static final Seasons WINTER = new Seasons();
}
class Frameworks {
public static final Frameworks DJANGO = new Frameworks();
public static final Frameworks SPRING = new Frameworks();
public static final Frameworks NEST = new Frameworks();
public static final Frameworks EXPRESS = new Frameworks();
}
위의 코드처럼 객체를 생성해주면 상수 명 중복과 타입 안정성 모두 해결할 수 있다. 다만 코드가 너무 길어지고 switch문에 활용할 수 없는 문제가 생긴다. 이런 맥락에서 해당 문제들을 가장 효과적으로 해결하기 위해 만들어진 것이 enum 이다.
enum Seasons { SPRING, SUMMER, FALL, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, EXPRESS }
이처럼 enum을 사용하면 앞선 문제들을 모두 효과적으로 해결할 수 있고 코드를 단순하고 가독성이 좋게 만들 수 있으며 switch 문에서 사용이 가능하다. 아래에서 switch 문을 사용할 때 public static final을 사용하여 정의한 상수와 enum을 사용하여 정의한 상수가 각각 어떻게 작동하는지 확인해보자.
class Seasons {
public static final Seasons SPRING = new Seasons();
public static final Seasons SUMMER = new Seasons();
public static final Seasons FALL = new Seasons();
public static final Seasons WINTER = new Seasons();
}
public class Main {
public static void main(String[] args) {
Seasons seasons = Seasons.SPRING;
switch (seasons) {
case Seasons.SPRING:
System.out.println("봄");
break;
case Seasons.SUMMER:
System.out.println("여름");
break;
case Seasons.FALL:
System.out.println("가을");
break;
case Seasons.WINTER:
System.out.println("겨울");
break;
}
}
}
/*
출력값
java: incompatible types: Seasons cannot be converted to int
*/
위의 코드는 호환되지 않는 타입이라는 에러가 발생한다. 이유는 switch문의 조건은 char, byte, short, int, Character, Byte, Short, Integer, String, enum 타입만 가능하고, 위의 seasuns는 사용자 정의 타입이기 때문이다. enum으로 구성된 코드는 제대로 출력되는지 확인해보자.
enum Seasons {SPRING, SUMMER, FALL, WINTER}
public class Main {
public static void main(String[] args) {
Seasons seasons = Seasons.SPRING;
switch (seasons) {
case SPRING:
System.out.println("봄");
break;
case SUMMER:
System.out.println("여름");
break;
case FALL:
System.out.println("가을");
break;
case WINTER:
System.out.println("겨울");
break;
}
}
}
//출력값
봄
위의 코드처럼 enum을 사용하면 switch 문을 사용할 수 있다는 것을 확인할 수 있다.
정리하자면 자바에서 열거형은 여러 상수들을 보다 편리하게 선언하고 관리할 수 있게 하며, 상수 명의 중복을 피하고, 타입에 대한 안정성을 보장한다. 또한 같은 효과를 낼 수 있는 다른 코드에 반해 훨씬 더 간결하고 가독성이 좋은 코드를 작성할 수 있으며 switch 문에서도 작동이 가능하다.
열거형의 사용
enum을 사용하여 사계절을 상수로 정의하면 다음과 같다.
enum Seasons {
SPRING, //정수값 0 할당
SUMMER, //정수값 1 할당
FALL, //정수값 2 할당
WINTER //정수값 3 할당
}
참고로 상수는 관례적으로 대문자로 작성한다.각각의 열거 상수들은 객체이기 때문에 Seasons라는 이름의 열거형은 SPRING, SUMMER, FALL, WINTER 총 네 개의 열거 객체를 포함하고 있다고 말할 수 있다. 각각의 상수들은 따로 값을 지정해주지 않아도 자동적으로 0부터 시작하는 정수값이 할당되어 각각의 상수를 가리키게 된다.
enum Seasons { SPRING, SUMMER, FALL, WINTER }
public class EnumExample {
public static void main(String[] args) {
System.out.println(Seasons.SPRING); // SPRING
}
}
위의 코드처럼 열거형에 선언된 상수에 접근하는 방법은 열거형이름.상수명 을 통해서 가능하다.
아래 코드를 통해 참조변수 favoriteSeason에 Seasons.SPRING을 담아보도록 하자.
enum Seasons { SPRING, SUMMER, FALL, WINTER }
public class EnumExample {
public static void main(String[] args) {
Seasons favoriteSeason = Seasons.SPRING;
System.out.println(favoriteSeason); // SPRING
}
}
보는 바와 같이 Seasons.SPRING을 Seasons 타입의 참조 변수에 할당하고 있다.
enum Level {
LOW, // 0
MEDIUM, // 1
HIGH // 2
}
public class Main {
public static void main(String[] args) {
Level level = Level.MEDIUM;
switch(level) {
case LOW:
System.out.println("낮은 레벨");
break;
case MEDIUM:
System.out.println("중간 레벨");
break;
case HIGH:
System.out.println("높은 레벨");
break;
}
}
}
//출력값
중간 레벨
위의 코드를 보면 Level 이라는 열거형을 하나 만들고 세가지 열거상수 LOW, MEDIUM, HIGH 를 선언하였다. 그리고 열거형과 같은 타입의 참조변수 level에 Level.MEDIUM 값을 할당하고 switch 문을 통해 해당 값에 대한 출력값을 얻을 수 있다.
이처럼 enum을 사용하면 변경되지 않는 한정적인 데이터들을 효과적으로 관리할 수 있다.
아래 메서드들은 java.lang.Enum에 정의되어 있는 것으로 클래스 Object에 정의된 메서드들을 사용할 수 있던 것과 동일하다고 볼 수 있다.
리턴타입 | 메서드(매개변수) | 설명 |
String | name() | 열거 객체가 가지고 있는 문자열을 리턴하며, 리턴되는 문자열은 열거타입을 정의할 때 사용한 상수 이름과 동일합니다. |
int | ordinal() | 열거 객체의 순번(0부터 시작)을 리턴합니다. |
int | compareTo(비교값) | 주어진 매개 값과 비교해서 순번 차이를 리턴합니다. |
열거 타입 | valueOf(String name) | 주어진 문자열의 열거 객체를 리턴합니다. |
열거 배열 | values() | 모든 열거 객체들을 배열로 리턴합니다 |
enum Level {
LOW, // 0
MEDIUM, // 1
HIGH // 2
}
public class EnumTest {
public static void main(String[] args) {
Level level = Level.MEDIUM;
Level[] allLevels = Level.values();
for(Level x : allLevels) {
System.out.printf("%s=%d%n", x.name(), x.ordinal());
}
Level findLevel = Level.valueOf("LOW");
System.out.println(findLevel);
System.out.println(Level.LOW == Level.valueOf("LOW"));
switch(level) {
case LOW:
System.out.println("낮은 레벨");
break;
case MEDIUM:
System.out.println("중간 레벨");
break;
case HIGH:
System.out.println("높은 레벨");
break;
}
}
}
//출력값
LOW=0
MEDIUM=1
HIGH=2
LOW
true
중간 레벨
몇 가지 열거형 메서드를 사용한 예제이다.
먼저 values() 메서드는 컴파일러가 자동적으로 모든 열거형에 추가해주는 메서드로 Level에 정의된모든 상수를 배열로 변환했다. 열거형의 최상위 클래스로부터 확장된 name()과 ordinal()을 사용하여 각각 이름과 순서를 출력값으로 반환하고 있다. 마지막으로 valueOf() 메서드를 활용하여 지정된 열거형에서 이름과 일치하는 열거형 상수를 반환하고, 반환된 상수가 의도했던 상수와 일치하는지 여부를 불리언 값으로 확인하고 있다.
'공부 > 전자컴퓨터공학' 카테고리의 다른 글
Java 예외처리(Exception Handling)란? 자바 기초 배우기 (1) | 2024.05.28 |
---|---|
Java 제네릭(Generic) 이란? 자바 기초 배우기 (0) | 2024.05.28 |
Java 추상화(Abstraction) 란? 자바 기초 배우기 (1) | 2024.05.28 |
Java 다형성(polymorphism) 이란? 자바 기초 배우기 (0) | 2024.05.27 |
Java 캡슐화란? 자바 기초 배우기 (0) | 2024.05.27 |