저번 시간에 transient를 보다가, 잠깐 reflection에 대해서 언급했었는데요. 아마 언급을 하지 않았더라도, 클래스의 메타 데이터에 대한 정보를 얻어온다. 라는 것은 언급했을 듯 합니다. 내부를 보실 때, 이해하셨다면 좋았을 법한 로직만 간단하게 소개해 볼게요.

 


 먼저, 객체를 직렬화 하기 위해서, 필드와 필드에 셋팅된 값이 어떤 값이였는지 알아야 했습니다. 그러한 정보들을 얻어와서 직렬화를 시킨다고 했어요. 그런데, transient 같은 키워드가 앞에 붙어있으면 직렬화를 하지 말아야 함을 의미해요. 즉, 필드 중에서 직렬화를 하지 말아야 하는 키워드가 앞에 붙어있는지도 알아내야 합니다.

 

 즉, 객체에 대한 정보를 얻어올 때, 이 필드가 직렬화가 가능한 친구인지, 할당된 값은 무엇인지. 필드 이름은 무엇인지 등을 얻어와야 합니다. 어떻게 해야 할까요? 예제 프로그램을 먼저 봅시다.

 

 

 먼저 d.getClass()는 객체 d의 클래스 메타 데이터들을 얻어옵니다. 예를 들자면 선언되어 있는 필드 등이 이에 속합니다. 그리고 메서드 getDeclaredFields가 보이는데요. 선언된 필드들의 메타 정보들을 얻어옵니다. 리턴 값은 배열입니다.

 

 

 이제 이들을 가지고, 필드 이름과 앞에 붙은 Modifiers, 그리고 실제로 할당된 값 등을 얻어옵니다.

 

 

 필드는 private로 선언된 x와 y가 있는데요. 이들에 대한 메타 정보들이 배열에 저장됩니다. 그러면 배열을 돌면서 해당 필드들에 대한 메타 데이터를 뽑아주기만 하면 되겠네요.

 

 

 getName은 필드의 이름을 뽑아냅니다.

 

 

 getModifiers는 필드 앞에 붙은 modifiers를 뽑아내는데요. 왠 int값을 뽑아내지? 라는 의문이 드실 수 있습니다.

 

 

 Modifier 클래스를 보면 isPublic, isPrivate와 같은 친구들이 있는데요. 이들을 잘 보면, & 연산을 하고 있음을 알 수 있어요. 마스킹 연산인데요. 특정 비트가 켜져 있으면 참값을 리턴합니다. 즉, 상태를 비트로 관리한다는 것을 챌 수 있어요. 이 필드가 Public인지, 아니면 Private가 붙어있는지 등은 Modifier의 isXXX 메서드로 처리할 수 있어요.

 

 직렬화 과정에서는 아예 Modifier의 STATIC과 TRANSIENT를 bit or한 것과 masking 했을 때 0이 아니면 필터링 걸어버리는 로직이 있었습니다.

 

 

 앞에 붙은 modifier를 모두 출력하려면, toString을 이용하시면 됩니다. masking 연산을 이용해서 어떤 비트가 켜져있는지를 모두 검사한 후에, StringJoiner를 이용해서 리턴해 버리게 됩니다. 예를 들어, private이면서 static인 경우, "private static"이 리턴될 겁니다.

 

 


 다음에, get 메소드는 특정 object의 필드 값을 리턴합니다. 예를 들어 f[i]의 필드 이름이 "x"였다고 해 보겠습니다. f[i].get(d)는, 객체 d의 필드 "x"의 값을 리턴합니다. 그런데, for loop를 자세히 보셨다면 아시겠지만, setAccessible을 true로 설정했음을 알 수 있습니다.

 

 

 이는 필드 x와 y가 private 하기 때문입니다.

 

 

 프로그램의 실행 결과는 위와 같습니다. 필드들의 값, 앞에 붙어 있는 modifier, 그리고 오브젝트 d가 들고 있는 값을 보여줍니다. 그러면, 필드 이름을 알고 있을 때, 해당 필드에 대한 정보만 얻어오는 방법은 없을까요?

 

 

 이 때는 getDeclaredField를 이용하면 됩니다. 이 메서드는 필드 이름이 name인 필드 정보를 얻어옵니다.

 

 

 이 프로그램의 실행 결과는 어떻게 될까요?

 

 

 x private 1이 나옵니다.