안녕하세요. 666번째 글입니다. 이번 시간에는 reflection을 이용해서 field value를 set하는 코드만 간략하게 보겠습니다.

 


 먼저, data 클래스의 코드는 요렇습니다. private field로 선언된 x, y, 그리고 hm이 있네요. 당연하게도, hashCode와 equals, 그리고 toString은 오버라이딩 되어 있습니다.

 

 

 우리는 먼저, 이름으로 Field에 대한 정보를 얻어온 다음에, 10번째 줄에서 set 메서드를 이용해서, 객체 d의 hm 필드의 값을 {"a":"b", "c":"d"}로 바꿀 것인데요.

 

 

 NoSuchFieldException이 뜹니다. 왜 그런지 메서드 설명을 봐야 겠어요.

 

 

 먼저, 이 친구는 public member인 field member를 리턴합니다. Data에서 이름이 "x"인 것은 public field가 아니였으므로, 이름 "x"인 field는 리턴되지 않고, NoSuchField exception이 떨어지게 됩니다. private field에 대한 정보도 얻어오기 위해서는 선언된 필드를 가져오는 getDeclaredField 메서드를 써야 합니다. 

 

 

 이 메서드는 declared field를 리턴하게 됩니다. 실제로 함수 내부로 들어가서 보면, privateGetDeclaredFields 라는 메소드를 호출하는 부분이 보이는데요.

 

 

 여기서 publicOnly 플래그가 false가 켜져 있음을 볼 수 있습니다.

 

 


 우리의 목적은 data 객체인 d의 field hm의 값을 리플렉션을 이용하여 바꾸는 것입니다. 그러기 위해서는 선언된 "hm" 필드에 대한 정보를 얻어온 다음에 set 메서드를 호출하면 될 것인데요.

 

 

 그래서, 그냥 요렇게만 코드를 작성했어요. 의도대로 수행이 될까요?

 

 

 그렇지 않습니다. hm 필드가 private로 묶여버렸기 때문입니다. 그러면 어떻게 해야 할까요? Accessible 하지 않아서 예외가 떨어졌으니, Accessible하게 만들어 주면 됩니다. 이는 setAccessible 메서드로 할 수 있습니다.

 

 

 사실 문서를 읽어보면 얼추 알 수 있는데요. setAccessible을 true로 설정해 두면, java language의 access control을 suppress 하게 되는데요. 사전을 찾아보면, 억누르다, 억제하다, 참다 정도의 뜻을 가지고 있습니다. 이에 대해 모르더라도 false로 설정되면, 강제하다라는 enforce가 언급됨을 알 수 있는데요.

 

 이로 미루어 보았을 때, 필드 "hm"에 대해서 setAccessible을 true로 설정하면, "hm"에 대한 access check를 억제한다고 유추할 수 있어요. 

 

 따라서, 9번째 줄에서 setAccessible을 true로 설정하고 나면, 객체 d의 field "hm"에 값을 set 할 수 있게 됩니다. 이는 set 메서드의 설명의 중간 부분을 보시면 대강 유추하실 수 있는 부분입니다. field "hm"이 private였기 때문에, 저는 setAccessible을 true로 설정했습니다. 실행 결과를 보겠습니다.

 

 

 제가 원하던 대로 잘 들어갔음을 볼 수 있습니다.