yapp a.a study 2 reflection+annotation

68
Reflection + Annotation 2013. 7. 23 이준영 13723화요일

Upload: -

Post on 31-May-2015

502 views

Category:

Technology


12 download

DESCRIPTION

Java Reflection, Annotation 이해 및 활용

TRANSCRIPT

Page 1: Yapp a.a study 2 reflection+annotation

Reflection+ Annotation

2013. 7. 23이준영

13년 7월 23일 화요일

Page 2: Yapp a.a study 2 reflection+annotation

Class?

• 클래스를 구성하는 것들

• Fields,

• Methods,

• Constructors

13년 7월 23일 화요일

Page 3: Yapp a.a study 2 reflection+annotation

Class detailsField

Constructor

Method

13년 7월 23일 화요일

Page 4: Yapp a.a study 2 reflection+annotation

이클립스는어떻게

Contents Assist(Ctrl + Space)를지원할까?

13년 7월 23일 화요일

Page 5: Yapp a.a study 2 reflection+annotation

이클립스는클래스가 어떻게 생겨먹었는지 알고 있다.

13년 7월 23일 화요일

Page 6: Yapp a.a study 2 reflection+annotation

Class 클래스• 어떤 클래스의 모양(구성)을 알고 있는 클래스

• Fields,

• Methods,

• Constructors

• 상속 받은 것,정의한 것,인터페이스 등

13년 7월 23일 화요일

Page 7: Yapp a.a study 2 reflection+annotation

예제 자바 프로젝트 생성

13년 7월 23일 화요일

Page 8: Yapp a.a study 2 reflection+annotation

Class 클래스로 클래스 살펴보기

• 파헤쳐볼 WishItem 클래스 작성

13년 7월 23일 화요일

Page 9: Yapp a.a study 2 reflection+annotation

Class 클래스로 클래스 살펴보기

• 파헤쳐볼 WishItem 클래스 작성

13년 7월 23일 화요일

Page 10: Yapp a.a study 2 reflection+annotation

Class 클래스로 클래스 살펴보기

• 파헤쳐볼 WishItem 클래스 작성

public class WishItem implements Serializable{ private int id; private String name; private String createdTime; public WishItem(String name, String createdTime) { this(-1, name, createdTime); } public WishItem(int id, String name, String createdTime) { this.id = id; this.name = name; this.createdTime = createdTime; } public int getId() { return id; }

public void setId(int id) { this.id = id; }

public String getName() { return name; }

public void setName(String name) { this.name = name; }

public String getCreatedTime() { return createdTime; }

public void setCreatedTime(String createdTime) { this.createdTime = createdTime; }}

13년 7월 23일 화요일

Page 11: Yapp a.a study 2 reflection+annotation

Class 클래스로 클래스 살펴보기

• 파헤쳐볼 WishItem 클래스 작성

public class WishItem implements Serializable{ private int id; private String name; private String createdTime; public WishItem(String name, String createdTime) { this(-1, name, createdTime); } public WishItem(int id, String name, String createdTime) { this.id = id; this.name = name; this.createdTime = createdTime; } public int getId() { return id; }

public void setId(int id) { this.id = id; }

public String getName() { return name; }

public void setName(String name) { this.name = name; }

public String getCreatedTime() { return createdTime; }

public void setCreatedTime(String createdTime) { this.createdTime = createdTime; }}

13년 7월 23일 화요일

Page 12: Yapp a.a study 2 reflection+annotation

우린 왜 IDE를 쓸까?잠깐, 다른 이야기

13년 7월 23일 화요일

Page 13: Yapp a.a study 2 reflection+annotation

우린 왜 IDE를 쓸까?좀 더 편하고 빠르게 개발하기 위해서

잠깐, 다른 이야기

13년 7월 23일 화요일

Page 14: Yapp a.a study 2 reflection+annotation

Eclipse의 소스 생성 기능

13년 7월 23일 화요일

Page 15: Yapp a.a study 2 reflection+annotation

WishItem 클래스 정보 읽어보기

• Main 메서드 작성main 쓰고 Ctrl + Space bar

• 클래스의 Class 클래스 인스턴스를 가져오기Class<WishItem> clazz = WishItem.class

Class<? extends WishItem> clazz = obj.getClass()

