-
아무 메서드도 선언하지 않은 인터페이스를 말한다.
-
단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 역할을 한다.
-
대표적으로
Clonealbe
,Serializable
이 있다.
마커 인터페이스 예시
public class TestObjcet{
private String name;
private String email;
public TestObjcet(String name, String email) {
this.name = name;
this.email = email;
}
public static void main(String[] args){
final TestObjcet obj = new TestObjcet("kim", "[email protected]");
// clone() 사용
final Object clone = obj.clone();
System.out.println("clone.toString() = " + clone.toString());
}
}
실행 결과
Exception in thread "main" java.lang.CloneNotSupportedException:
at java.base/java.lang.Object.clone(Native Method)
at main.effective_java.stage_6.item_41.TestObjcet.main(TestObjcet.java:22)
Cloneable
인터페이스를 가지지 않은 객체를 clone()할 경우, 위와 같이CloneNotSupportedException
을 발생시킨다.
Cloneable 사용 예시
public interface Cloneable { // 아무것도 정의되어 있지 않다.
}
public class TestObjcet implements Cloneable{
...
public static void main(String[] args){
final TestObjcet obj = new TestObjcet("kim", "[email protected]");
// clone() 사용
final Object clone = obj.clone();
System.out.println("clone.toString() = " + clone.toString());
}
}
실행 결과
clone.toString() = TestObjcet{name='kim', email='[email protected]'}
-
이번에는
Cloneable
인터페이스를 붙여주고 실행해주면, 올바르게 복제되는 것을 확인할 수 있다. -
즉
Cloneable
인터페이스는 "나 clone() 가능한 클래스야~" 라고 알리는 셈인다. -
이처럼 아무 메서드도 없고, 특정 속성을 가졌다는 것 알리는 역할을 하는 인터페이스를 마커 인터페이스라고 한다.
마커 애너테이션 예시
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
-
마커 인터페이스와 동일하게 아무 메서드도 가지지 않은 애너테이션을 말한다.
-
아래와 같은
meta-annotaiton(메타 애너테이션)
을 이용해 만든다. -
@Target
: 해당 애너테이션을 어디에 적용시킬지 정한다. -
@Retention
: 해당 어네테이션이 적용되고 유지되는 범위를 정한다.
meta-annotaiton(메타 애너테이션) 이란?
다른 애너테이션에서도 사용되는 애너테이션을 말한다.
예를 들어, @Service 안에 들어가있는
@Component
,@Target
,@Retention
등을 말한다.
마커 애너테이션이 등장하면서 마커 인터페이스는 구식이 되는 것 같지만
실제로는 2가지 면에서 마커 인터페이스가 애너테이션보다 장점을 가지고 있다.
-
마커 인터페이스는 어엿한 타입이다.
-
만약 인스턴스를 잘못사용했다면, 마커 인터페이스의 경우는 컴파일 단계에서 문제를 발견할 수 있다.
-
하지만 애너테이션의 경우, 컴파일이 아닌 런타임 단계에서 문제가 발생한다.
-
마커 애너테이션을 정의할때, 만약
@Target
을ElementType.TYPE
으로 선언한다면 모든 타입에 달 수 있다. -
모든 타입 : 클래스, 인터페이스, 열거 타입, 애너테이션
-
즉, 타입을 더 세밀하게 제한하지 못한다.
그래서 애너테이션을 적극사용하는 프레임워크에서는 애너테이션이 더 유리할 수 도 있다.
🤷♂️ 그렇다면 우리는 어떤 기준으로 선택하는 것이 좋을까?
아래의 질문들에 답해보면서 인터페이스 혹은 애너테이션을 고르면 좋을 것 같다.
-
만약 마킹이 된 객체를 매개변수로 주고 받는 경우가 존재하는가?
- 이 경우, 인터페이스가 유리하다.
- 인터페이스을 사용하면 적용대상을 더 정밀하제 지정할 수 있고, 컴파일 단계에서 문제를 잡을 수 있다.
-
만약 클래스와 인터페이스 외의 프로그램 요소에 마킹해야되거나 애너테이션 관련 프레임워크를 사용하는가?
- 이 경우, 애너테이션이 유리하다
- 클래스와 인터페이스만이 인터페이스를 구현하거나 확장할 수 있기 때문이다.