[whiteship] 11주차 - Enum

prayme·2021년 1월 25일
0
post-thumbnail

학습할 것 (필수)

  • enum 정의하는 방법
  • enum이 제공하는 메소드 (values()와 valueOf())
  • java.lang.Enum
  • EnumSet

Enum

Enum은 몇 가지의 한정된 값만을 가진다.
만약 Week라는 Enum을 정의한다면 월,화,수,목,금,토,일 7개의 값만 가지게 될 것이다.

Enum은 몇가지 특징을 가지고 있다.

  • Enum은 암묵적으로 java.lang.Enum을 상속받는다.
  • generic을 지원하지 않는다.
  • 인터페이스 구현이 가능하다.
  • 부모 클래스가 될 수 없다.
  • 단 하나의 abstract 메소드를 가질 경우에
    모든 열거상수들은 그 메소드를 구현할 수 있다.

public enum Week {
MONDAY {
@Override
void sayHello() {
System.out.println("Hello, Monday");
}
},
...
...
FRIDAY {
@Override
void sayHello() {
System.out.println("Hello, Friday");
}
};
abstract void sayHello();
}



* `new`를 통해 인스턴스화할 수 없다.
> 기본 생성자가 있긴한데 `private`으로 선언이 되어 있다.
또, 열거 상수에 매개변수를 추가할 때 마다 필드가 늘어나는데 필드가 늘어나면 반드시 생성자가 필요하다. 그러나 생성자로는 인스턴스를 생성하지 않고 반드시 `Week.MONDAY`와 같이 생성한다.
생성자는 각각의 열거상수를 힙 스택에 생성할 때 `JVM`이 사용하는 것 같다.


# Enum 정의하기
열거타입과 열거상수로 이루어져있다.
`Enum` 자체로도 `.java`파일을 이룰 수 있고 다른 클래스 안에 정의될 수도 있다.
![](https://media.vlpt.us/images/prayme/post/b6dfafd4-f2c8-4f25-81d4-2bfe4d3fe112/image.png)

만약 멤버 변수, 멤버 메소드를 포함한다면 열거 상수는 
**`;`으로 끝나야하며 반드시 멤버 변수, 멤버 메소드보다 앞에 등장해야 한다.**

또한 열거 상수는 매개변수를 가질 수 있다. 매개변수를 가지는 만큼 필드가 추가되어야 하고 필드를 매개변수로 받는 생성자를 반드시 정의해야 한다.

![](https://media.vlpt.us/images/prayme/post/50eb40af-e1a5-41ac-9cca-cc0676b15018/image.png)

생성자를 선언하지만 `new`를 사용해서 생성자를 호출하여 Enum 인스턴스를 생성할 수 없다.
프로그램이 실행될 때 `Enum`은 각각의 상수들의 숫자만큼 객체로 만들어져 힙 영역에 자동으로 생성된다. 즉 `Week`의 경우 월~일까지 7개의 `Week` 인스턴스가 생성되는 것이다.
이미 생성되어 있기 때문에 `Week w = Week.MONDAY`와 같이 상수를 할당하듯 할당하면 되며 같은 값이라면 열거상수라면 같은 메모리 주소를 참조한다.

```java
Week w1 = Week.FRIDAY;
Week w2 = Week.FRIDAY;
Week w3 = Week.MONDAY;

System.out.println(w1.hashCode());
System.out.println(w2.hashCode());
System.out.println(w3.hashCode()); 

실제로 w1w2hashCode가 같다.

Enum이 제공하는 메소드

static method

values()

Week.values()를 입력하면 모든 열거상수를 리턴한다.
리턴 값은 열거타입이다.

for (Week w : Week.values()) {
  System.out.println(w);
}

valueof()

두 가지 형태가 있다.

Week.valueOf(String)

우리가 정의한 열거타입이 매개변수로 넘겨준 문자열과 동일한 열거상수를 리턴한다.

for (Week w : Week.values()) {
  System.out.println(Week.valueOf(w.toString()));
}

Enum.valueOf(Class<T>, String)

Enumstatic method이다.
우리가 정의한 열거 타입을 첫번째 매개변수로 넘겨주고 두번째 문자열을 넘겨주면 첫번째 매개변수가 가진 두번째 매개변수를 리턴해준다.

for (Week w : Week.values()) {
  System.out.println(Week.valueOf(Week.class, w.toString()));
}

두 메소드 모두 null을 넘겨주던가 일치하는 열거상수가 없다면 Exception이 발생한다.

java.lang.Enum

우리가 정의한 enum 클래스는 java.lang.Enum을 자동으로 상속받는다. 따라서 우리가 정의한 enum 클래스는 다른 클래스를 상속받을 수 없다.

EnumObject를 직접적으로 상속받는다. 위에서 언급한 것처럼 Enum의 생성자는 사용자가 호출할 수없고 컴파일러가 호출할 수 있다.

java.util.EnumSet

SetEnum과 사용하기 좋도록 특수한 형태로 구현한 클래스이다.
마찬가지로 EnumSet 또한 생성자를 통해 생성하지 않는다. static method를 통해 생성할 수 있다.

  • EnumSet.allOf(Class<T>): 매개변수로 받은 enum 클래스의 모든 열거 상수를 가진 EnumSet<T> 리턴
  • EnumSet.of(Enum...): 매개변수로 받은 열거 상수을 가진 EnumSet 리턴
EnumSet<Week> es = EnumSet.allOf(Week.class);
EnumSet es2 = EnumSet.of(Week.MONDAY); // 제네릭이 없어도 됨

System.out.println(es);
System.out.println(es2);

profile
잘하고 싶은 사람

0개의 댓글