이펙티브 자바 6장 : 열거 타입과 애너테이션

bo-yoon·2021년 8월 7일
0

effectivejava

목록 보기
5/5

34. int 상수 대신 열거 타입을 사용하라

아래 처럼 사용하면 위험하다. 타입 안전을 보장할 방법이 없으며 표현력도 좋지 않다.

pubic static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPLE = 1;
  • 가장 단순한 열거 타입
public enum Apple { FUJI, PIPPIN, GRANNY_SMITH }
public enum Orange { NAVEL, TEMPLE, BLOOD }

자바의 열거 타입은 완전한 형태의 클래스라서 다른 언어의 열거 타입보다 강력하다. 열거 타입은 싱글턴을 일반화한 형태라고 볼 수 있고, 컴파일 타입 안전성을 제공한다.

열거 타입 상수 각각을 특정 데이터와 연결지으려면 생성자에서 데이터를 받아 인스턴스 필드에 저장하면 된다.


public enum Planet {
	
    	MERCURY ( 3.302e +24, 2.439e6 ),
        VENUS ( 4.869e + 24 , 6.05e6 ),
        EARTH ( 5.975e + 24, 6.378e6 ),
        MARS ( 6.419e + 23 , 3.393e6 )
  
  
        private final double mass;
        private final double radius;
        private final double surfaceGravity;
        
        
        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; }
 }


	
}

toString 이 반환하는 문자열을 해당 열거 타입 상수로 변환해주는 fromString




35. ordinal 메서드 대신 인스턴스 필드를 사용하라

열거 타입 상수에 연결된 값은 ordinal 메서드로 얻지말고 인스턴스 필드에 저장하자.

ordinal 메서드 : enum에서 숫서 인덱스를 반환

적당한 예시


public enum Ensemble {
	SOLO(1), DUET(2), TRIO(3)
    
    
    private final int numberOfMusicians;
    Ensemble(int size) { this.numberOfMusicians =size; }
    public int numberOfMusicians() { return numberOfMusicians; }
}

인스턴스 필드에 저장하지 않고 ordinal 로 반환하는 코드였다면 뭔가 다른 로직을 추가할때 유지보수가 끔찍해질 수 있다.




36. 비트 필드 대신 EnumSet 을 사용하라

열거 할 수 있는 타입을 한데 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다.

 public static final int STYLE_BOLE = 1 << 0;  // 1
public static final int STYLE_ITALIC = 1 << 2 ;  // 2

public void applyStyles(int styles) { ... }


비트 필드 : text.applyStyle(STYLE_BOLD | STYLE_ITALIC) ;
한마디로 비트연산자를 활용해 합집합과 교집합 같은 집합 연산을 사용할 수 있는

public class Text {
	public enum Style { BOLO, ITALIC, UNDERLINE }
    
    public void applyStyles(Set<Style> styles) {... }
}

EnumSet 클래스가 비트 필드 수준의 명료함과 성능을 제공해준다.

EnumSet : enum 인데 여러개 변수




37. ordinal 인덱신 대신 EnumMap 을 사용하라

EnumMap : Map이긴 한데 키가 Enum 인 자료구조

Map<Plant.LifeCycle, Set<Plant>> plantsLifeCycle = new EnumMap<> (Plant.LifeCycle.class );

public enum Phase {
	SOLID, LIQUID, GAS;
    
    public enum Transtition {
      MELT(SOLID, LIQUID) , FREEZE( LIQUID, SOLID),
      BOTL(LIQUID, GAS), CONDENST(GAS, LIQUID);
    }

}

다차원 관계는 EnumMap으로 표시해라




38. 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용해라

타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 그럴 수 없다. 타입 안전 열거 패턴은 결거한 값을 그대로 가져온 다음 값을 더 추가하여 다른 목적으로 쓸수 있지만 열거 타입은 아니다.

하지만 연산 코드용 열거 타입이 임의의 인터페이스로 정의하고 열거 타입이 이 인터페이스를 구현하게 하면된다.




39. 명명 패턴보다 애너테이션을 사용해라



@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {

}


public class Sample {

	@Test public static void m1();
}

애너테이션으로 할 수 있는 일을 명명 패턴으로 처리할 이유는 없다.




40. @Override 애너테이션을 일관되게 사용하라

상위 클래스의 메서드를 재정의하려는 모든 메서드에 @Override 애너테이션을 달자.단 구체 클래스에서 상위 클래스의 추상메서드를 재정의한 경우에는 이 애너테이션을 달 필요 없다.




41. 정의 하려는 것이 타입 이면 마커 인터페이스를 달자.

마커 인터페이스 : 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 것

마커 인터페이스는 2가지 면에서 마커 애너테이션보다 낫다.

1) 마커 인터페이스는 이를 구현한 클래스의 인터페이스들을 구분하는 타입으로 쓸 수 있으나, 마커에네터에션은 그렇지 않다.
2) 적용 대상을 정밀하게 지정할 수 있다.

반대로 마커 애너테이션은 애너테이션 시스템의 지원을 받을 수 있다는 점에서 좋다.

profile
개발 로그 🍎 🍎 🍎

0개의 댓글

관련 채용 정보