Point 34. int 상수 대신 열거형을 사용하세요.
-
정수 열거형 패턴 – 꽤 깨지기 쉽습니다!
public class IntegerConstants { public static final int APPLE_FUJI = 0; public static final int APPLE_PIPPIN = 1; public static final int APPLE_GRANNY_SMITH = 2; public static final int ORANGE_NAVEL = 0; public static final int ORANGE_TEMPLE = 1; public static final int ORANGE_BLOOD = 2; }
위의 정수 열거형 패턴은 형식 안전성을 보장할 수 없으며 표현력이 없습니다.
오렌지를 전달해야 하는 메서드에 사과를 보냅니다.
동등 연산자(==)
컴파일러는 경고 메시지를 발행하지 않습니다.
- 가장 단순한 열거형
public enum Apple { FUJI, PIPPIN, GRANNY_SMITH } public enum Orange { NAVEL, TEMPLE, BLOOD }
Java의 열거형은 완전한 형식의 클래스이므로 다른 언어의 열거형보다 훨씬 강력합니다.
실제로 열거형은 외부에서 액세스할 수 있는 생성자를 제공하지 않습니다.
final
오전.따라서 클라이언트가 인스턴스를 직접 생성하거나 확장할 수 없기 때문에 열거형 선언으로 생성된 인스턴스는 하나만 존재함을 보장합니다.
만약에.
Apple
열거 유형을 매개변수로 사용하는 메소드를 선언할 때 전달되는 참조는 다음과 같습니다.
Apple
확실한 것은 이것이 세 가지 가치 중 하나라는 것입니다.다른 유형의 값을 전달하려고 하면 컴파일 타임 오류가 발생합니다.
-
데이터 및 메서드가 포함된 열거형
public enum Planet { MERCURY(3.302e+23, 2.439e6), VENUS (4.869e+24, 6.052e6), EARTH (5.975e+24, 6.378e6), MARS (6.419e+23, 3.393e6), JUPITER(1.899e+27, 7.149e7), SATURN (5.685e+26, 6.027e7), URANUS (8.683e+25, 2.556e7), NEPTUNE(1.024e+26, 2.477e7); private final double mass; // 질량(단위: 킬로그램) private final double radius; // 반지름(단위: 미터) private final double surfaceGravity; // 표면중력(단위: m / s^2) // 중력상수(단위: m^3 / kg s^2) private static final double G = 6.67300E-11; // 생성자 Planet(double mass, double radius) { this.mass = mass; this.radius = radius; surfaceGravity = G * mass / (radius * radius); } public double mass() { return mass; } public double radius() { return radius; } public double surfaceGravity() { return surfaceGravity; } public double surfaceWeight(double mass) { return mass * surfaceGravity; // F = ma } }
열거된 각 유형 상수를 특정 데이터와 연결하려면 생성자로부터 데이터를 수신하고 인스턴스 필드에 저장하기만 하면 됩니다.
위의 행성 예제에 표시된 속성은 연관 유형이 사용되는 대부분의 상황을 잘 설명합니다.
그러나 더 많은 기능을 제공하기 위해 상수를 원할 때가 있습니다.
-
값으로 분기하는 enum 유형 – 만족하십니까?
public enum Operation { PLUS, MINUS, TIMES, DIVIDE; public double apply(double x, double y){ switch (this){ case PLUS: return x+y; case MINUS: return x-y; case TIMES: return x*y; case DIVIDE: return x/y; } throw new AssertionError("알 수 없는 연산: " + this); } }
위의 소스는 작동하지만 다른 작업을 추가하려면 case 문을 추가해야 합니다.
case 문을 잊어버리고 추가하지 않으면 컴파일 타임 오류가 발생하지 않으며 실행 유형 중에 “알 수 없는 작업” 오류가 발생합니다.
따라서 각 상수에 대한 클래스 본문, 즉 각 상수에서 다시 정의하는 방법이 있습니다.
-
상수로 메서드를 구현한 열거형
public enum Operation2 { PLUS { public double apply(double x, double y){ return x+y; } }, MINUS { public double apply(double x, double y){ return x-y; } }, TIMES { public double apply(double x, double y){ return x*y; } }, DIVIDE { public double apply(double x, double y){ return x/y; } }; public abstract double apply(double x, double y); // 추상 메서드를 선언 }
위와 같은 추상 메소드
apply
다른 작업을 추가할 때 메소드 구현을 추가하지 않는 경우.컴파일 오류가 없기 때문에 안전합니다.
참고 자료
Joshua Bloch, 『Effective Java 3/E』, 잘 번역됨, Programming Insight (2018)
http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788966262281&orderClick=LEa&Kc=