15. WishItem 클래스 정보 읽어보기
• Main 메서드 작성
main 쓰고 Ctrl + Space bar
• 클래스의 Class 클래스 인스턴스를 가져오기
Class<WishItem> clazz = WishItem.class
Class<? extends WishItem> clazz =
obj.getClass()
13년 7월 23일 화요일
16. .class vs .getClass()
• .class는 타입 그대로의 클래스를 가져옴
• .getClass()는 인스턴스의 실제 타입의 클래스
를 가져옴
Animal
Dog
상속
Animal a = new Animal();
Animal d = new Dog();
d 의 클래스 정보를 얻기 위해서는
Animal.class가 맞을까, d.getClass()가 맞을까?
13년 7월 23일 화요일
20. clazz. ...
공부 많이 해야겠죠?
그렇다고 외우진 마세요.
그런게 있었다는 것만 기억!
13년 7월 23일 화요일
21. 하나씩 해 봅시다.
• 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일 화요일
22. • 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일 화요일
23. • 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일 화요일
24. • 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일 화요일
25. • 모든 Field 가져오기
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
System.out.println(field.getName());
}
Field의 배열 형태로 반환
13년 7월 23일 화요일
26. • 특정 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일 화요일
27. • 메서드 실행하기
• 실행 결과
// 메서드 실행하기
String name = (String)getNameMethod.invoke(wi);
// 가져온 값 확인
System.out.println("가져온 값 : " + name);
위시 아이템 이름은 세상의 모든 지식
가져온 값 : 세상의 모든 지식
13년 7월 23일 화요일
29. • Class 클래스를 이용해 인스턴스 만들기
try {
WishItem item = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
13년 7월 23일 화요일
30. • Class 클래스를 이용해 인스턴스 만들기
try {
WishItem item = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
newInstance 메서드는 해당 클래스가 매개변수가 없는
기본 생성자를 가지고 있어야 사용 가능
13년 7월 23일 화요일
32. • 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일 화요일
33. Reflection?
• 객체를 통해 클래스의 정보를 분석해 내는 프
로그램 기법
• 타입은 알고 있지만 형변환을 할 수 없는 상태
에서 메서드를 호출
13년 7월 23일 화요일
34. Reflection?
• 객체를 통해 클래스의 정보를 분석해 내는 프
로그램 기법
• 타입은 알고 있지만 형변환을 할 수 없는 상태
에서 메서드를 호출
앞에서 살펴본 Class 클래스 가지고 놀기
13년 7월 23일 화요일
35. Annotation
• 사전적 정의 : 주석
• Meta Data : 데이터에 대한 데이터
• 어노테이션은 @으로 표현
13년 7월 23일 화요일
36. Annotation
• 사전적 정의 : 주석
• Meta Data : 데이터에 대한 데이터
• 어노테이션은 @으로 표현
@Override
@Deprecated
@SuppressWarnings
최소한 @Override는 본적 있죠?
13년 7월 23일 화요일
38. • 그럼 이런 파일이 생성
• WishItem 클래스의 name 필드에 붙여보기
public @interface FirstAnno {
}
@FirstAnno
private String name;
짠!
13년 7월 23일 화요일
39. • Annotation에 값 담기
• WishItem으로 돌아가보면..
• 그릇이 생겼으니 담아줘야.
public @interface FirstAnno {
public int value();
}
@FirstAnno
private String name;
@FirstAnno(27)
private String name;
13년 7월 23일 화요일
40. • 또 다른 값 담아보기
• 다시 WishItem 클래스로..
public @interface FirstAnno {
public int value();
public String weekday();
}
@FirstAnno(value=27, weekday="화요일")
private String name;
13년 7월 23일 화요일
41. 처음에는 value 라고 적어주지 않았었는데..?
@FirstAnno(27)
private String name;
13년 7월 23일 화요일
43. • 어노테이션 변수에 기본값 지정
public @interface FirstAnno {
public int value() default 0;
public String weekday();
}
@FirstAnno(weekday="화요일")
private String name;
13년 7월 23일 화요일
45. • 이건 또 무슨 Class의 클래스 같은 소리?
어노테이션의 어노테이션
13년 7월 23일 화요일
46. • 이건 또 무슨 Class의 클래스 같은 소리?
• 어노테이션 인터페이스 정의에 붙이는
어노테이션을 말함
어노테이션의 어노테이션
13년 7월 23일 화요일
47. • 이건 또 무슨 Class의 클래스 같은 소리?
• 어노테이션 인터페이스 정의에 붙이는
어노테이션을 말함
• Meta 어노테이션이라고 함
어노테이션의 어노테이션
13년 7월 23일 화요일
48. • 이건 또 무슨 Class의 클래스 같은 소리?
• 어노테이션 인터페이스 정의에 붙이는
어노테이션을 말함
• Meta 어노테이션이라고 함
• @Target,
@Retention,
@Documented,
@Inherited 하나씩 알아봅시다.
어노테이션의 어노테이션
13년 7월 23일 화요일
49. @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일 화요일
50. • ElementType.TYPE
: 클래스에 적용하는 어노테이션으로 설정
• ElementType.METHOD
: 메서드에 적용하는 어노테이션으로 설정
• ElementType.CONSTRUCTOR
:생성자에 적용하는 어노테이션으로 설정
• ElementType.ANNOTATION_TYPE
:어노테이션에 적용하는 어노테이션으로 설정
13년 7월 23일 화요일
51. • ElementType.FIELD
: 필드에 적용하는 어노테이션으로 설정
• ElementType.PARAMETER
: 매개변수에 적용하는 어노테이션으로 설정
• ElementType.LOCAL_VARIABLE
:지역변수에 적용하는 어노테이션으로 설정
• ElementType.PACKAGE
:패키지에 적용하는 어노테이션으로 설정
13년 7월 23일 화요일
52. • 필드에만 적용할 어노테이션으로 지정
@Target(ElementType.FIELD)
public @interface FirstAnno {
public int value() default 0;
public String weekday();
}
13년 7월 23일 화요일
53. • 어노테이션이 언제까지 유효할 지 설정
• @Retention(RetentionPolicy. ?)
@Retention
Source
Code
Compile Runtime
13년 7월 23일 화요일
54. • RetentionPolicy.SOURCE
: 소스코드 상에서만 유효함
• RetentionPolicy.COMPILE
: 컴파일 단계까지 유효함
• RetentionPolicy.RUNTIME
:프로그램이 실행 중(런타임)일 때도 유효함
13년 7월 23일 화요일
55. • JavaDoc으로 출력 시 어노테이션 정보를 출력
할 것인지를 설정
• @Documented가 적용되어있는 어노테이션
은 Java Doc에서도 표현됨
• 없으면 해당 어노테이션은 표현되지 않음
@Documented
13년 7월 23일 화요일
56. @Inherited
• 하위(자식) 클래스에서 어노테이션을 유지할
것인지를 결정
• @Inherited가 적용되어 있는 경우 하위 클래
스에서도 동일하게 어노테이션이 적용됨
• @Retention(RetentionPolicy.RUNTIME)이
함께 적용되어야 의미가 있음
13년 7월 23일 화요일
61. 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일 화요일
62. 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일 화요일
64. 어떻게 해야할까?
• Reflection을 통해 액티비티의 필드를 가져옴
getDeclaredFields()
• 가져온 필드에 적용된 어노테이션을 가져옴
getAnnotation(ViewById.class)
• 어노테이션이 적용되었다면 값을 가져옴
null인 경우는 어노테이션이 적용되지 않은 필드
• value가 -1인지, 지정된 값인지에 따른 처리
• 액티비티에서 뷰를 찾아서 필드에 값을 설정
13년 7월 23일 화요일
65. 이런 모양으로 시작해봅시다
public class ViewByIdResolver{
public static void resolve(Activity activity) {
}
}
13년 7월 23일 화요일