본문 바로가기
Java

[Advanced JAVA] Jaca annotation and RTTI

by 루에 2014. 12. 25.
반응형

RTTI(Run-Time Type Information)

  • 자바 프로그램의 실행(런타임)중에 타입 정보를 알아낼 수 있으며 사용도 가능하다
  • 런타임 시 객체와 클래스의 정보를 알아내는 방법

첫번째는 전통적 RTTI로 컴파일 시점에 사용 가능한 모든 타입을 클래스에 내포

두번째는 리플렉션 매커니즘으로 런타임 시에 클래스의 정보만을 알고 사용할 수 있는 것

  • OOP의 다형성은 전통적 RTTI로 자바 컴파일 시 상속구조를 파악하여 동작하는 원리


c의 프로그램 실행 과정

a.c                            a.o

a가 b를 참조     +     link    ->    a.exe    ->    RAM으로 올리고, RAM에 올린 주소로 재배치한 뒤 파일 실행

b.c                            b.o


java의 프로그램 실행 과정

Java는 linking이 없고, jar를 이용해서 jar파일을 생성. a,b를 묶어 jar라는 파일로 합함

a.java    ->    a.class

+        a.jar    ->    JVM

b.java    ->    b.class

a를 실행하는 중에 b를 참조하게 되면 그 시점에 b를 로딩한 뒤 주소를 찾아온다



annotation 정의 및 사용

annotation 정의

@Target ({ElementType.TYPE, ElementType.METHOD})    // target과 retention 지정

@Retention (RetenthonPolicy.RUNTIME)

public @interface MyAnnotation{    // MyAnnotation이란 이름의 annotation 생성

int num();

String name();

String id();

String date() default "unsigned";    // 기본값을 지정할 수 있다

}


annotation 사용

@MyAnnotation(num=1,name='MainActivity",id="1")

public class MainActivity extends Activity{

@Override

@MyAnnotation(num=1,name="onCreate",id="2")

public void onCreate(Bundle savedInstanceState){

...

}

}



 Java Reflect

동적으로 이름(String)을 이용하여 Java class를 다루는 방법

class를 메모리에 불러와서 class의 객체 생성

class의 method나 field를 이름과 signature를 이용하여 획득한 다음, 함수 호출 또는 값의 설정 및 획득

signature : 동일 이름(오버로딩) 등을 구분하기 위한 성질


Class class

Java의 class파일을 나타내는 class로 Class.forName()(ex: Class.Java.lang. 등 풀네임)과 같은 함수를 이용하여 Class 회득

Class의 newInstance()함수를 이용해 객체 생성

생성자를 이용하여 생성하고자 할 때, getConstructor()를 이용해 생성자를 얻어온 다음 생성자의 newInstance()를 이용해 객체 생성

Class가 메모리에 로딩되어 있지 않으면 ClassLoader를 이용해 메모리에 Class를 로딩해야 한다


Method class

class에 정의된 함수를 나타내는 class로서 Class 객체의 getMethod()를 호출하여 획득

getDeclaredMethod()로 protected나 private method도 얻어올 수 있음

invoke()로 함수 호출


Field

class에 정의 된 field를 나타내는 class로서 Class객체의 getField()를 호출하여 획득

get(),set() 함수를 이용하여 값을 설정하거나 얻어올 수 있음


Class 획득

Class clazz = Class.forName("org.tacademybasic.MyClass");

Class clazz = ClassLoader.loadClass("org.....MyClass");

Class clazz = MyClass.class;    or    Class clazz = MyClassObject.getClass();


객체의 생성

Object obj = clazz.newInstance();

Constructor c = clazz.getConstructor(String.class, Integer.class);

Object obj = c.newInstance("test",1);


ClassLoader

Class를 메모리에 로딩하기 위해 사용하는 class로 class가 설치된 패키지의 위치로부터 클래스를 읽어온다

ClassLoader.getSystemClassLoader()로 안드로이드 시스템의 클래스로더를 획득

이미 로딩된 클래스의 경우 getClassLoader()로 클래스로더를 얻어올 수 있다


PathClassLoader myClassLoader = 

new dalvik.system.PathClassLoader(apkName, ClassLoader.getSystemClassLoader());

Class clazz = myClassLoader.loadClass(className);

Class clazz = Class.forName(className, true, myClassLoader);


Annotation

Class의 getAnnotation()으로 클래스에 정의된 어노테이션을 얻어올 수 있다


Method의 획득

Method method = clazz.getMethod("myMethod",String.class,interger.class);

Mythod method = clazz.getDeclaredMethod("myPrivateMethod",String.class,intsger.class);

Method[] methods[] = clazz.getMethods();


Method의 호출

method.invoke(myClassObject, "param1", 10);    // instance method의 호출

method.invoke(null, "param1", 10);    // static method의 호출


private method 호출

method.setAccessivle(true);

method.invoke(myClassObject, "param1", 10);


Method의 정보

getName() : 메소드 이름

getModifiers() : public, private, final, static 등의 정보

getParameterTypes() : paramter의 class[]

getReturnType() : return값의 class


Annotation 정보

getAnnotation()

getParameterAnnotation()


Field의 획득

Field field = clazz.getField("myField");

Field field = clazz.getDeclaredField("myPrivateField");

Field[] fields[] = clazz.getFields()l


Field값 획득 및 설정

Object value = field.get(myClassObject), field.set(myClassObject, valueObject);

Object value = field.get(null);, field.get(null, valueObject);    // static field의 경우

그 외 값 획득 및 설정 함수

getBoolean(), getChar(), .....;

setBoolean(), setDouble(), ....;


Field의 정보

getName() : 필드 이름

getModifiers() : public, static 등의 정보

getType() : field의 class

getGenericType() : field의 Class<T>, GenericArraType, 등


Annotation 정보

메소드와 동일



Proxy class

interface를 implements한 클래스나 객체를 동적으로 생성해 주기 위한 class

reflect를 이용할 때 reflect로 생성한 object에 등록할 interface를 implements한 객체를 동적으로 생성

static Object newProxyInstance(ClassLoader loader, Class[] Interfaces, InvocationHandler hander)


InvocationHandler

newProxyInstance로 생성한  Object의 interface함수가 호출되면 InvocationHandler의 invoke가 호출된다

Object invoke(Object proxy, Method method, Object[] args)

Inboke함수에서는 method의 이름을 얻어와서 해당 method에 대한 처리 후 결과를 return한다



Class annotation check

Class clazz = AnnotationTest.class;

if(clazz.isAnnotationPresent(CheckAnnotation.class)){

CheckAnnotation ann = (CheckAnnotation) clazz.getAnnotation(CheckAnnotation.class);

int num = ann.num();

}


Method annotation check

Class clazz = AnnotationTest.class;

for(Method m : clazz.getMethods()){

if(m.isAnnotationPresent(CheckAnnotation.class)){

...

}

}

반응형

댓글