Java Reflection의 정의
리플렉션이란 객체를 통해 클래스의 정보를 분석해내는 프로그램 기법을 말한다.
자바는 스크립트 언어가 아니라 컴파일언어이다.
물론 .java->.class-> 실행이라는 2단계의 매커니즘을 가지고 있다. 그러나 컴파일 언어로 분리하는게 옳다. 원래 자바에서는 동적으로 객체를 생성하는 기술이 없었다.
그리고 동적으로 인스턴스를 생성하는 Reflection으로 그 역할을 대신하게 된다.
*리플렉션이란 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법을 말한다.
자바는 스크립트 언어가 아니라 컴파일언어이다.
물론 .java->.class-> 실행이라는 2단계의 매커니즘을 가지고 있다. 그러나 컴파일 언어로 분리하는게 옳다. 원래 자바에서는 동적으로 객체를 생성하는 기술이 없었다.
그리고 동적으로 인스턴스를 생성하는 Reflection으로 그 역할을 대신하게 된다.
*리플렉션이란 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법을 말한다.
가정을 해 보자. 만약 객체의 메모리만을 알고 있고, 그리고 객체의 형에 대해서는 모른다고 생각하보자,
리플렉션으로 형은 알고 있지만 형변환을 할 수 없는 상태에서 객체의 메서드를 호출할 수 있다.
Class c = Data.class;
//Class c = Class.forName("클래스이름");
Method[] m = c.getMethods();
Field[] f = c.getFields();
Constructor[] cs = c.getConstructors();
Class[] inter = c.getInterfaces();
Class superClass = c.getSuperclass();
<Java Reflection의 사용>
Reflection은 자바의 특징이다. 실행중인 자바 프로그램 내부를 검사하고 내부의 속성을 수정할 수 있도록 한다. 예를들어, 어떤 자바 클래스가 가진 모든 멤버의 이름을 얻거나 보여줄 수 있다.
자바에서 클래스가 그 자신을 조사하고 수정하는 것이 많다고 할 수는 없으나 다른 언어에서는 볼 수 없는 특징이다.
reflection이 구체적인 쓰임중에 하나가 빌더툴을 이용해서 소프트웨어 컴포넌트를 만드는 곳에서 이다. 툴은 reflection을 사용해서 동적으로 로딩되는 자바 컴포넌트(클래스)의 속성을 얻을 수 있다.
예제)
import java.lang.reflect.Method
public class DumpMethods{
public static void main(String args[]){
try{
Class c=Class.forName(args[0]);
Method m[]=c.getDeclaredMethods();
for(int i=0;i<m.length;i++){
System.out.println(m[i].toString());
}catch(Throwable e){
System.err.pritln(e);
}
}
}
명령
java DumpMethods java.util.Stack
실행 결과
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
이 프로그램은 java.util.Stack 의 속성과 반환값에 따라 메소드리스트를 출력한다.
이 프로그램은 Class.forName 을 통해서 클래스를 로딩하고 getDeclaredMethods 을 통해서 클래스에서 정의한 메소드리스트를 얻는다. java.lang.reflect.Method 는 단일 메쏘드를 나타내는 클래스이다.
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
이 프로그램은 java.util.Stack 의 속성과 반환값에 따라 메소드리스트를 출력한다.
이 프로그램은 Class.forName 을 통해서 클래스를 로딩하고 getDeclaredMethods 을 통해서 클래스에서 정의한 메소드리스트를 얻는다. java.lang.reflect.Method 는 단일 메쏘드를 나타내는 클래스이다.
<Reflection을 사용한 Set up>
Method와 같은 reflection class는 java.lang.reflect에 있다. 이 클래스를 사용하기 위해서는 세 가지 스텝을 밟아야 한다.
첫 번째는 수정하기를 원하는 클래스의 java.lang.Class 객체를 얻어야 한ㄷ. java.lang.Class는 클래스를 표현하고, 실행중인 자바 프로그램과 인터페이스 한다.
*자바 기본형에 대한 클래스 정보를 얻는 방법
1. Class c=Class.forName("java.lang.String");
2. Class c=int.class;
3. 기본형의 경우 (Integer와 같은) Wrapper에 기정의된 TYPE을 사용한다.
Class c=Integer.TYPE;
두 번째 스텝은, getDelcaredMethods와 같은 메소드를 Call해서, 클래스에 정의된 모든 메소드의 리스트를 얻는다.
세 번째 스텝은, 정보수정을 위해 Reflection API를 이용한다.
Class c=Class.forName("java.lang.String");
Method m[]=c.getDelcaredMethods();
S.O.P(m[o].toString());
<Reflection을 사용한 Set up>
클래스 정보가 있으면, 다음 스텝은 클래스 객체에 대해서 기본적인 질의다. Class.isinstance 메소드는 instanceof를 통해서 구현될 수 있다.
class A{}
public class instance1{
public static void main(String[] args){
try{
Class cls=Class.forName("A");
boolean b1=cls.isinstacne(new Integer(37));
S.O.P(b1);
boolean b2=cls.isinstance(new A());
S.O.P(b2);
}catch(Throwable e){
System.err.println(e);
}
}
}
A의 클래스객체가 만들어진다. 그리고 class instance objects 가 A 의 인스턴스인지 체크한다.
Integer(37) 은 아니지만, new A() 는 True 이다.
Integer(37) 은 아니지만, new A() 는 True 이다.
<Constructors에 대한 정보얻기>
import.java.lang.reflect.*
public class constructor1{
public constructor1(){
}
protected constructor1(int i,double d){
}
public static void main(String args[]){
try{
Class cls=Class.forName("constructor1");
Constructor ctolist[]=cls.getDeclaredConstructors();
for(int i=0;i<ctolist.length;i++){
Constructor ct=ctorlist[i];
S.O.P("name="+ct.getName());
S.O.P("decl class="+ct.getDeclaringClass());
Class pvec[]=ct.getParameterTypes();
for(int j=0;j<pvec.length;j++)
S.O.P("param#"+j+" "+pvec[j]);
Class evec[]=ct.getExceptionTypes();
for(int j=0;j<evec.length;j++)
S.O.P("exc #"+j+" "+evec[j]);
}}}
이 프로그램에서는 리턴타입정보가 없는데... 생성자는 리턴타입을 갖지 않기 때문이다.
실행결과
name = constructor1
decl class = class constructor1
-----
name = constructor1
decl class = class constructor1
param #0 int
param #1 double
실행결과
name = constructor1
decl class = class constructor1
-----
name = constructor1
decl class = class constructor1
param #0 int
param #1 double
댓글
댓글 쓰기