본문 바로가기

OS 관련/안드로이드

안드로이드 getDeclaredFields 활용하여 VO 객체에 한번에 값 넣기


안드로이드 개발 중 간단하게 VO에 임의의 값을 넣어서 사용해야 할 일이 있어 getDeclaredFields를 사용해서 구현하였습니다.

자바의 라이브러리라 자바에 포스팅 해야하나 안드로이드에 포스팅 해야하나 고민하다가 자바였으면 이렇게 개발하지 않았을 것 같아서 안드로이드 카테고리에 포스팅 합니다.

참고하실 분들은 보시고 참고해 주세요.

getDeclaredFields로 프로퍼티 정보 가져오기


특정 객체의 클래스로 접근 시(getClass()사용) 내부의 프로퍼티들의 명을 getDeclaredFields를 활용하여  Field의 배열 형태로 가져올 수 있습니다.

예를 들어서 TestVO라는 클래스가 있고 이 클래스의 객체를 testVO라고 하겠습니다. 이때,


TestVO testVO = new TestVO();

Field[] fields = testVO.getClass().getDeclaredFields();


와 같은 방법 사용 시 fields 내부에 TestVO의 프로퍼티에 대한 정보가 담기는 방식입니다.

이를 이용해서 모든 프로퍼티에 값을 넣을 생각입니다.

 for문과 Field 객체를 활용하여 임의 데이터 넣기


위와 같은 방식으로 필드가 생성된 상태라면 for문을 활용해 배열의 전체를 훓고 지나가는 것이 가능해집니다. 

그 후 TestVO의 내부 프로퍼티를 Field클래스를 활용하여 값을 넣어줄것입니다.

일단 Field의 getType() 메소드로 어떤 타입인지 확인하는 분기를 만들겠습니다. 


for (Field field : testVO.getClass().getDeclaredFields()) {
    if (field.getType().equals(String.class)) {
        //set string
    } else if(field.getType().equals(Integer.class)) {
        //set Integer
    } else if(field.getType().equals(Boolean.class)) {
        //set Boolean
    }
}


getType을 활용하여 프로퍼티의 클래스 형을 가져온 후 제가 만든 VO에 존재하는 클래스의 타입을 .class와  equals를 활용해 비교 하였습니다.

다음으로, 실제 객체에 값을 집어 넣어보겠습니다.

이를 위해서 Field클래스의 set 메소드를 활용하겠습니다.


for (Field field : testVO.getClass().getDeclaredFields()) {
    if (field.getType().equals(String.class)) {
        field.set(testVO, "1");
    } else if(field.getType().equals(Integer.class)) {
        field.set(testVO, 1);
    } else if(field.getType().equals(Boolean.class)) {
        field.set(testVO, true);
    }
}


Field 클래스의 set 메소드는 두개의 매개변수를 가지고 있습니다. 

첫번째 매개변수는 실질적으로 값이 주입될 객체를 두번째 매개변수는 넣어줄 값 입니다.

이로써, 실질적으로 객체에 프로퍼티에 값을 주입하는 부분은 완료 되었습니다. 

* set 메소드의 경우 실사용 시에는 IllegalAccessException 이란 예외가 발생할 수 있기 때문에 try catch 구문을 활용해 주셔야 합니다.

함수로 만들기


이제 위 코드의 활용성을 높이기 위해 위 코드를 활용하여 함수로 만들겠습니다.


private <T> T setVO(T t){
    try {
        T testVO = t;

        for (Field field : testVO.getClass().getDeclaredFields()) {
            if (field.getType().equals(String.class)) {
                field.set(testVO, "1");
            } else if(field.getType().equals(Integer.class)) {
                field.set(testVO, 1);
            } else if(field.getType().equals(Boolean.class)) {
                field.set(testVO, true);
            }
        }

        return testVO;
    } catch (IllegalAccessException e){
        Log.e("ERROR", e.getMessage());

        return t;
    }
}


대략 위와 같은 형태가 됩니다.

어떠한 클래스가 사용되는지 상관 없도록 하기 위해서 제너릭을 활용하였고, 

set 메소드의 예외 처리를 해주었습니다. 

더 간결한 코드를 만들수도 있겠지만 당장 생각난 것은 위 방법이라 이러한 방식으로 해결 해봤네요.

다른 좋은 방법을 아시면 얘기해 주시면 감사하겠습니다.