본문 바로가기

Programming/Java

[Java] 김영한의 자바 중급 1편 #5 - ENUM

반응형


 

김영한 선생님의 자바 중급을 듣고 정리한 내용입니다.

 

 

 


 

1. 문자열과 타입 안정성 - 문자열

Java가 제공하는 Enum Type을 왜 사용하는지에 대해서 알아보자.

 

만약 Enum Type을 사용하지 않고 문자열을 사용한다면 다음의 문제들이 발생할 수 있다.

 

  • 타입 안정성 부족 : 문자열의 경우 오타가 발생하기 쉽고 유효하지 않은 값이 입력될 수 있다.
  • 데이터 일관성 부족 : 다양한 형식으로 문자열이 입력될 수 있어서 일관성이 떨어질 수 있다.
  • 값의 제한 부족
  • 컴파일 시 오류 감지 불가

 

이런 문제를 해결하려면 문자열이 아닌 특정 범위로 값을 제한해야 한다.

 

예를 들어 BASIC, GOLD, DIAMOND라는 정확한 문자만 사용될 수 있어야 한다.

 

하지만 String 클래스는 어떤 문자들 받을 수 있기 때문에 Java 입장에서는 아무런 문제가 되지 않는다.

 

따라서 String을 사용하는 것을 매우 좋지 않은 방식이다.

 

 

2. 문자열과 타입 안정성2 - 문자열 상수

문자열 상수를 사용하면 상수의 이름을 잘못 입력할 경우 컴파일 시점에 오류가 발생하기 때문에 에러 캐리도 쉬워진다.

 

하지만 문자열 상수를 사용해도 String 타입이기 때문에 어떤 문자열이든 입력할 수 있다.

 

따라서 개발자가 실수로 문자열 상수를 사용하지 않고 직접 문자열을 사용해도 막을 수 있는 방법은 없다.

 

3. 타입 안전 열거형 패턴

Type-Safe Enum Pattern

 

 

3.1. Enum Pattern을 직접 구현해보기

  • 회원 등급을 다루는 클래스를 만들고 각 회원 등급별로 상수를 선언
  • 각각의 상수마다 별도의 인스턴스를 생성하고 생성한 인스턴스를 대입한다.
  • 상수로 선언하기 위해 static final을 사용한다.
    • static : 메서드 영역에 선언
    • final : 인스턴스(참조값)를 변경할 수 없게 한다.

 

 

 

 

 

 

 

각각의 상수는 ClassGrade 타입을 기반으로 인스턴스를 만들었기 때문에 getClass() 결과는 모두 동일

각각의 상수는 서로 다른 ClassGrade 인스턴스를 참조하기 때문에 ref (x001, x002, x003) 값을 다르게 출력

 

 

 

  • discount() 메서드는 매개변수로 ClassGrade 클래스를 사용한다.
  • 값을 비교할 때는 classGrade == ClassGrade.BASIC와 같이 == 참조값(Ref) 비교를 사용한다. → 매개변수로 넘어오는 인수도 ClassGrade가 가진 상수 중에 하나를 사용한다.

 

3.1.1. Private 생성자

위의 방식은 외부에서 임의로 ClassGrade 인스턴스를 생성할 수 있다는 문제가 있다.

→ 이 문제를 해결하려면 ClassGrade를 외부에서 생성할 수 없도록 해야 한다. 기본 생성자를 private으로 변경해야 한다.

 

3.2. Enum Pattern을 직접 구현해보기 - private 생성자

 public class ClassGrade {
     public static final ClassGrade BASIC = new ClassGrade();
     public static final ClassGrade GOLD = new ClassGrade();
     public static final ClassGrade DIAMOND = new ClassGrade();
		//private 생성자 추가
     private ClassGrade() {}
}

 

private 생성자를 사용해서 외부에서 ClassGrade 인스턴스를 임의로 생성할 수 없게 했다.

 

ClassGrade 클래스 내부에서만 ClassGrade 인스턴스를 생성할 수 있게 되었다.

 

