애너테이션 (Annotation)

박대운·2022년 11월 14일
0

Java

목록 보기
7/9

애너테이션

애너테이션의 용도

  1. 컴파일러에게 문법 에러를 체크하도록 정보를 제공합니다.
  2. 프로그램을 빌드할 때 코드를 자동으로 생성할 수 있도록 정보를 제공합니다.
  3. 런타임에 특정 기능을 실행하도록 정보를 제공합니다.
@Test // 아래 메서드가 테스트 대상임을 테스트 프로그램에게 알리는 애너테이션
public void run() {...생략...}

public void stop() {...생략...}

위에 정의된 두 개의 메서드 중 @Test 애너테이션이 붙여진 run() 메서드만 테스트 프로그램에게 테스팅이 필요한 메서드로 전달이 되게 됩니다.

주석과 마찬가지로 애너테이션은 해당 테스트를 수행하는 프로그램 외의 다른 프로그램들에게는 아무런 영향을 주지 않습니다. 즉, 명확한 타겟이 있고, 타겟 외의 대상에게는 없는 것과 다름 없는 것입니다.

애너테이션의 종류

자바에서 기본적으로 제공하는 표준 애너테이션과 애너테이션을 정의하는 데 사용되는 ‘애너테이션의 애너테이션’ 메타 애너테이션이 있습니다.

표준 애너테이션: 자바에서 기본적으로 제공하는 애너테이션입니다.

출처. codestates

메타 애너테이션: 애너테이션에 붙이는 애너테이션으로, 애너테이션을 정의하는 데에 사용됩니다.

출처. codestates

표준 애너테이션

@Override

@Override는 메서드 앞에만 붙일 수 있는 애너테이션으로, 선언한 메서드가 상위 클래스의 메서드를 오버라이딩하는 메서드라는 것을 컴파일러에게 알려주는 역할을 수행합니다.

class Super {
	void run() {}
}
class Sub extends Super {
	void rnu() {} // 오버라이딩을 하려고 했으나 오타가 발생함.
}

extends 를 하고 메서드 이름을 다르게 하면 컴파일러는 새로운 메서드를 만든것으로 인식하여 컴파일 오류를 발생하지 않고 런타임오류를 발생시킵니다.

아래 처럼 @Overide를 하면 런타임 오류를 방지 할 수 있습니다.

class Super {
	void run() {}
}
class Sub extends Super {
	@Override
	void rnu() {} // 컴파일 에러 발생, 오타가 난 것을 발견할 수 있음.
}

@Deprecated

@Deprecated 애너테이션은 새로운 버전의 JDK가 소개되어 더 이상 사용하지 않는 필드나 메서드가 있는 경우에 애너테이션이 붙은 대상이 새로운 것으로 대체되었으니 기존의 것을 사용하지 않을 것을 권장하는 데 사용합니다.

즉, 기존 메서드를 하위 버전 호환성 문제로 삭제하기 곤란해 남겨두어야만 하지만 더 이상 사용하는 것을 권장하지 않을 때 @Deprecated를 사용합니다.

class OldClass {
	@Deprecated
	int oldField;

	@Deprecated
	int getOldField() { return oldField; };
}

위처럼 버전호환성이 없는 필드를 사용하지 않을 때 그렇지만 삭제하기 곤란해 남겨두어야 할 때 사용합니다.

@SuppressWarnings

@SuppressWarnings 애너테이션은 컴파일 경고 메시지가 나타나지 않도록 합니다. 경우에 따라서 경고가 발생할 것이 충분히 예상됨에도 묵인해야 할 때 주로 사용합니다.

아래와 같이 @SuppressWarnings 뒤에 괄호를 붙이고 그 안에 억제하고자 하는 경고메세지를 지정해줄 수 있습니다.


출처. codestates

더 나아가 아래와 같은 방법으로 둘 이상의 경고를 한번에 묵인할 수 있습니다.

@SuppressWarnings({"deprecation", "unused", "null"})

@FunctionalInterface

@FunctionalInterface 애너테이션은 함수형 인터페이스를 선언할 때, 컴파일러가 함수형 인터페이스의 선언이 바르게 선언되었는 지 확인하도록 합니다. 만약 바르게 선언되지 않은 경우, 에러를 발생시킵니다.

