-
아이템41. 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라책/이펙티브자바 2021. 8. 31. 13:59
아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스를 마커 인터페이스 (marker interface)라 한다.
ex. Cloneable, Serializable
// 그냥 비어있음. public interface Serializable { }
마커 애너테이션의 예
ex. @Override, @FunctionalInterface, @SafeVarargs, @Native
Serializable 은 자신을 구현한 클래스의 인스턴스는 ObjectOutputStream 을 통해 쓸수(write) 있다고, 즉 직렬화(serialization) 할 수 있다고 알려준다.
마커 인터페이스는 두 가지 면에서 마커 애너테이션보다 낫다.
- 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다.
- 마커 인터페이스는 어엿한 타입이기에, 마커 애너테이션을 사용했다면 런타임에야 발견될 오류를 컴파일 타임에 잡을 수 있다.
- 적용 대상을 더 정밀하게 지정할 수 있다.
- 애노테이션의 경우 @Target 선언 으로 모든 타입에 달 수 있다.
- 부착 할 수 있는 타입을 더 세밀하게 제한하지는 못한다는 뜻이다.
- 근데 특정 인터페이스를 구현한 클래스에만 적용하고 싶은 마커가 있다고 치면, 이 마커를 인터페이스로 정의했다면 그냥 마킹하고 싶은 클래스에서만 그 인터페이스를 구현하면 된다.
- 마킹된 타입은 자동으로 그 인터페이스의 하위 타입임이 보장되는 것이다.
반대로 마커 애너테이션이 마커 인터페이스보다 나은점으로는 거대한 애너테이션 시스템의 지원을 받는다는 점이 있다.
따라서 애너테이션을 적극 활용하는 프레임워크에서는 마커 애너테이션을 쓰는 쪽이 일관성을 지키는데 더 유리할 것이다.
그렇다면 언제 마커 애너테이션을, 언제 마커 인터페이스를 사용하는가 ?
- 클래스와 인터페이스 외의 프로그램 요소 (모듈, 패키지, 필드, 지역변수 등)에 마킹해야 할 때 애너테이션을 쓸 수 밖에 없다.
- 마커를 클래스나 인터페이스에 적용해야 한다면 "이 마킹이 된 객체를 매개변수로 받는 메서드를 작성할 일이 있을까? " 를 자문해보자.
- 그렇다 → 마커 인터페이스를 쓴다.
- 마커 인터페이스를 해당 메서드의 매개변수 타입으로 사용하여 컴파일 타임에 오류를 잡아낼 수 있따.
- 아니다 → 마커 애너테이션을 쓴다.
- 추가로 애너테이션이 활발한 프레임워크라면 ? → 마커 애너테이션을 쓴다.
결론
- 마커 인터페이스와 마커 애너테이션은 각자의 쓰임이 있다.
- 새로 추가하는 메서드 없이 단지 타입 정의가 목적이면 마커 인터페이스를 쓰자.
- 클래스나 인터페이스 외의 프로그램 요소에 마킹해야 하거나, 애너테이션을 적극적으로 쓰는 프레임워크라면 마커 에너테이션을 쓰자.
- 적용 대상이 ElementType.TYPE 인 마커 애너테이션을 작성하고 있다면, 이게 정말 애너테이션으로 구현하는게 올흥ㄴ지, 혹은 인터페이스가 낫지는 않을지 곰곰이 생각해보자.
'책 > 이펙티브자바' 카테고리의 다른 글
아이템29. 이왕이면 제네릭 타입으로 만들라 (0) 2021.09.01 아이템28. 배열보다는 리스트를 사용하라 (0) 2021.09.01 아이템40. @Override 애너테이션을 일관되게 사용하라 (0) 2021.08.31 아이템39. 명명 패턴보다 애너테이션을 사용하라 (0) 2021.08.31 아이템50. 적시에 방어적 복사본을 만들라 (0) 2021.08.30 - 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다.