이로 인해 ClassGrade 타입에 값을 전달할 때 BASIC, GOLD, DIAMOND 상수만 사용할 수 있게 되었다.

 

 

Type-Safe Enum Pattern 장점

- 타입 안정성 향상 : 정해진 객체만 사용할 수 있기 떄문에, 잘못된 값을 입력하는 문제를 근본적으로 방지할 수 있다.

- 데이터 일관성 : 정해진 객체만 사용하므로 데이터의 일관성이 보장된다.

- 제한된 인스턴스 생성 : 클래스는 사전에 정의된 몇 개의 인스턴스만 생성하고, 외부에서는 이 인스턴스들만 사용할 수 있도록 한다. 이를 통해 미리 정의된 값을만 사용하도록 보장한다.

- 타입 안정성 : 잘못된 값이 할당되거나 사용되는 것을 컴파일 시점에 방지할 수 있게 된다.

 

 

4. 열거형 - Enum Type

자바의 enum은 타입 안정성을 제공하고, 코드의 가독성을 높이며, 예상 가능한 값들의 집합을 표현하는 데 사용된다.

 

  • 열거형을 정의할 때 class 대신 enum을 사용한다.
  • 원하는 상수의 이름을 나열하면 된다.
package lang.enum_ex3;

public enum Grade {
    BASIC, GOLD, DIAMOND
}

 

열거형을 정의할 때는 class 키워드 대신 enum 키워드를 활용한다.

 

원하는 상수의 이름을 나열하기만 하면 된다.

 

열거형으로 작성한 Grade는 다음 코드와 거의 같다고 이해하면 된다.

 public class Grade extends Enum {
     public static final Grade BASIC = new Grade();
     public static final Grade GOLD = new Grade();
     public static final Grade DIAMOND = new Grade();

		//private 생성자 추가
     private Grade() {}
}
  • 열거형도 클래스이다. 다만 자바에서 쉽게 사용할 수 있도록 enum 키워드를 제공하는 것 뿐이다.
  • 열거형은 자동으로 java.lang.Enum을 상속받는다.
  • 외부에서 임의로 생성할 수 없다.

 

 

 

 

 

  • 상수들이 열거형으로 선언한 타입인 Grade 타입을 사용하는 것을 확인할 수 있다. 그리고 각 인스턴스도 서로 다르다.
  • 열거형은 toString()을 오버라이딩하기 때문에 참조값을 직접 확인할 수 없다. 참조값을 구하기 위해 getRefValue() 메서드를 만들었다.
  • System.identityHashCode(grade) : 자바가 관리하는 객체의 참조값을 숫자로 반환한다.
  • Integer.toHexString() : 숫자를 16진수로 변환해준다.

 

 

 

 

4.1. 열거형의 주요 메서드

열거형은 java.lang.Enum 클래스를 자동으로 상속받는다. → 따라서 해당 클래스가 제공하는 메서드들을 사용할 수 있다.

  • values() : 모든 ENUM 상수를 포함하는 배열을 반환한다.
  • valueOf(String name) : 주어진 이름과 일치하는 ENUM 상수를 반환한다.
  • name() : ENUM 상수의 이름을 문자열로 반환한다.
  • ordinal() : ENUM 상수의 선언 순서를 반환한다.
  • toString() : ENUM 상수의 이름을 문자열로 반환한다. (직접 오버라이딩 가능)

 

 

 

> 가급적 ordinal()은 사용하지 않는 것이 좋음
→ 중간에 상수를 선언하는 위치가 변경되면 전체 상수의 위치가 변경될 수 있으며 큰 버그가 발생할 가능성이 있다.

 

4.1.1. 열거형 정리

  • 열거형은 java.lang.Enum을 자동으로 상속받는다. → Enum 클래스의 여러 메서드를 활용할 수 있다.
  • 다른 클래스를 추가로 상속받을 수 없다.
  • 열거형은 인터페이스를 구현할 수 있다.
  • 열거형에 추상 메서드를 선언하고, 구현할 수 있다. → 이 경우 익명 클래스와 같은 방식을 사용한다.

 

 

 

 

반응형