ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Annotation,Reflection-22.03.29
    고급자바 2022. 3. 29. 16:53
    728x90

    Annotation

    주석, 즉 주석처럼 달아서 프로그램에 도움이 되도록

      주석처럼 달아서 의미제공하려고
      프로그램 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것.
      주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공한다.
      
      종류: 1.표준 애너테이션
             2.메타 에너테이션(애너테이션을 위한 애너테이션, 즉 애너테이션을 정의할 때 사용하는 애너 테이션)
          
          
     애너테이션 타입 정의하기
      @interface 애너테이션이름{
             요소타입  타입요소 이름(); 반환값이 있고 매개변수는 없는 추상메서드의 형태
             ...
     }
     
     애너테이션(어노테이션) 요소의 규칙
     1.요소의 타입은 기본형, String, enum, annotation, class 만 허용된다.
     2.() 안에 매개변수를 선언할 수 없다.
     3.예외를 선언할 수 없다.
     4. 요소의 타입에 타입 매개변수(제너릭타입 문자)를 사용할 수 없다.

    <1번 코드> 메타애너테이션

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    
    @Target(ElementType.METHOD)  // 적용 가능한 대상 지정, METHO에만 적용하겠다.
    @Retention(RetentionPolicy.RUNTIME) //애너테이션 유지기간 지정(CLASS가 기본값임. 컴파일 되고나서도 존재), CLASS,RUNTIME,SOURCE존재
    public @interface PrintAnnotation {
    	String value() default "-"; //기본값을 "-"로 지정
    	int count() default 20;     //기본값을 20으로 지정
    	
    }

     

    package kr.or.ddit.basic;
    
    //@PrintAnnotation target이 메서드 이므로 여기에 X
    public class Service {
    
    		@PrintAnnotation() // 디폴트 설정이므로 value="-", count="20"
    		public void method1() {
    			System.out.println("메서드1에서 출력되었습니다.");
    		}
    		@PrintAnnotation(value="%")
    		public void method2() {
    			System.out.println("메서드2에서 출력되었습니다.");
    		}
    		@PrintAnnotation(value="#",count=25)
    		public void method3() {
    			System.out.println("메서드3에서 출력되었습니다.");
    		}
    
    	
    
    }

    <Service에서 만들어놓은 Annotation의 정보를 가져오기 테스트>

    import java.lang.annotation.Annotation;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class AnnotationTest {
    	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
    		
    		//접근할 클래스로 만든 객체 생성
    		Service service=new Service();
    		//클래스 정보를 담음 클래스 객체 생성
    		Class<?> klass=service.getClass();
    		//리플렉션을 이용한 메서드 정보 접근하기 (2번째 방법 사용)
    		Method[] declaredMethods = klass.getDeclaredMethods();
    		
    		for(Method m: declaredMethods) {
    			System.out.print(m.getName()); //메서드명 출력
    			
    		    Annotation[] annos=m.getAnnotations();
    		    
    		    for(Annotation anno:annos) {
    		    	if(anno.annotationType().getSimpleName().equals("PrintAnnotation")) {
    		    		PrintAnnotation printAnn=(PrintAnnotation)anno;
    		    		for(int i=0; i<printAnn.count(); i++) {
    		    			System.out.print(printAnn.value());
    		    		}
    		    	}
    		    }
    		    System.out.println(); //줄바꿈 처리
    		    
    		    m.invoke(service); //invoke: 메소드를 실행해라
    		    
    		    
    		    /*3번째 방법 사용(new 키워드 안쓰기) -> m.invoke와 같은방법
    		    Class<?> clazz=Service.class;
    		    service=(Service)clazz.newInstance();
    		    m.invoke(service);*/
    		}
    
    	}
    }


    Reflection

    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 등. 

    <2번코드>

    Class 오브젝트(클래스 정보를 담고 있는 )를 생성하기

    * Class 오브젝트(클래스 정보를 담고 있는 )를 생성하기
     */
    public class T01_ClassObjectCreationTest {
        public static void main(String[] args) throws ClassNotFoundException {
        	//클래스 정보 가져오는 방법 3가지 ,클래스 타입의 객체로 받아서 넣겠다
    		첫 번째 방법: Class.forName()이용하기
      
        	Class<?> klass=Class.forName("kr.or.ddit.reflection.T01_ClassObjectCreationTest") ; //패키지이름경로.클래스 이름
        	
        	두 번째 방법: getClass() 메서드 이용하기, 인스턴스 메소드이기때문에 인스턴스를 만들어야 한다. 
        	T01_ClassObjectCreationTest obj=new T01_ClassObjectCreationTest();
        	klass=obj.getClass();
        	
        	세번째 방법: .class
        	klass=T01_ClassObjectCreationTest.class; 	
        	
    	}
        
    }

     Class의 메타 데이터 가져오기 예제

    import java.lang.reflect.Modifier;
    /**
     * Class의 메타 데이터 가져오기 예제
     */
    public class T02_ClassMetadataTest {
    	public static void main(String[] args) {
    	//클래스 오브젝트 생성하기 (3번째 방법으로 하게됨)
    		Class<?> clazz= SampleVO.class;
    		System.out.println("심플 클래스명: "+clazz.getSimpleName());
    		System.out.println("클래스명: "+clazz.getName());
    		System.out.println("상위 클래스명: "+clazz.getSuperclass().getName());
    		
    		//패키지 정보 가져오기
    		Package pkg=clazz.getPackage();
    		System.out.println("패키지 정보: "+pkg.getName());
    		
    		//해당 클래스에서 구현하고 있는 인터페이스 목록 가져오기
    		Class<?>[] interfaces=clazz.getInterfaces();
    		
    		System.out.print("인터페이스 목록:");
    		for(Class<?> inf: interfaces) {
    			System.out.println(inf.getName()+"|");
    		}
    		System.out.println();
    		
    		//클래스의 접근 제어자 가져오기(flag bit 값 반환됨. =>접근제어자의 유무 체크함)
    		int modFlag=clazz.getModifiers();
    		System.out.println("접근제어자: "+Modifier.toString(modFlag));	
    	}
    }

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

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    /**
     * 클래스에 선언된 메서드의 메타 정보 가져오기
     */
    public class T03_MethodMetadataTest {
    	public static void main(String[] args) throws ClassNotFoundException {
    	//클래스 오브젝트 가져오기(1번쨰 방법 사용)
    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.print("메서드 파라미터 타입 : ");
    			for(Class<?> clazz : paramArr) {
    				System.out.print(clazz.getName() + " | ");
    			}
    			System.out.println();
    			
    			// 해당 메서드에서 던지는 예외타입 가져오기
    			Class<?>[] exTypeArr = m.getExceptionTypes();
    			System.out.print("메서드에서 던지는 예외타입 목록 : ");
    			for(Class<?> clazz : exTypeArr) {
    				System.out.print(clazz.getName() + " | ");
    			}
    			System.out.println();
    			
    			// 해당 메서드에 존재하는 Annotation 타입 정보 가져오기
    			Annotation[] annos = m.getDeclaredAnnotations();
    			System.out.println("Annotation 타입 : ");
    			for(Annotation anno : annos) {
    				System.out.print(anno.annotationType().getName() + " | ");
    			}
    			
    			System.out.println();
    			System.out.println("---------------------------------------------");
    			
    		}
    	
    	}
    }

    VO객체 만들기

    import kr.or.ddit.basic.PrintAnnotation;
    
    public class SampleVO implements Comparable<SampleVO> {
    	
    public String id;
    protected String name;
    private int age;
    
    public SampleVO() throws RuntimeException {
    	
    }
    
    public SampleVO(String id, String name, int age) {
    	super();
    	this.id = id;
    	this.name = name;
    	this.age = age;
    }
    @PrintAnnotation(value="$",count=30)
    public String getId() throws RuntimeException {
    	return id;
    }
    
    public void setId(String id) {
    	this.id = id;
    }
    
    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 + "]";
    }
    
    @Override
    public int compareTo(SampleVO o) {
    	return name.compareTo(o.getName());
    }
    
    }

    static메소드(객체를 생성하지 않고 사용 가능,자주쓰는 기능들을 Util처럼 ) vs 인스턴스메소드

    728x90

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

    Thread 처리 시간-22.03.30  (0) 2022.03.30
    ThreadTest-22.03.29  (0) 2022.03.29
    가변형 인수,enum-22.03.29  (0) 2022.03.29
    WildCard2-22.03.29  (0) 2022.03.29
    WildCard-22.03.28  (0) 2022.03.28
Designed by Tistory.