함수형 인터페이스는 단 하나의 추상 메서드만을 가져야하는 제약이 있습니다.

@FunctionalInterface
public interface Runnable {
	public abstract void run (); // 하나의 추상 메서드
}

메타 에너테이션

@Target

@Target 애너테이션은 이름 그대로 애너테이션을 적용할 “대상"을 지정하는 데 사용됩니다.

출처. codestates

import static java.lang.annotation.ElementType.*; 
//import문을 이용하여 ElementType.TYPE 대신 TYPE과 같이 간단히 작성할 수 있습니다.

@Target({FIELD, TYPE, TYPE_USE})	// 적용대상이 FIELD, TYPE
public @interface CustomAnnotation { }	// CustomAnnotation을 정의

@CustomAnnotation	// 적용대상이 TYPE인 경우
class Main {
    
		@CustomAnnotation	// 적용대상이 FIELD인 경우
    int i;
}

위의 예제에서는 @Target({FIELD, TYPE, TYPE_USE}) 을 사용하여, 각각 필드, 타입, 그리고 타입이 사용되는 모든 대상(변수)에 애너테이션이 적용되도록 한 것을 확인할 수 있습니다.

@Documented

@Documented 애너테이션은 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 하는 애너테이션 설정입니다.

자바에서 제공하는 표준 애너테이션과 메타 애너테이션 중 @Override와 @SuppressWarnings를 제외하고는 모두 @Documented가 적용되어 있습니다.

@Documented
@Target(ElementType.Type)
public @interface CustomAnnotation { }

@Inherited

@Inherited 애너테이션은 이름에서도 알 수 있듯이 하위 클래스가 애너테이션을 상속받도록 합니다. @Interited 애너테이션을 상위 클래스에 붙이면, 하위 클래스도 상위 클래스에 붙은 애너테이션들이 동일하게 적용됩니다.

@Inherited // @SuperAnnotation이 하위 클래스까지 적용
@interface SuperAnnotation{ }

@SuperAnnotation
class Super { }

class Sub extends Super{ } // Sub에 애너테이션이 붙은 것으로 인식

@Retention

@Retention 애너테이션도 이름 그래도 특정 애너테이션의 지속 시간을 결정하는 데 사용합니다.

애너테이션과 관련한 유지 정책(retention policy)의 종류에는 다음의 세 가지가 있습니다.


출처. codestates

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE) 
//오버라이딩이 제대로 되었는지 컴파일러가 확인하는 용도 
//클래스 파일에 남길 필요 없이 컴파일시에만 확인하고 사라짐
public @interface Override(){ }

위의 예제에서 Override 애너테이션은 컴파일러가 사용하면 끝나기 때문에, 실행 시에는 더이상 사용되지 않음을 의미합니다.

@Repeatable

@Repeatable 애너테이션은 애너테이션을 여러 번 붙일 수 있도록 허용한다는 의미를 가지고 있습니다.

@interface Works {  // 여러개의 ToDo애너테이션을 담을 컨테이너 애너테이션 ToDos
    Work[] value(); 
}

@Repeatable(Works.class) // 컨테이너 애너테이션 지정 
@interface Work {
	String value();
}

@Repeatable 애너테이션은 일반적인 애너테이션과 달리 같은 이름의 애너테이션이 여러번 적용될 수 있기 때문에, 이 애너테이션들을 하나로 묶어주는 애너테이션도 별도로 작성해야 합니다.

사용자 정의 애너테이션

사용자 정의 애너테이션은 이름 그대로 사용자가 직접 애너테이션을 정의해서 사용하는 것을 의미합니다.

@interface 애너테이션명 { // 인터페이스 앞에 @기호만 붙이면 애너테이션을 정의할 수 있습니다. 
	타입 요소명(); // 애너테이션 요소를 선언
}

한 가지 유의할 점은, 애너테이션은 java.lang.annotation 인터페이스를 상속받기 때문에 다른 클래스나 인터페이스를 상속 받을 수 없다는 사실입니다.

profile
성장하는사람이 되자

0개의 댓글