• Anotation
    - Java Annotation?
     : 어노테이션은 어노테이션된 요소들의 행동으로부터 프로그램의 행위를 추출하여, 필요하다면 컴파일러나 VM이 상호 의존적인 코드를 생성하는, 프로그램 요소와 메타 태그에 관계된 매커니즘.
     : 사전적으로는 "주석"이라는 의미를 가지고 있으며, 의미대로 자바 코드에 주석처럼 달아 특수한 의미를 부여해준다. 이 특별한 의미는 컴파일 타임 또는 런타임에 해석 될 수 있다.


    - .java부터 .class까지

  •  : .java => Parser => Type checker => [Annotation Checker] => Class File writer => .class


    - 어노테이션 규칙

     : @interface + 어노테이션 이름

     : 어노테이션 소스코드 내부의 메소드 선언은 매개변수를 지닐 수 없다.

     : 어노테이션 소스코드 내부의 메소드 선언은 clauses를 throw 할 수 없다.

     : 메소드의 반환 타입은 primitives, String, Class, enum과 primitives배열, String배열, Class배열, enum배열 중 하나이다.


    - 분류

     1. marker ; @AnnotationTypeName
      : 멤버 변수가 없으며, 단순히 표식으로서 사용되는 어노테이션이다. 컴파일러에게 어떤 의미를 전달한다.

     2. single-element ; @AnnotationTypeName(single-element)
      : 멤버로 단일변수만을 갖는 어노테이션이다. 단일변수 밖에 없기 때문에 (값)만을 명시하여 데이터를 전달할 수 있다.

     3. normal, full-value, multi-value ; @AnnotationName(element=value, element=value, ...)
      : 멤버로 둘 이상의 변수를 갖는 어노테이션으로, 데이터를 (값=쌍)의 형태로 전달한다.


    Built-in Annotation

    == java.lang.annotation (meta-annotation)

    @Retention

     : Retention은 어노테이션이 얼마나 오랫동안 유지되는지에 대해, JVM이 어떻게 사용자 어노테이션을 다루어야 하는지를 서술합니다.

     * SOURCE - 어노테이션이 컴파일 타임시 버려진다는 것을 의미합니다. retention정책이 source로 정의되어 있으면, 클래스 파일은 어노테이션을 지니지 못합니다.

     * CLASS - 어노테이션이 생성된 클래스 파일에서 나타날 것이라는 것을 의미합니다. 그러나 런타임시에는 이 어노테이션을 이용하지 못합니다.

     * RUNTIME- 이는 런타임시 JVM에서 어노테이션의 이용이 가능하다는 것을 의미합니다. 이러한 어노테이션을 읽는 사용자 로직을 가짐으로써 런타임시 무언가를 할 수 있습니다.


    @Target

     : Target은 어디에 어노테이션을 넣을 수 있는지를 서술합니다. field, method, class가 정의된 곳에 어노테이션을 넣을 수 있습니다.

     * TYPE - class, interface, enumeration에 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * METHOD - method 선언에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * PARAMETER - parameter 선언에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * PACKAGE - package 선언에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * FIELD - field 선언에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * LOCAL_VARIABLE - 지역 변수 선언에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * CONSTRUCTOR - 생성자에만 어노테이션을 적용할 수 있다는 것을 의미합니다.

     * ANNOTATION_TYPE - 어노테이션 타입에만 어노테이션을 적용할 수 있다는 것을 의미합니다.


    @Inherited

     - 기본적으로 어노테이션은 상속되지 않습니다. 따라서 상속을 원한다면, 어노테이션을 Inherited 해야 합니다. Inherited 어노테이션이 사용자 어노테이션에 놓여야 하며, 이는 클래스에만 효과가 있습니다. (즉, 상속받는 클래스도 같은 어노테이션 사용)


    @Documented

     - 어노테이션이 기본으로 javadoc 및 유사한 툴에 의해 문서화 되는 것을 나타냅니다. 이러한 형태는 타입의 선언에 주석을 달기 위해 사용합니다. 어노테이션은 클라이언트에 의해 어노테이션된 요소의 사용에 영향을 미치게 됩니다. 타입의 선언에 Documented 어노테이션을 붙인 경우, 그 어노테이션은 어노테이션된 요소의 공개 API중 한 부분이 됩니다.


    == java.lang

    @Override
     : 현재 메소드가 수퍼클래스의 메소드를 오버라이드한 메소드임을 컴파일러에게 명시한다. 만일 수퍼 클래스에 해당하는 메소드가 없으면 컴파일러가 인지하고 에러를 발생시켜 준다.

    @Deprecated
     : 마커 오노테이션으로 차후 버전에 지원되지 않을 수 있기 때문에 더 이상 사용되지 말아야할 메소드를 나타낸다. 특이하게 더이상 사용되지 말아야할 메소드와 같은 라인상에 놓여져야 한다.

    @SuppressWarnings
     : 의미대로 경고를 제거하는 어노테이션이다. Object형을 엘리먼트로 하는 컬렉션을 사용하면, 컴파일러 경고가 발생하는데 이 어노테이션을 사용하여 프로그래머의 의도적인 Object형 사용임을 알려 경고를 제거할 수 있다.

    출처: http://www-01.ibm.com/support/knowledgecenter/SSQ2R2_9.1.0/org.eclipse.jdt.doc.user/tasks/task-suppress_warnings.htm?lang=ko
    Java 5.0부터 java.lang.SuppressWarning 어노테이션을 사용하여 컴파일 단위의 서브세트와 관련된 컴파일 경고를 사용하지 않도록 설정할 수 있습니다.

    @SuppressWarning("unused") public void foo() { String s; }

    어노테이션이 없으면 컴파일러에서 로컬 변수 s를 사용할 수 없습니다. 어노테이션을 사용하여 컴파일러는 이 경고를 foo 메소드에 대해 로컬에서 무시합니다. 이러한 경우 동일한 컴파일 단위 또는 동일한 프로젝트의 다른 위치에 경고를 보관할 수 있습니다.

    SuppressWarnings 어노테이션 내부에서 사용할 수 있는 토큰 목록은 다음과 같습니다.

    • all 모든 경고를 억제합니다.
    • boxing boxing/unboxing 오퍼레이션과 관련된 경고를 억제합니다.
    • cast 캐스트 오퍼레이션과 관련된 경고를 억제합니다.
    • dep-ann 권장되지 않는 어노테이션과 관련된 경고를 억제합니다.
    • deprecation 권장되지 않는 기능과 관련된 경고를 억제합니다.
    • fallthrough switch 문에서 누락된 break 문과 관련된 경고를 억제합니다.
    • finally 리턴되지 않는 마지막 블록과 관련된 경고를 억제합니다.
    • hiding 변수를 숨기는 로컬과 관련된 경고를 억제합니다.
    • incomplete-switch switch 문에서 누락된 항목과 관련된 경고를 억제합니다(enum case).
    • javadoc javadoc 경고와 관련된 경고를 억제합니다.
    • nls 비nls 문자열 리터럴과 관련된 경고를 억제합니다.
    • null 널(null) 분석과 관련된 경고를 억제합니다.
    • rawtypes 원시 유형 사용법과 관련된 경고를 억제합니다.
    • resource 닫기 가능 유형의 자원 사용에 관련된 경고 억제
    • restriction 올바르지 않거나 금지된 참조 사용법과 관련된 경고를 억제합니다.
    • serial 직렬화 가능 클래스에 대한 누락된 serialVersionUID 필드와 관련된 경고를 억제합니다.
    • static-access 잘못된 정적 액세스와 관련된 경고를 억제합니다.
    • static-method static으로 선언될 수 있는 메소드와 관련된 경고를 억제합니다.
    • super 수퍼 호출을 사용하지 않는 메소드 겹쳐쓰기와 관련된 경고를 억제합니다.
    • synthetic-access 내부 클래스로부터의 최적화되지 않은 액세스와 관련된 경고를 억제합니다.
    • sync-override 동기화된 메소드를 오버라이드하는 경우 누락된 동기화로 인한 경고 억제
    • unchecked 미확인 오퍼레이션과 관련된 경고를 억제합니다.
    • unqualified-field-access 규정되지 않은 필드 액세스와 관련된 경고를 억제합니다.
    • unused 사용하지 않은 코드 및 불필요한 코드와 관련된 경고를 억제합니다.

    참고: http://netpyoung.tistory.com/100, http://hiddenviewer.tistory.com/88, https://en.wikibooks.org/wiki/Java_Programming/Annotations/Meta-Annotations

    - Custom Annotation

     : 클래스와 같이 어노테이션을 임의로 정의하여 사용할 수 있다. 어노테이션은 interface 키워드 앞에 @를 붙여 표시한다.
     : @interface InProgress{}

    - 예제

    package kr.co.ioacademy; // ioacademy 윤찬식 강사님
    // Simple JUnit4
    // 어노테이션(Annotation) ; 주석
    // Comment : 비공식적이고 임시적이다.
    // 정의 : 자바의 각 요소(클래스, 메소드, 필드, 매개변수) 가 가질 수 있는
    //        주석 리소스
    
    // 목적
    // 1. 컴파일러에게 추가적인 정보 전달
    // 2. 컴파일 할 때와 설치시의 작업 지정
    // 3. 실행할 때 별도의 처리를 수행
    
    // 기본 어노테이션
    // 1. @Override
    // 2. @Deprecated
    // 3. @SuppressWarnings
    
    // 1. 어노테이션을 만드는 방법.
    
    import java.lang.annotation.*;
    import java.lang.reflect.Method;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface Test {
      boolean enabled() default true;
    }
    
    public class Example7 {
      @Test
      public void testA() {
        System.out.println("testA : do something");
      }
    
      @Test(enabled = true)
      public void testB() {
        System.out.println("testB : do something");
        throw new RuntimeException("failed to run");
      }
    
      @Test(enabled = true)
      public void testC() {
        System.out.println("testC : do something");
      }
    
      public static void main(String[] args) {
        System.out.println("Testing....");
    
        int count = 0;
        int passed = 0;
        int failed = 0;
        int ignore = 0;
    
        Class obj = Example7.class;
        for (Method method : obj.getDeclaredMethods()) {
    
          if (method.isAnnotationPresent(Test.class)) {
            ++count;
            Annotation annotation = method.getAnnotation(Test.class);
            Test test = (Test) annotation;
    
            if (test.enabled()) {
              try {
                method.invoke(obj.newInstance());
                ++passed;
                System.out.printf("Test '%s' - passed\n", method.getName());
              } catch (Throwable e) {
                ++failed;
                System.out.printf("Test '%s' - failed : %s\n", method.getName(),
                    e.getCause());
              }
            } else {
              ++ignore;
              System.out.printf("Test '%s' ignored\n", method.getName());
            }
          }
        } // for
    
        System.out.printf("Result - Total:%d, Passed:%d, Failed:%d, Ignore:%d\n",
            count, passed, failed, ignore);
      }
    
    }
    




'Programing > Java' 카테고리의 다른 글

Effective Java - Exception  (0) 2016.03.09
Effective Java - Reflection  (0) 2016.03.08
Effective Java - 스레드(2)  (0) 2016.03.07
Effective Java - 스레드(1)  (0) 2016.03.07
Effective Java - 불변 객체  (0) 2016.03.07

+ Recent posts