-
어노테이션 (Annotation)프로그래밍/JAVA 자바 2021. 9. 9.반응형
package annoEx; import java.util.Date; public class Ex001_BuiltinAnnotation { public static void main(String[] args) { User user = new User(); System.out.println(user); //System.out.println(user.toString()); user.sub1(); user.sub2(); } } class User { @Override public String toString() { return "Builtin Annotation 예제"; } @Deprecated // 더 나은 메소드가 있음을 나타낼때 사용 public void sub1() { System.out.println("사용을 자제하세요"); } @SuppressWarnings("deprecation") public void sub2() { Date date = new Date(); int y = date.getYear() + 1900; System.out.println(y); } }
- 어노테이션은 @를 이용해서 자바한테 이게 어노테이션이라고 알림
- @override = 재정의 하겠다
- @Deprecated = 이거보다 더 나은 메소드가 있으니 사용 자제해라 라는 뜻 이걸 사용하면 메소드명에 줄이 그어진다.
- @SuppressWarnings = 자바에 노란 경고문을 없애준다. (코드에 문제가 없고, 그 경고를 충분히 인지한 상태에서만 사용)
사용자 정의 어노테이션
package annoEx; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class Ex002_Annotation { public static void main(String[] args) { // 사용자 정의 어노테이션 TestService obj = new TestService(); obj.execute(); } } // 커스텀 어노테이션 생성 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation { } class TestService { public void execute() { System.out.println("어노테이션 생성 예제"); } }
- 내가 만드는 어노테이션
- @interface로 만들어야함
- 그리고 @Target으로 어떤 애들을 타겟으로할지 정함
- @Retention = 어노테이션 값들을 언제까지 유지할 것인지 값을 입력함
(RUNTIME = 바이트 코드 파일까지 어노테이션 정보 유지, 리플렉션을 이용해서 런타임에 어노테이션 정보 얻을 수 있음)
package annoEx; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; public class Ex003_Annotation { public static void main(String[] args) { // TODO Auto-generated method stub PrintService obj = new PrintService(); obj.method2(); System.out.println(); // PrintService 클래스의 메소드 정보 얻어오기 Method[] mm = PrintService.class.getDeclaredMethods(); for(Method m : mm) { // 메소드에 어노테이션이 적용 되었는지 확인 if(m.isAnnotationPresent(PrintAnnotation.class)) { // PrintAnnotation 객체 얻어오기 PrintAnnotation pa = m.getAnnotation(PrintAnnotation.class); // 메소드 이름 출력 System.out.println("["+m.getName()+"]"); // 어노테이션 속성 값을 가져와서 이용하기 // System.out.println(pa.value()) + ", " + pa.number()); for(int i=0; i<pa.number(); i++) { System.out.print(pa.value()); } System.out.println(); // 메소드 호출 try { m.invoke(obj); } catch (Exception e) { // TODO: handle exception } System.out.println(); } } } } @Target({ElementType.METHOD}) // 어노테이션을 적용할 타겟이 1개 이상인 경우 배열로 설정 @Retention(RetentionPolicy.RUNTIME) @interface PrintAnnotation { String value() default "-"; int number() default 15; } class PrintService { @PrintAnnotation public void method1() { System.out.println("실행 내용 1"); } @PrintAnnotation("*") public void method2() { System.out.println("실행 내용 2"); } @PrintAnnotation(value = "#", number = 20) public void method3() { System.out.println("실행 내용 3"); } public void method4() { System.out.println("어노테이션이 없는 경우"); } }
-@Target에서 대상 적용할때 1개이상이면 배열로 해줘야 한다.
- PrintService 클래스의 메소드에 내가 만든 어노테이션 설정이 있는지 확인하고 => @PrintAnnotation 붙인 이유
- 각 메소드에 설정된 어노테이션에 삽입된 값에 따라 특정 값을 일정한 숫자만큼 출력함.
- () = 디폴트값을 따라감 - 을 15번 출력
- ("*") value만 바뀌고 넘버는 그대로 *을 15번 출력
- (value = "#", number = 20) 다 바뀜 #을 20번 출력
package annoEx; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Field; public class Ex004_Annotation { public static void main(String[] args) { try { MyContainer obj = new MyContainer(); /* String s = "annoEx.UserVO"; Class<?> cls = Class.forName(s); UserVO vo = obj.get(cls); */ UserVO vo = obj.get(UserVO.class); System.out.println(vo.getSubject()); // 스프링 System.out.println(vo.getDefaultValue()); // 자바 System.out.println(vo.getPrice()); // null } catch (Exception e) { e.printStackTrace(); } } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface MyData{ // 속성 public String value() default "자바"; } class UserVO { @MyData("스프링") private String subject; @MyData private String defaultValue; @MyData private Integer price; public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getDefaultValue() { return defaultValue; } public void setDefaultValue(String defaultValue) { this.defaultValue = defaultValue; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } } class MyContainer { private <T> T invokeAnnotations(T t) throws IllegalAccessException { Field[] ff = t.getClass().getDeclaredFields(); try { for(Field f : ff) { MyData md = f.getAnnotation(MyData.class); if(md != null && f.getType() == String.class) { f.setAccessible(true); // 리플렉트돤 private 필드나 메소드를 호출가능하도록 설정 f.set(t, md.value()); } } } catch (IllegalAccessException e) { throw e; } return t; } @SuppressWarnings("unchecked") public <T> T get(Class<?> cls) throws Exception { T t = null; try { // 객체 생성하기 Constructor<?> con = cls.getDeclaredConstructor(); t = (T) con.newInstance(); t = invokeAnnotations(t); } catch (Exception e) { throw e; } return t; } }
반응형'프로그래밍 > JAVA 자바' 카테고리의 다른 글
람다식(2) / 메소드 참조 (0) 2021.09.10 자바 람다식(1) 개념 (0) 2021.09.10 자바 네트워크(3) / 숫자 야구 게임 (0) 2021.09.09 자바 네트워크(1) URL, 소켓 ,TCP/IP (0) 2021.09.07 자바 UI swing / 버튼 추가 해보기 JFrame (0) 2021.09.07