13년 7월 23일 화요일

Page 16: Yapp a.a study 2 reflection+annotation

.class vs .getClass()

• .class는 타입 그대로의 클래스를 가져옴

• .getClass()는 인스턴스의 실제 타입의 클래스를 가져옴

Animal

Dog

상속

Animal a = new Animal();Animal d = new Dog();

d 의 클래스 정보를 얻기 위해서는Animal.class가 맞을까, d.getClass()가 맞을까?

13년 7월 23일 화요일

Page 17: Yapp a.a study 2 reflection+annotation

clazz.

• getDeclaredField(String name) - Field

• getDeclaredFields() - Fields[]

• getDeclaredMethod(String name) - Method

• getDeclaredMethods() - Method[]

• getDeclaredConstructor(Class<?>...paramTypes)

• getDeclaredConstructors() - Constructor

13년 7월 23일 화요일

Page 18: Yapp a.a study 2 reflection+annotation

clazz. ...

13년 7월 23일 화요일

Page 19: Yapp a.a study 2 reflection+annotation

clazz. ...

13년 7월 23일 화요일

Page 20: Yapp a.a study 2 reflection+annotation

clazz. ...

공부 많이 해야겠죠?그렇다고 외우진 마세요.

그런게 있었다는 것만 기억!

13년 7월 23일 화요일

Page 21: Yapp a.a study 2 reflection+annotation

하나씩 해 봅시다.

