quilt code

[고급자바] Annotation 본문

daily/고급자바

[고급자바] Annotation

김뱅쇼 2023. 2. 6. 20:25

1. Annotation 애너테이션


프로그램 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속한 형식으로 포함시킨 것(JDK 1.5부터 지원)
주석처럼 프로그램 코드에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공함.


종류
1) 표준(일반) 애너테이션
2) 메타 애너테이션(애너테이션을 위한 애너테이션, 즉 애너테이션을 정의할 때 사용하는 애너테이션)
    애너테이션을 생성할때를 위한 또 다른 애너테이션


애너테이션 타입 정의하기
@interface애너테이션이름 {
     요소타입 타입요소이름();        //반환값이 있고 매개변수는 없는 추상메소드의 형태
     ....
  }


애너테이션 요소의 규칙
  1) 요소타입은 기본형, String, enum, annotation, class만 허용된다.
  2) () 안에 매개변수를 선언할 수 없다.
  3) 예외를 선언할 수 없다
  4) 요소의 타입에 타입 매개변수(제너릭타입글자)를 사용할 수 없다.

 

**주석처럼 붙일 수 있음 

 

1
2
3
4
5
6
7
8
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)  // 애너테이션이 유지되는 기간
 
public @interface PrintAnnotation {
    int id = 100;   // 상수 선언 가능 static붙여서 선언하는거랑 똑같음 
    String value() default "-";   // 기본값을 "-"로 지정
    int count() default 20;       // 기본값을 20으로 지정
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package kr.or.ddit.basic;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
 
 
public class AnnotationTest {
    public static void main(String[] args) {
        
        // Reflection API를 이용한 메소드 정보 가져오기
        // 선언된 메소드 목록 가져오기
        Method[] declaredMethods = Service.class.getDeclaredMethods();
        
        for(Method m : declaredMethods) {
            Annotation[] annos = m.getDeclaredAnnotations();
            
            System.out.println("메소드 명 : " + m.getName());
            
            for(Annotation anno : annos) {
                if(anno.annotationType().getSimpleName().equals("PrintAnnotation")) {
                    PrintAnnotation printAnno = (PrintAnnotation) anno;
                    
                    System.out.println("value값 : " + printAnno.value());
                    System.out.println("count값 : " + printAnno.count());
                    
                    for(int i=0; i<printAnno.count(); i++) {
                        System.out.println(printAnno.value());
                    }
                    
                    
                }
            }
            
            System.out.println("-------------------------------------------------------");
                        
        }                
    }
 
}
cs

 

 

2. Java Reflection

  
  1) 리플렉션은 런타임 시점에 클래스 또는 멤버변수, 메소드, 생성자 등에 대한 정보를 가져오거나 수정할 수 있고, 
      새로운 객체를 생성하거나 메소드를 실행할 수 있다.
      (컴파일 시점에 해당 정보를 알 수 없는 경우(소스코드 부재)에 유용하게 사용될 수 있다.)
  2) Reflection API는 java.lang.reflect 패키지와 java.lang.class를 통해 제공된다.
  3) java.lang.class의 주요 메소드
      - getName(), getSuperClass(), getInterfaces(), getModifiers() 등.
  4) java.lang.reflect 패키지의 주요 클래스
      - Field, Method, Constructor, Modifier 등.

**알지못하는 정보들을 가져오는 역할

**어노테이션된 정보들을 가져옴 (어노테이션에 저장된 정보들을 리플렉션해서 가져옴)

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) throws ClassNotFoundException{
        // 첫번째 방법 : Class.forName() 메소드 이용
        Class<?> klass = Class.forName("kr.or.ddit.reflction.T01ClassObjectCreationTest");
        
        
        // 두번째 방법 : getClass() 메소드 이용
        T01ClassObjectCreationTest obj = new T01ClassObjectCreationTest();
        klass = obj.getClass();
        
        // 세번째 방법 : .class 이용
        klass = T01ClassObjectCreationTest.class;
    }
 
cs

 

 

 

3. Class의 메타정보 가져오기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class T02ClassMetadataTest {
    public static void main(String[] args) {
        
        // 클래스 오브젝트 생성하기
        Class<?> clazz = SampleVO.class;
        
        System.out.println("심플클래스명 : " + clazz.getSimpleName());
        System.out.println("클래스명 : " + clazz.getName());
        System.out.println("상위클래스명 : " + clazz.getSuperclass());
        
        // 패키지정보 가져오기
        Package pkg = clazz.getPackage();
        System.out.println("패키지 정보 : " + pkg.getName());
        
        // 해당 클래스에서 구현하고 있는 인터페이스 목록 가져오기
        Class<?>[] interfaces = clazz.getInterfaces();
        
        for(Class<?> inf : interfaces) {
            System.out.println(inf.getName() + " | ");
        }
        System.out.println();
        
        // 클래스의 접근제어자 정보 가져오기
        int modFlag = clazz.getModifiers();
        
        System.out.println("접근제어자 : " + Modifier.toString(modFlag));
    }    
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package kr.or.ddit.reflection;
 
import java.io.Serializable;
 
public class SampleVO implements Serializable{
    
    public String id;
    protected String name;
    private int age;
    
    public SampleVO(String id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    public SampleVO() {    
    }
    
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    
    @Deprecated
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "SampleVO [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
}
 
cs

 

 

 

4. 클래스에 선언된 메소드의 메타정보 가져오기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package kr.or.ddit.reflection;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
 
/**
 *   클래스에 선언된 메소드의 메타정보 가져오기
 */
 
public class T03MethodMetadataTest {
    public static void main(String[] args) throws ClassNotFoundException {
        // Class 객체 생성하기
        Class<?> klass = Class.forName("kr.or.ddit.reflection.SampleVO");
        
        // 클래스에 선언된 모든 메소드의 메타데이터 정보 가져오기
        Method[] methodArr = klass.getDeclaredMethods();
        
        for(Method m : methodArr) {
            System.out.println("메소드 명 : " + m.getName());
            System.out.println("메소드 리턴타입 : " + m.getReturnType());
            
            // 해당 메소드의 접근제어자 정보 가져오기
            int modFlag = m.getModifiers();
            System.out.println("메소드 접근제어자 : " + Modifier.toString(modFlag));
            
            // 해당 메소드의 파라미터 타입 가져오기
            Class<?>[] paramArr = m.getParameterTypes();
            System.out.println("메소드 파라미터 타입 : ");
            for(Class<?> clazz : paramArr) {
                System.out.println(clazz.getName() + " | ");
            }
            System.out.println();
            
            // 해당 메소드에서 던지는 예외타입 가져오기
            Class<?>[] exTypeArr = m.getExceptionTypes();
            System.out.println("던지고 있는 예외 타입 : ");
            for(Class<?> clazz : exTypeArr) {
                System.out.println(clazz.getName() + " | ");                
            }
            System.out.println();
            
            // 해당 메소드에 존재하는 annotation 타입 정보 가져오기
            Annotation[] annos = m.getDeclaredAnnotations();
            System.out.println("Annotation 타입 : ");
            for(Annotation anno : annos) {
                System.out.println(anno.annotationType().getName() + " | ");
            }
            
            System.out.println();
            System.out.println("-------------------------------------------");
            
        }
    }
 
}
 
cs

'daily > 고급자바' 카테고리의 다른 글

[고급자바] Thread (2)  (0) 2023.02.07
[고급자바] Thread (1)  (0) 2023.02.06
[고급자바] 호텔 과제  (0) 2023.02.03
[고급자바] 로또 과제  (0) 2023.02.03
[고급자바] Enum  (0) 2023.02.03