View

Java Reflection

rura6502 2018. 4. 3. 23:18

Reflection 이란?

클래스의 이름만으로도 객체의 정보를 가져올 수 있는 기능.

왜쓰나?

동적으로 클래스를 호출해야 될 때 사용. 코드를 작성하는 시점이 아니라 JVM이 application이 running하고 있을 때 어떤 동작(사용자의 요청 또는 로직)에 의해서 사용해야 하는 class가 정해질 때 사용된다. JSON, XML 파서나 Spring에서 Bean을 생성할 때도 쓴다고 한다.

기본 사용법


의 모양으로 class를 얻는다. 여기서 className은 패키지를 포함한 클래스명을 적어야한다. 이렇게 Class 객체를 얻으면 해당 클래스에 대한 annotation, field, method, constructor 등 거의 모든 정보에 접근 가능하고 해당 정보를 사용해서 인스턴스를 생성까지 할 수 있다.


사용예시

내가 받는 예상 가능 한 일정한 모양의 데이터(DB 쿼리 결과 등)를 조회해서 똑같은 모양의 클래스와 매핑하고자 할 때 사용을 하였었다. 파서도 유사한 로직을 수행할 것으로 예상된다. 만약에 어떤 api를 조회했을 때


1
2
3
4
5
{
    "name" : "rura6502"
    "age" : 99
    "country" : "korea"
}

cs


위와 같은 데이터가 나온다고 하면

1
2
3
4
5
class Person {
  String name;
  int age;
  String country;
}
cs


위 모양의 클래스를 만들어서 매핑 시키면 활용가능한 인스턴스를 얻을 수 있을 것이다. 대충 Person 클래스의 매핑 로직을 짜면


1
2
3
4
5
6
public Person mappingForPerson(Map<String, Object> data) {
    Person person = new Person();
    person.name = data.get("name");
    ....
    return person;
}
cs


위와 같은 메소드가 만들어 질 것 같은데 만약 Person 말고 다른 종류의 다양한 객체가 있으면 해당 객체의 갯수 만큼 메소드를 만들어야 된다. 하지만 여기서 reflection을 활용하면 데이터의 클래스 오브젝트를 받아서 클래스의 필드, 생성자 등 클래스에 대한 정보를 알아낸 다음에 순서에 따라서 착착 매핑시켜주고 생성자를 호출해서 만든 인스턴스를 반환하면 여러가지 클래스를 감당할 수 있는 하나의 메소드를 만들수 있게 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public <T> T mapToClassMapping(Map<String, Object> data, Class<T> mappingClass) {
    
  Set<String> keys = data.keySet();
  Field[] fields = mappingClass.getDeclaredFields();
  Class paramTypes[] = new Class[fields.length];
  Object args[] = new Object[fields.length];
  int i=0;
  for (String key : keys) {
    paramTypes[i] = fields[i].getType();
    args[i] = paramTypes[i].cast(data.get(key));
    i++;
  }
  Constructor<T> ct = mappingClass.getConstructor(paramTypes);
  return ct.newInstance(args);
}
cs


간단하게 설명하자면 매핑하고자 하는 클래스 오브젝트를 받고 생성에 필요한 필드, 필드 타입을 분석해서 Map에서 나오는 데이터와 차례차례 매핑시켜서 인스턴스를 리턴하는 메소드이다. 이 코드는 테스트용 코드로 실제로 사용하려면 약간의 고급화 과정이 필요하다. 맵의 key와 맞는 필드에 세팅한다던가 등등.. 단순히 reflection의 기능을 이해하고자 만든 코드이다. 아래는 테스트 코드.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  public static void main(String[] args) throws Exception {
    class Person {
      String name;
      Integer age;
 
      public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
      }
    }
    Map<String, Object> testMap = new HashMap<String, Object>();
    testMap.put("name""rura6502");
    testMap.put("age"20);
 
    Person rura6502 = PrestoUtil.mapToClassMapping(testMap, Person.class);
    System.out.println(rura6502.name);
    System.out.println(rura6502.age);
  }
cs


참조

reflection을 조심해서 써야되는 이유 - https://stackoverflow.com/a/43014858/6563164


'Program language > Java' 카테고리의 다른 글

디자인 패턴 cheat sheet  (0) 2022.04.10
run java project with h2 without installation  (0) 2022.01.22
Share Link
reply