• Field 가져오기 WishItem wi = new WishItem(0, "2013.7.23", "세상의 모든 지식"); Class<? extends WishItem> clazz = wi.getClass(); try { Field idField = clazz.getDeclaredField("id"); // 필드의 이름 출력 System.out.println(idField.getName()); } catch (NoSuchFieldException e) { // 찾는 이름의 필드가 없을 때 e.printStackTrace(); } catch (SecurityException e) { // 접근 제한 발생할 때 e.printStackTrace(); }

13년 7월 23일 화요일

Page 22: Yapp a.a study 2 reflection+annotation

• Field의 값 보기, 바꾸기 try { Field idField = clazz.getDeclaredField("id"); // 필드의 이름 출력 System.out.println(idField.getName()); // 접근이 가능하도록 설정 idField.setAccessible(true); // 필드 값 가져오기 System.out.println(idField.get(wi)); // idField의 값을 15로 변경 idField.set(wi, 15); // WishItem 객체에 실제로 바뀌었는지 확인 System.out.println(wi.id); // 다시 접근이 불가능하도록 설정 idField.setAccessible(false);

...

13년 7월 23일 화요일

Page 23: Yapp a.a study 2 reflection+annotation

• Field의 값 보기, 바꾸기 try { Field idField = clazz.getDeclaredField("id"); // 필드의 이름 출력 System.out.println(idField.getName()); // 접근이 가능하도록 설정 idField.setAccessible(true); // 필드 값 가져오기 System.out.println(idField.get(wi)); // idField의 값을 15로 변경 idField.set(wi, 15); // WishItem 객체에 실제로 바뀌었는지 확인 System.out.println(wi.id); // 다시 접근이 불가능하도록 설정 idField.setAccessible(false);

...

13년 7월 23일 화요일

Page 24: Yapp a.a study 2 reflection+annotation

• Field의 값 보기, 바꾸기 try { Field idField = clazz.getDeclaredField("id"); // 필드의 이름 출력 System.out.println(idField.getName()); // 접근이 가능하도록 설정 idField.setAccessible(true); // 필드 값 가져오기 System.out.println(idField.get(wi)); // idField의 값을 15로 변경 idField.set(wi, 15); // WishItem 객체에 실제로 바뀌었는지 확인 System.out.println(wi.id); // 다시 접근이 불가능하도록 설정 idField.setAccessible(false);

...

13년 7월 23일 화요일

Page 25: Yapp a.a study 2 reflection+annotation

• 모든 Field 가져오기

Field[] fields = clazz.getDeclaredFields(); for(Field field : fields) { System.out.println(field.getName()); }

Field의 배열 형태로 반환

13년 7월 23일 화요일

Page 26: Yapp a.a study 2 reflection+annotation

• 특정 Method 가져오기getName 메서드 살짝 수정 public String getName() { System.out.println("위시 아이템 이름은 " + name); return name; }

try { // 특정 Method 가져오기 Method getNameMethod = clazz.getDeclaredMethod("getName"); // 메서드의 이름 확인 System.out.println(getNameMethod.getName()); } catch (NoSuchMethodException e) { // 그런 메서드가 없음! e.printStackTrace(); } catch (SecurityException e) { // 시큐리티! 시큐리티! e.printStackTrace(); }}

13년 7월 23일 화요일

Page 27: Yapp a.a study 2 reflection+annotation

• 메서드 실행하기

• 실행 결과

// 메서드 실행하기 String name = (String)getNameMethod.invoke(wi); // 가져온 값 확인 System.out.println("가져온 값 : " + name);

위시 아이템 이름은 세상의 모든 지식가져온 값 : 세상의 모든 지식

13년 7월 23일 화요일

Page 28: Yapp a.a study 2 reflection+annotation

Q : 모든 메서드를 가져와서 이름 출력해 보기

13년 7월 23일 화요일

Page 29: Yapp a.a study 2 reflection+annotation

• Class 클래스를 이용해 인스턴스 만들기

try { WishItem item = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }

13년 7월 23일 화요일

Page 30: Yapp a.a study 2 reflection+annotation

• Class 클래스를 이용해 인스턴스 만들기

try { WishItem item = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }

newInstance 메서드는 해당 클래스가 매개변수가 없는기본 생성자를 가지고 있어야 사용 가능

13년 7월 23일 화요일

Page 31: Yapp a.a study 2 reflection+annotation

기본 생성자를 만들거나

혹은

Constructor를 이용

13년 7월 23일 화요일

Page 32: Yapp a.a study 2 reflection+annotation

• Constructor를 이용해서 인스턴스 만들기try { // 생성자 가져오기 Constructor cons = clazz.getDeclaredConstructor(int.class, String.class, String.class); // 생성자를 통해서 인스턴스 생성 WishItem item = (WishItem) cons.newInstance(4, "2013. 7. 23", "갤럭시 S4"); // 실제로 잘 생성되었는지 값 확인 System.out.println(item.getName());} catch (Exception e) { } // 예외는 길이 상 생략..

13년 7월 23일 화요일

Page 33: Yapp a.a study 2 reflection+annotation

Reflection?

• 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법

• 타입은 알고 있지만 형변환을 할 수 없는 상태에서 메서드를 호출

13년 7월 23일 화요일

Page 34: Yapp a.a study 2 reflection+annotation

Reflection?

• 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법

• 타입은 알고 있지만 형변환을 할 수 없는 상태에서 메서드를 호출

앞에서 살펴본 Class 클래스 가지고 놀기

13년 7월 23일 화요일

Page 35: Yapp a.a study 2 reflection+annotation

Annotation

• 사전적 정의 : 주석

• Meta Data : 데이터에 대한 데이터

• 어노테이션은 @으로 표현

13년 7월 23일 화요일

Page 36: Yapp a.a study 2 reflection+annotation

Annotation

• 사전적 정의 : 주석

• Meta Data : 데이터에 대한 데이터

• 어노테이션은 @으로 표현@Override@Deprecated@SuppressWarnings

최소한 @Override는 본적 있죠?

13년 7월 23일 화요일

Page 37: Yapp a.a study 2 reflection+annotation

일단 만들어 봅시다.

• File >> New

13년 7월 23일 화요일

Page 38: Yapp a.a study 2 reflection+annotation

• 그럼 이런 파일이 생성

• WishItem 클래스의 name 필드에 붙여보기

public @interface FirstAnno {

}

@FirstAnnoprivate String name;

짠!

13년 7월 23일 화요일

Page 39: Yapp a.a study 2 reflection+annotation

• Annotation에 값 담기

• WishItem으로 돌아가보면..

• 그릇이 생겼으니 담아줘야.

public @interface FirstAnno { public int value();}

@FirstAnnoprivate String name;

@FirstAnno(27)private String name;

13년 7월 23일 화요일

Page 40: Yapp a.a study 2 reflection+annotation

• 또 다른 값 담아보기

• 다시 WishItem 클래스로..

public @interface FirstAnno { public int value(); public String weekday();}

@FirstAnno(value=27, weekday="화요일")private String name;

13년 7월 23일 화요일

Page 41: Yapp a.a study 2 reflection+annotation

처음에는 value 라고 적어주지 않았었는데..?@FirstAnno(27)private String name;

13년 7월 23일 화요일

Page 42: Yapp a.a study 2 reflection+annotation

value는 어노테이션의 기본값을 담는 이름>> 이름 없이도 값을 담는 어노테이션 변수

13년 7월 23일 화요일

Page 43: Yapp a.a study 2 reflection+annotation

• 어노테이션 변수에 기본값 지정public @interface FirstAnno { public int value() default 0; public String weekday();}

@FirstAnno(weekday="화요일")private String name;

13년 7월 23일 화요일

Page 44: Yapp a.a study 2 reflection+annotation

어노테이션의 어노테이션

13년 7월 23일 화요일

Page 45: Yapp a.a study 2 reflection+annotation

• 이건 또 무슨 Class의 클래스 같은 소리?

어노테이션의 어노테이션

13년 7월 23일 화요일

Page 46: Yapp a.a study 2 reflection+annotation

• 이건 또 무슨 Class의 클래스 같은 소리?

• 어노테이션 인터페이스 정의에 붙이는어노테이션을 말함

어노테이션의 어노테이션

13년 7월 23일 화요일

Page 47: Yapp a.a study 2 reflection+annotation

• 이건 또 무슨 Class의 클래스 같은 소리?

• 어노테이션 인터페이스 정의에 붙이는어노테이션을 말함

• Meta 어노테이션이라고 함

어노테이션의 어노테이션

13년 7월 23일 화요일

Page 48: Yapp a.a study 2 reflection+annotation

• 이건 또 무슨 Class의 클래스 같은 소리?

• 어노테이션 인터페이스 정의에 붙이는어노테이션을 말함

• Meta 어노테이션이라고 함

• @Target,@Retention,@Documented,@Inherited 하나씩 알아봅시다.

어노테이션의 어노테이션

13년 7월 23일 화요일

Page 49: Yapp a.a study 2 reflection+annotation

@Target

• 어노테이션이 적용될 타입을 지정@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE})public @interface FirstAnno { public int value() default 0; public String weekday();}

13년 7월 23일 화요일

Page 50: Yapp a.a study 2 reflection+annotation

• ElementType.TYPE: 클래스에 적용하는 어노테이션으로 설정

• ElementType.METHOD: 메서드에 적용하는 어노테이션으로 설정

• ElementType.CONSTRUCTOR:생성자에 적용하는 어노테이션으로 설정

• ElementType.ANNOTATION_TYPE:어노테이션에 적용하는 어노테이션으로 설정

13년 7월 23일 화요일

Page 51: Yapp a.a study 2 reflection+annotation

• ElementType.FIELD: 필드에 적용하는 어노테이션으로 설정

• ElementType.PARAMETER: 매개변수에 적용하는 어노테이션으로 설정

• ElementType.LOCAL_VARIABLE:지역변수에 적용하는 어노테이션으로 설정

• ElementType.PACKAGE:패키지에 적용하는 어노테이션으로 설정

13년 7월 23일 화요일

Page 52: Yapp a.a study 2 reflection+annotation

• 필드에만 적용할 어노테이션으로 지정@Target(ElementType.FIELD)public @interface FirstAnno { public int value() default 0; public String weekday();}

13년 7월 23일 화요일

Page 53: Yapp a.a study 2 reflection+annotation

• 어노테이션이 언제까지 유효할 지 설정

• @Retention(RetentionPolicy. ?)

@Retention

Source Code

Compile Runtime

13년 7월 23일 화요일

Page 54: Yapp a.a study 2 reflection+annotation

• RetentionPolicy.SOURCE: 소스코드 상에서만 유효함

• RetentionPolicy.COMPILE: 컴파일 단계까지 유효함

• RetentionPolicy.RUNTIME:프로그램이 실행 중(런타임)일 때도 유효함

13년 7월 23일 화요일

Page 55: Yapp a.a study 2 reflection+annotation

• JavaDoc으로 출력 시 어노테이션 정보를 출력할 것인지를 설정

• @Documented가 적용되어있는 어노테이션은 Java Doc에서도 표현됨

• 없으면 해당 어노테이션은 표현되지 않음

@Documented

13년 7월 23일 화요일

Page 56: Yapp a.a study 2 reflection+annotation

@Inherited

• 하위(자식) 클래스에서 어노테이션을 유지할 것인지를 결정

• @Inherited가 적용되어 있는 경우 하위 클래스에서도 동일하게 어노테이션이 적용됨

• @Retention(RetentionPolicy.RUNTIME)이 함께 적용되어야 의미가 있음

13년 7월 23일 화요일

Page 57: Yapp a.a study 2 reflection+annotation

안드로이드 스터디 하다가

왜?

Reflection과 Annotation을?

13년 7월 23일 화요일

Page 58: Yapp a.a study 2 reflection+annotation

btnAdd = (Button)findViewById(R.id.wl_btnAddWishItem);etItemName = (EditText)findViewById(R.id.wl_etWishItemName);lvItems = (ListView)findViewById(R.id.wl_lvItems);

@ViewByIdprivate Button btnAdd;

@ViewByIdprivate EditText etItemName;

@ViewByIdprivate ListView lvItems;

13년 7월 23일 화요일

Page 59: Yapp a.a study 2 reflection+annotation

룰을 정하자

• @ViewById 에 값을 넘겨주지 않으면필드의 이름을 ID로 간주하자

• @ViewById(R.id.xxx) 처럼ID를 직접 넘겨줄 수 있다.

• So Simple!그렇지만 구현은.. @(#@*!&%

13년 7월 23일 화요일

Page 60: Yapp a.a study 2 reflection+annotation

@ViewById 구현

13년 7월 23일 화요일

Page 61: Yapp a.a study 2 reflection+annotation

package yapp.aa.annotation;

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;

/** * View 클래스의 findViewById 메서드를 대체하기 위한 어노테이션 <p> * * case 1.value 값을 전달받는 경우 그 값을 ID로 사용 </br> * case 2.value 값을 전달받지 않는 경우 어노테이션이 적용된 필드의 이름을 ID로 사용</br> * @author 이준영 * */@Target(ElementType.FIELD) // 멤버 변수(필드)에만 적용하도록 함@Retention(RetentionPolicy.RUNTIME) // 런타임에 유효하도록 함public @interface ViewById { /** * 뷰의 ID 저장 * @return 뷰의 ID */ public int value() default -1;}

13년 7월 23일 화요일

Page 62: Yapp a.a study 2 reflection+annotation

package yapp.aa.annotation;

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ViewById { public int value() default -1;}

주석 빼면? 사실 몇 줄 안되는 어노테이션

13년 7월 23일 화요일

Page 63: Yapp a.a study 2 reflection+annotation

ViewByIdResolver Class

리플렉션을 통해 Activity의 필드 중@ViewById 어노테이션이 적용된 필드에

뷰를 찾아 설정해주는 역할을 수행

13년 7월 23일 화요일

Page 64: Yapp a.a study 2 reflection+annotation

어떻게 해야할까?

• Reflection을 통해 액티비티의 필드를 가져옴getDeclaredFields()

• 가져온 필드에 적용된 어노테이션을 가져옴getAnnotation(ViewById.class)

• 어노테이션이 적용되었다면 값을 가져옴null인 경우는 어노테이션이 적용되지 않은 필드

• value가 -1인지, 지정된 값인지에 따른 처리

• 액티비티에서 뷰를 찾아서 필드에 값을 설정

13년 7월 23일 화요일

Page 65: Yapp a.a study 2 reflection+annotation

이런 모양으로 시작해봅시다public class ViewByIdResolver{ public static void resolve(Activity activity) { }}

13년 7월 23일 화요일

Page 66: Yapp a.a study 2 reflection+annotation

ㄱㄱ

13년 7월 23일 화요일

Page 67: Yapp a.a study 2 reflection+annotation

더 많은 것들을 할 수 있지 않을까?

13년 7월 23일 화요일

Page 68: Yapp a.a study 2 reflection+annotation

findViewById 말고?

• setOnClickListener?

• 여기서 숙제 @Click 만들어보기(사실 검색해도 나오긴 합니다 :D )

• 요점은 고민해보기

13년 7월 23일 화요일