-
[whiteship] 온라인스터디 - 11주차 과제 : EnumIT 발자취.../JAVA 2021. 1. 30. 23:37
github.com/whiteship/live-study/issues/11
목표
자바의 열거형에 대해 학습하세요.
학습할 것 (필수)
- enum 정의하는 방법
- enum이 제공하는 메소드 (values()와 valueOf())
- java.lang.Enum
- EnumSet
enum 정의하는 방법
자바의 열거형 (enum)은 열거형이 갖는 값뿐만 아니라 타입까지 관리하기 때문에 보다 논리적인 오류를 줄일 수 있다.
기존의 많은 언어들이 타입이 달라도 값이 같으면 조건식 결과가 참이었으나 자바의 '타입에 안전한 열거형 (typesafe enum)'에서는 실제 값이 같아도 타입이 다르면 조건식의 결과가 거짓이 된다.
enum 열거형이름 { 상수명1, 상수명2, ... }
예시, 동서남북 4방향을 상수로 정의하는 열거형 Direction
public enum Direction { EAST, SOUTH, WEST, NORTH; }
java.lang.Enum - enum이 제공하는 메소드 (values()와 valueOf())
모든 열거형의 조상은 java.lang.Enum 클래스이다.
docs.oracle.com/javase/10/docs/api/java/lang/Enum.html
타입 메서드 설명 Class<E> getDeclaringClass() 열거형의 Class 객체를 반환한다. String name() 열거형 상수의 이름을 문자열로 반환한다. int ordinal() 열거형 상수가 정의된 순서를 반환한다. (0부터 시작) static <T extends Enum<T>> T valueof(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다. 컴파일러가 자동적으로 추가해주는 메서드
static E values() static E valueOf(String name)
아래는 valueof 메서드의 주석에서 얻어온 문장
* All the constants of an enum type can be obtained by calling the implicit {@code public static T[] values()} method of that type.
public static void main(String[] args) { System.out.printf("Direction EAST getDeclaringClass : %s \n", Direction.EAST.getDeclaringClass()); System.out.printf("Direction EAST name : %s \n",Direction.EAST.name()); System.out.printf("Direction EAST ordinal : %s \n",Direction.EAST.ordinal()); // static method System.out.printf("Direction EAST valueOf (static) : %s \n",Direction.valueOf(Direction.class, "EAST")); // implicit methods // valueOf() - 상수의 이름으로 문자열 상수에 대한 참조를 얻을 수 있다. Direction d= Direction.valueOf("WEST"); System.out.printf("Direction valueOf : %s ", d); // WEST System.out.println(Direction.WEST==Direction.valueOf("WEST")); // TRUE // value() System.out.println("###############################################"); System.out.println("##############Direction.values()###############"); System.out.println("###############################################"); Arrays.stream(Direction.values()) .forEach(direction -> System.out.println(direction.name())); } // Result Direction EAST getDeclaringClass : class com.gintire.pure.week11.Direction Direction EAST name : EAST Direction EAST ordinal : 0 Direction EAST valueOf (static) : EAST Direction valueOf : WEST true ############################################### ##############Direction.values()############### ############################################### EAST SOUTH WEST NORTH
EnumSet
## effective java - 규칙32. 비트 필드(bit field) 대신 EnumSet을 사용하라
EnumSet은 특정한 enum 자료형의 값으로 구성된 집합을 효율적으로 표현할 수 있다.
이 클래스는 Set 인터페이스를 구현하며, Set이 제공하는 풍부한 기능들을 그대로 제공할 뿐 아니라 형 안전성, 그리고 다른 Set 구현들과 같은 수준의 상호운용성도 제공한다.
하지만 내부적으로는 비트 벡터 (bit vector)를 사용한다. enum 값 개수가 64 이하인 경우 EnumSet은 long 값 하나만 사용한다. 따라서 비트 필드에 필적하는 성능이 나온다. removeAll이나 retailAll 같은 일괄 연산도 비트 단위 산술 연산을 통해 구현한다.
더보기비트 열거형 상수
public class Text { public static final int STYLE_BOLD = 1 << 0; //1 public static final int STYLE_ITALIC = 1 << 1; //2 public static final int STYLE_UNDERLINE = 1 << 2; //4 public static final int STYLE_STRIKETHROUGH = 1 << 3; //8 // 이 메서드의 인자는 STYLE_ 상수를 비트별 (bitwise) OR 한 값이거나 0, public void applyStyles (int styles) { // } }
열거 자료형을 집합에 사용해야 한다고 해서 비트 필드로 표현하면 곤란하다.
EnumSet 클래스는 비트 필드 만큼 간결하고 성능도 우수할 뿐 아니라, enum 자료형의 여러 가지 장점을 전부 갖추고 있다.
public class TestEmum { public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } // 어떤 Set 객체도 인자로 전달할 수 있으나, EnumSet이 분명 최선 // 인터페이스를 자료형으로 쓰는 것이 낫다 public void applyStyles(Set<Style> styles) {} }
text.applyStyles(EnumSet.of(TestEmum.Style.BOLD, TestEmum.Style.ITALIC));
EnumMap
public class Herb { enum Type {ANNUAL, PERENNIAL, BIENNIAL} final String name; final Type type; public Herb(String name, Type type) { this.name = name; this.type = type; } @Override public String toString() { return name; } }
Herb[] garden = new Herb[3]; garden[0] = new Herb("Basil", Herb.Type.ANNUAL); garden[1] = new Herb("Lovage", Herb.Type.PERENNIAL); garden[2] = new Herb("Angelica", Herb.Type.BIENNIAL); Map<Herb.Type, Set<Herb>> herbsByType = new EnumMap<Herb.Type, Set<Herb>>(Herb.Type.class); for(Herb.Type t : Herb.Type.values()) herbsByType.put(t, new HashSet<>()); for(Herb h : garden) herbsByType.get(h.type).add(h); System.out.println(herbsByType); //result {ANNUAL=[Basil], PERENNIAL=[Lovage], BIENNIAL=[Angelica]}
'IT 발자취... > JAVA' 카테고리의 다른 글
[whiteship] 온라인스터디 - 12주차. 애노테이션 (0) 2021.02.06 [whiteship] 온라인스터디 - 8주차.인터페이스 (0) 2021.01.09 [whiteship] 온라인스터디 - 6주차. 상속 (0) 2020.12.26 [whiteship] 온라인스터디 - 5주차. 클래스 (0) 2020.12.19 [whiteship] 온라인스터디 - 4주차. 제어문 (0) 2020.12.12 댓글