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

이펙티브 자바

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

아무 구현이 없고 단지 자기를 구현하는 클래스가 특성 속성을 가짐을 표시해주는것 인터페이스를 마커인터페이스라고 한다.

대표적인 예가 Serializable이다 그럼 코드를 보면

1
2
3
4
5
6
7

package java.io;

public interface Serializable {
}


마커인터페이스는 두가지 측면에서 마커 인터페이스 보다 낫다.

첫번째 마커 인터페이스는 이를 구현한 클래스의 인스턴스를 구분하는 타입으로 쓸수 있으나 마커 어너테이션은 아니다.

이부분은 아래의 예제를 통해서 보겠다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

package com.github.sejoung.codetest.annotation.markerannotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Developer {

}



@Target에 ElementType.TYPE 이면 Class나 interface 그리고 enum에 사용할수 있는데 이부분에 대한 설명이다.

1
2
3
4
5
6
7
8
9
10
11
12

package com.github.sejoung.codetest.annotation;

import com.github.sejoung.codetest.annotation.markerannotation.Developer;

@Developer
public class Sejoung {


}


이런식으로 선언하면 해당 값을 판별 할수있는것이 런타임때 아래와 같이 할수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

package com.github.sejoung.codetest.annotation;

import com.github.sejoung.codetest.annotation.markerannotation.Developer;

public class RunTests {
public static void main(String[] args) {
Class<?> testClass = Sejoung.class;

if(testClass.isAnnotationPresent(Developer.class)){
System.out.println("Developer Annotation");
}

}
}

실행결과

1
2
3
Developer Annotation

Process finished with exit code 0

하지만 인터페이스를 사용하면 코드레벨에서 컴파일시에 할수있다 예제를 보면

마커 인터페이스

1
2
3
4
5
6
7
8

package com.github.sejoung.codetest.annotation.markerinterface;

public interface Developer {

}


1
2
3
4
5
6
7
8
9
10
11

package com.github.sejoung.codetest.annotation;

import com.github.sejoung.codetest.annotation.markerannotation.Developer;

public class Sejoung {


}


1
2
3
4
5
6
7
8
9
10
11
12

package com.github.sejoung.codetest.annotation;

import com.github.sejoung.codetest.annotation.markerinterface.Developer;

public class RunTests {
public static void main(String[] args) {
Developer developer = new Sejoung();

}
}

메시지

1
2
3

Error:(14, 86) java: incompatible types: com.github.sejoung.codetest.annotation.Sejoung cannot be converted to com.github.sejoung.codetest.annotation.markerinterface.Developer

위와 같이 컴파일 시점에 알수있다.

두번째 장점은 적용대상을 좀더 정밀히 지정할수 있다.

어너테이션은 모든타입에 달수 있으니 모든 타입을 다 검사해야 되지만 인터페이스는 인터페이스를 구현한 클래스만이 하위클래스임을 보장하는것이다.

그럼 마커 어너테이션의 장점은 거대한 어너테이션 시스템의 지원을 받는다는 것이다.

클래스의 타입을 정의 할때는 한번더 생각해 보아야 된다.

참조