애너테이션(Annotation) @

김설영·2022년 4월 20일
0
  • 주석처럼, 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공한다.

  • 특정 프로그램에게만 정보를 제공함. (설정 정보..등)

  • 사용 예

@Test	// 이 메서드가 테스트 대상임을 테스트 프로그램에게 알린다. (JUnit, 테스트프로그램)
public void method() {
	...
}

표준 애너테이션

@Override : 오버라이딩을 올바르게 했는지 컴파일러가 체크
@Deprecated
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
@Native

// 메타 애너테이션(*가 붙음)
@Target*
@Documented*
@Inherited*
@Retention*
@Repeatable*

@Override

  • 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.

  • 오버라이딩을 할 때, 메서드 이름을 잘못적는 실수를 하는 경우가 많다.

  • 오버라이딩 할 때는, 선언부 위에 @Override를 붙이자.


메타 애너테이션

  • 애너테이션을 위한 애너테이션

  • 메타 애너테이션은 java.lang.annotation 패키지에 포함

  • @Target : 에너테이션을 정의할 떄, 적용 대상 지정에 사용

  • @Retention : 애너테이션이 유지되는 기간을 지정할 때 사용
    SOURCE : 소스 파일에만 존재. 클래스 파일에는 존재하지 않음. (컴파일 하기 전까지만 존재. 컴파일 하고나면 사라짐.)
    CLASS : 클래스 파일에 존재. 실행 시 사용 불가. 기본값. (ClassLoader 까지 존재)
    RUNTIME : 클래스 파일에 존재. 실행 시에 사용 가능. (Runtime 까지 존재)

  • 컴파일러에 의해 사용되는 애너테이션(@Override)의 유지 정책은 SOURCE이다.

  • @FunctionalInterface의 유지 정책은 RUNTIME이다.

  • @Documented : javadoc으로 작성한 문서에 포함시키려면, @Documented를 붙인다.

  • @Inherited : 부모가 가진 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.

  • @Repeatable : 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용

// 적용 대상 지정 (만든 Annotation을 붙일 수 있는 대상을 지정)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)

public @interface SuppressWarnings {
	String[] value();
}

// ex1
@Inherited	// @SuperAnno는 자손까지 영향이 가게 된다. 자동으로 Annotation도 함께 상속됨.
@interface SuperAnno {}	

@SuperAnno
class Parent {}

class Child extends Parent {}  // Child에 @SuperAnno라는 애너테이션이 있는 것으로 인식됨.

// ex2 : Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있다.
// @Repeatable인 애너테이션을 하나로 묶을 컨테이너 애너테이션 정의가 필수임.
@Repeatable(ToDos.class)
@interface ToDo {
	String value();
}

@interface ToDos {	// 여러 개의 ToDo 애너테이션을 담을 컨테이너 애너테이션 ToDos
	ToDo[] value(); // Todo[] 배열 요소 선언. 이름은 반드시 value!
}

@ToDo("delete test codes.")
@ToDo("override inherited methods")
class MyClass{
	...
}

애너테이션 타입 정의하기

  • 애너테이션을 직접 만들어서 쓸 수 있다.

  • 애너테이션의 메서드는 추상메서드이다. 애너테이션을 적용할 때 지정한다. (순서 X)

@interface 애너테이션이름 {
	타입 요소이름();	// 애너테이션의 요소를 선언한다.
}

@interface DateTime {
	String yymmdd();
    String hhmmss();
}

@interface TestInfo {
	int count();
    String testedBy();
    String[] testTools();	// 배열
    TestType testType();	// enum TestType { FIRST, FINAL }
    DateTime testDate();	// 자신이 아닌 다른 애너테이션(@DateTime)을 포함할 수 있다.
}

// 애너테이션 사용. 요소의 값을 타입에 맞게 전부 적어주어야 함.
@TestInfo(
	count=3, testedBy="Kim",
    testTools={"JUnit", "AutoTester"},
    testType=TestType.FIRST,
    testDate=@DateTime(yymmdd="160101", hhmmss="235959")
)
public class NewClass { ... }

애너테이션의 요소

  • 적용시, 값을 지정하지 않으면 사용될 수 있는 기본값 지정 가능(null 제외)

  • 요소가 하나이고, 이름이 value일 때는, 요소의 이름을 생략할 수 있다.

  • 요소의 타입이 배열인 경우, 괄호{}를 사용한다.

// ex1
@interface TestInfo {
	int count() default 1;  // 기본값을 1로 지정
}

@TestInfo  // @TestInfo(count = 1)과 동일
public class NewClass { ... }

// ex2
@interface TestInfo {
	String value();
}

@TestInfo("passed")	 // @TestInfo(value="passed")와 동일
class NewClass { ... }

// ex3
@interface TestInfo{
	String[] testTools();
}	

@TestInfo(testTools={"Junit", "AutoTester"})
@TestInfo(testTools="Junit")
@TestInfo(testTools={})  // 값이 없을 때는, 괄호{}가 반드시 필요

모든 애너테이션의 조상

  • java.lang.annotation.Annotation

  • 조상이지만, 상속은 불가능하다. "Interface"이기 때문.

  • Annotation이 가진 추상 메서드들은 따로 구현하지 않아도 되는데, 이는 컴파일러가 자동으로 해주기 때문이다. 그렇기 때문에, 사용이 가능하다.


마커 애너테이션

  • 요소가 하나도 정의되지 않은 애너테이션

  • 예: @Override, @Test, @Deprecated

  • 요소가 없기 때문에, 아무것도 안적어줘도 됨.


애너테이션 요소의 규칙

  • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다.

  • 메서드의 괄호()안에 매개변수를 선언할 수 없다.

  • 예외를 선언할 수 없다.

  • 요소를 타입 매개변수로 정의할 수 없다. (지네릭 타입 불가)

profile
블로그 이동하였습니당! -> https://kimsy8979.tistory.com/

0개의 댓글