이것을 참조하여 만든 JavaBeans의 toString()
// 전역변수로 쓰인 모든 변수명과 저장된 값을 출력한다.
public String toString() {
  StringBuffer sb = new StringBuffer();
  try {
   for(Field f : this.getClass().getDeclaredFields()) {
    sb.append("{" + f.getName() + ":" + f.get(this) + ":" + paramMap.get(f.getName()) + "},");
   }
  } catch(Exception e) {
   e.printStackTrace();
  }
  return sb.toString();
 }



Java Reflection in Action
http://www.manning.com/forman/
http://decoder.tistory.com/610

리플렉션을 이용한 객체 직렬화(serialization)

자바에는 내장(built-in) 직렬화 메커니즘을 갖추고 있다. 바로 Serializable 마커 인터페이스(marker interface)가 그것이다. Serializable 인터페이스를 구현하는 클래스는 JVM에 의해 직렬화가 가능하다. 하지만 이 방법은 바이너리 형식으로 객체를 직렬화하기 때문에 readable 하지 못하고, JVM 상에서만 활용 가능하다. 따라서 직렬화 형태를 텍스트나 XML 형태로 하면 보다 다른 곳에서도 보다 유용하게 활용할 수 있다. 게다가 Serializable을 이용한 방법은 직렬화 대상 클래스가 Serializable 인터페이스를 구현해야 하기 때문에 제약이 심하다는 단점도 있다. 만약 써드 파티 라이브러리의 객체를 직렬화 하고 싶다면 Serializable 인터페이스를 이용한 방법은 쓸 수 없는 것이다.

Reflection API를 이용한 XML 직렬화
어떤 객체를 직렬화 하려면 해당 객체의 필드 정보에 접근해야 한다. Reflection API에는 객체의 필드에 접근할 수 있도록 도와주는 메서드를 제공한다.

Field getField(String name)
Field[] getFields()
Field getDeclaredField(String name)
Field[] getDeclaredFields()

getField()와 getDeclaredField()의 차이점은 getMethod()와 getDeclaredMethod() 메서드와 동일하다.

주어진 객체의 모든 필드를 가져오는 메서드(상위클래스를 traverse하여 필드를 찾는다)
public Field[] getAllFields(Object obj) {
    Class cls = obj.getClass();
    List accum = new LinkedList();
   
    while ( cls != null ) {
        Field[] f = cls.getDeclaredFields();
        for (int i = 0; i < f.length; i++) {
            accum.add(f[i]);
        }
        cls = cls.getSuperclass();
    }
   
    return (Field[])accum.toArray(new Field[accum.size()]);
}

java.lang.reflect.Field 클래스는 필드에 대한 정보를 조회할 수 있는 각종 메서드를 제공한다.
Class getType()
Class getDeclaringClass()
String getName()
int getModifiers()
Object get(Object obj)
boolean getBoolean(Object obj)
...
void set(Object obj, Object value)
void setBoolean(Object obj, boolean value)
...

getModifiers() 메서드는 해당 Field의 modifier가 int로 인코딩된 값을 반환한다.
get() 메서드는 주어진 필드의 값을 반환한다.
set 메서드는 주어진 필드의 값을 전달된 value로 설정한다.
getBoolean()이나 setBoolean()과 같이 특정 타입이 명시된 메서드는 해당 타입의 값을 가져오거나, 해당 타입의 값을 설정한다.

String fieldName = field.getName();
String fieldDeclClass = field.getDeclaringClass().getName();

자바의 modifier는 11개이다.
 public  static  native
 volatile  protected  abstract
 synchronized  strictfp  private
 final
 transient  

Modifier 클래스에는 이런 자바의 modifier를 확인할 수 있는 메서드를 제공한다.
static boolean isPublic(int mod)
static boolean isPrivate(int mod)
static boolean isProtected(int mod)
static boolean isStatic(int mod)
static boolean isFinal(int mod)
static boolean isSynchronized(int mod)
static boolean isVolatile(int mod)
static boolean isNative(int mod)
static boolean isInterface(int mod)
static boolean isTransient(int mod)
static boolean isAbstract(int mod)
static boolean isStrict(int mod)

Modifier의 값을 String 형태로 제공하는 메서드는 다음과 같다.
System.out.print( Modifier.toString(Member.class.getModifiers()) );

직렬화를 위해서는 static 멤버를 제외할 필요가 있다. 이를 위해서는 Modifier의 정보를 이용하면 된다.
if ( !Modifier.isStatic(fields[i].getModifiers()) ) {
   accum.add(fields[i]);
}

nonpublic 멤버에 접근하려면?
Field와 Method 클래스는 java.lang.reflect.AccessibleObject 클래스의 하위 클래스이다. 어떤 필드나 메서드를 외부에서도 접근 가능하게 설정하려면 AccessibleObject 클래스에 정의된 setAccessible() 메서드를 이용하면 된다.

if ( !Modifier.isPublic(field.getModifiers()) ) {
   field.setAccessible(true);
}
Object value = field.get();

Array는 어떻게 하나?
primitive array는 Object[]로 type casting할 수 없다. 이 경우 java.lang.reflect.Array 클래스에서 제공하는 기능을 활용할 수 있다.

Array 클래스에서 제공하는 메서드는 다음과 같다.
Object newInstance(Class componentType, int length)
Object newInstance(Calss elementType, int[] dimensions)
int getLength(Object array)
Object get(Object array, int index)
boolean getBoolean(Object array, int index)
...
void set(Object array, int index, Object value)
void setBoolean(Object array, int index, boolean value)
...

이런 사항들과 XML 처리 라이브러리를 활용하면 객체를 직렬화할 수 있을 것이다. 실제로 돌아가는 코드는 Java Reflection in Action의 예제 코드를 참조하시라! 낄낄


출처 : 아직 가지 않은 길 (http://decoder.tistory.com/612)

'Java' 카테고리의 다른 글

KorConvert 최적화된 한글 인코딩을 찾는다.  (1) 2011.03.17
java로 제작된 최소용량 httpd (pygmy)  (1) 2011.03.15
jdbc lib url 모음  (1) 2011.01.10
java mail helper  (2) 2010.12.24
정규표현식  (2) 2010.08.04