아이템41. 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라

oyeon·2022년 2월 13일
0

Effective Java

목록 보기
2/8

마커 애너테이션 (아이템39 Review)

  • "아무 매개변수 없이 단순히 대상에 마킹(marking)한다"는 뜻에서 마커(marker) 애너테이션이라 한다.
// TYPE의 경우 모든 타입(클래스, 인터페이스, 열거 타입, 애너테이션)에 달 수 있다.
// 부착할 수 있는 타입을 더 세밀하게 제한하지는 못한다는 뜻이다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Developer {

}

@Developer
class Hoyeon {

}

public class MarkerAnnotationTest {
	public static void main(String[] args) {
		Class<?> testClass = Hoyeon.class;
		
		if(testClass.isAnnotationPresent(Developer.class)) {
			System.out.println("Developoer Annotation");
		}
	}
}

실행결과

Developoer Annotation

마커 인터페이스

  • 마커 인터페이스는 일반적인 인터페이스와 동일하지만 사실상 아무 메소드도 선언하지 않은 인터페이스를 말한다.
  • 대표적인 예 - Serializable 인터페이스
package java.io;

public interface Serializable {
}
  • 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다.
/**
 * 특정 인터페이스를 구현한 클래스에만 적용하고 싶은 마커가 있을 경우
 * 이 마커를 인터페이스로 정의했다면, 그냥 마킹하고 싶은 클래스에서만 그 인터페이스를 구현하면 된다.
 * 마킹된 타입은 자동으로 그 인터페이스의 하위 타입임이 보장되는 것이다.
 */
class SomeObject implements Serializable { // Serializable를 상속받지 않은 경우 java.io.NotSerializableException 발생
	private String name;
	private String email;
	public SomeObject(String name, String email) {
		super();
		this.name = name;
		this.email = email;
	}
}

public class MarkerInterfaceTest {
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		serializableTest();
	}
	
	public static void serializableTest() throws IOException, ClassNotFoundException {
		File f = new File("a.txt");
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(f));
		objectOutputStream.writeObject(new SomeObject("wonwoo", "test@test.com"));
	}
}
  • 마커 인터페이스는 적용 대상을 더 정밀하게 지정할 수 있다.

  • 그렇다면 마커 어노테이션의 장점은 뭘까? 마커 어노테이션은 유연하게 확장이 가능하다. 어노테이션을 만들어 사용한 뒤에도 계속적으로 더 많은 정보를 추가할 수 있는 것이 큰 장점이다.

  • 예를 들어, 어떤 어노테이션을 만들고 배포를 한 뒤에 뭔가 더 정보를 추가하고 싶다면 새로 추가된 요소들에 대해 default 값을 갖게 하면 하위 호환성도 지킬 수 있으면 처음에는 마커 어노테이션으로 시작하여 쓰다가 나중에는 기능이 많은 어노테이션으로 진화 가능하다.

  • 하지만 인터페이스 경우에는 메소드를 만드는 순간 하위 호환성이 깨지므로 마커 어노테이션처럼 지속적인 진화는 불가능하다.

핵심 정리

  • 새로 추가하는 메서드 없이 단지 타입 정의가 목적이라면 마커 인터페이스를 선택한다.
  • 클래스나 인터페이스 외의 프로그램 요소에 마킹해야 하거나, 애너테이션을 적극 활용하는 프레임워크의 일부로 그 마커를 편입시키고자 한다면 마커 애너테이션이 올바른 선택이다.
  • 적용 대상이 ElementType.TYPE인 마커 애너테이션을 작성하고 있다면, 정말 애너테이션으로 구현하는게 옳은지, 혹은 마커 인터페이스가 낫지는 않을지 생각하자.

reference
https://woovictory.github.io/2019/01/04/Java-What-is-Marker-interface/

profile
Enjoy to study

0개의 댓글