Skip to content

Latest commit

 

History

History
158 lines (120 loc) · 6.5 KB

Annotation.md

File metadata and controls

158 lines (120 loc) · 6.5 KB

Anntation

  • 1. Annotation 무엇인가?
  • 2. 어디에, 어떻게 Annotation를 사용할까?



1. Annotation 무엇인가?



Annotation은 주석처럼, 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공한다. 코드를 작성할 때, 컴파일전, 문법 에러를 체크할 수 있고, 빌드나 배포시 코드를 자동으로 생성할 수 있도록 정보 제공을 해준다. 특정 기능을 실행하도록 정보를 제공해주기도 한다.

예전 자바에서 소스코드를 작성할 때, 프로그램에 대한 문서를 따로 작성하게 되었다. 즉 Class 또는 Method에 대한 정보를 따로 문서 작성하게 되니, 소스코드와 문서와의 불일치가 발생하게 되었다. 그래서, 소스코드와 문서와 합쳐 /* */(javadoc)주석을 이용해서, 작성하게 되었다.

Annotation은 소스코드와 XML 파일(설정 파일)의 경우도 서로 분리되어있다 보니, 둘 간의 불일치가 자주 발생하게 되었고, 소스코드와 XML 파일(설정 파일)을 합쳐, Annotation이 생겨나게 되었다.

Annotation은 Junit이라는 특정 프로그램을 위해, 정보를 제공하기위해 생겨났다. 예를 들어 @Test와 같이 프로그램에 설정 정보를 심게 되었다. 다음의 표는 자바에서 제공하는 Annotation으로 *가 붙은 것은 메타 애너테이션이다.

메타 Annotation은 Annotation을 만들 때 사용한다.

Annotation 설명
@Override 컴파일러에게 오버라이딩을 하는 메서드라는 것을 알린다.
@Deprecaled 앞으로 사용하지 않을 것을 권장하는 대상에 붙인다.
@SuppressWarnings 컴파일러의 특정 경고메시지가 나타나지 않게 해준다.
@SafeVarargs 제네릭 타입의 가변인자에 사용한다.
@FunctionalInterface 함수형 인터페이스라는 것을 알린다.
@Native native메서드에서 참조되는 상수 앞에 붙인다.
@Target* Annotation이 적용가능한 대상을 지정하는데 사용한다.
@Documented* Annotation 정보가 javadoc으로 작성된 문서에 포함되게 한다.
@Inherited* Annotation 자손 클래스에 상속이 되도록 한다.
@Retention* Annotation이 유지되는 범위를 지정하는데 사용한다.
@Repeatable* Annotation을 반복해서 적용할 수 있게 한다.



2. 어디에, 어떻게 Annotation을 사용할까?


Annotation을 직접 커스텀화 시킬 수 있다. Annotation의 메서드는 추상 메서드ㅣ며, Annotation을 적용할 때 지정(순서X)한다. Annotation의 메서드는 추상 메서드이므로, 구현이 필요 없다.

 @interface AnnotationName {
    // Annotation의 요소를 선언한다.
    Type elementName();
 }

 // 예시
 @interface DateTime {
    // abstract method
    String yymmdd();
    Stirng hhmmss();
 }

 // 사용 예시
 @DateTime(
    yymmdd = "230415",
    hhmmss = "013032"
 )
 public class clazz { ... }

 // 또한 Annotation안에 Annotation을 사용할 수 있다.
 @interface TestInfo {
    int count();
    String testedBy();
    String[] testTools();
    TestType testType(); // Enum TestType = {FIRST, FINAL}
    DateTime testDate(); // This!
 }

 // 사용 예시
 @TestInfo(
    count = 3,
    testedBy = "wonho",
    testTools = {"Junit", "AutoTester"},
    testType = TestType.FIRST,
    testDate = @DateTime(yymmdd = "230415", hhmmss = "013032")
 )
 public class newClass { ... }

 // Annotation은 적용시 값을 지정하지 않으면, 사용될 수 있는 default값이 사용된다.
 @interface TestInfo {
    int count() default 1;
 }
 @TestInfo // @TestInfo(count = 1)과 동일
 public class newClass { ... }

 // 요소가 하나이고, 메서드 이름이 value일 때는 요소의 이름을 생략할 수 있다.
 @interface TestInfo {
    String value();
 }
 @TestInfo("passed") // @TestInfo(value="passed")와 같다.
 public class newClass { ... }

 // 요소의 타입이 배열인 경우 값이 하나가 아닌 경우 {}로 감싸줘야 한다.
 @interface TestInfo {
    String[] testTools();
 }
 @TestInfo(testTools={"Junit", "AutoTester"})
 @TestInfo(testTools="Junit")
 @TestInfo(testTools={}) // 값이 없을 때는 {}가 필요하다.

모든 Annotation의 조상은 interface Annotation이다. 하지만, 상속은 불가능 하다. 코드를 통해 봐보자.

 @interface TestInfo extends Annotation { // <- extends Annotation 에러를 일으킨다. 하지만, 상속을 받지는 않지만 Annotation 인터페이스의 추상 메서드를 구현하지 않고도 사용이 가능하다.
    ...
 }

 package java.lang.annotation;

 public interface Annotation { // Annotation 자신은 인터페이스이다.
    boolean equals(Object obj);
    int hashCode();
    String toString();

    Class<? extends Annotation> annotationType(); // 애너테이션의 타입을 반환
    // 하지만, Annotation의 interface에 있는 추상 메서드를 구현하지 않아도 사용이 가능하다. 컴파일러가 자동으로 메서드를 추가해 주기 때문이다.
 }

Marker Annotation으로 요소가 하나도 정의 되지 않은 Annotation을 의미한다.

 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.SOURCE)
 public @interface Override {} // Marker Annotation 정의된 요소가 없다.

 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.SOURCE)
 public @interface Test {} // Marker Annotation 정의된 요소가 없다.

 // 따라서 정의 된게 없으므로, 그냥 붙이면 된다.
 @Test // 이 메서드가 테스트 대상임을 테스트 프로그램(Junit)에게 알린다.
 public void method() { ... }

 @Deprecated
 public int getdate() { ... }

Annotation 요소의 규칙을 지켜야 한다. 요소의 타입은 기본형, String, enum, Annotation, Class(설계도 객체)만 허용된다. ( )안에 매개 변수를 선언할 수 없으며, 예외를 선언할 수 없다. 요소를 타입 매개 변수로 정의할 수 없다. 다음의 코드를 보고 잘못된 부분을 찾아보자.

 @interface AnnoTest {
    int id = 100; 
    String major (int i, int j); // 매개변수를 선언할 수 없다.
    String minor () throws Exception; // 예외를 던질 수 없다.
    ArrayList<T> list(); // 요소를 타입 매개 변수로 정의할 수 없다.
 }