ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리플렉션을 이용해 private 필드 값 변경
    TIL 2021. 2. 7. 12:11

    내가 이해한 리플렉션은 런타임 시점에 어떤 객체의 메소드나 필드가 몇 개인지 뭐 인지 등 값을 알 수 있고 사용도 가능하고 값도 변경이 가능하다.

     

     

     

     

     

    내용물을 보려면 해당 클래스가 무엇인지를 알아야한다. 클래스를 알 수 있는 방법은 많으면 Class클래스의 forName()이나 getClass가 있다.

    getClass는 얻고자 하는 클래스의 객체에 사용하면 런타임 시점에 얻을 수 있다.

    forName은 객체를 생성하지 않고 Class.forName()으로 얻고자 하는 클래스의 풀 경로를 적어주면 얻을 수 있다.

     

     

     

    근데 Class 말고 해당 클래스에서 얻는 방법도 있다. 클래스명.Class를 하면 얻을 수 있다.

    .getClass()와 .Class의 차이점이 궁금했다.

     

    둘의 차이점은 무엇일까?

     

    객체.getClass()

    런타임 시점에 해당 객체의 클래스를 얻을 수 있음

    클래스명.Class()

    컴파일 시점에 얻을 수 있음

     

    또 성능 차이가 있을 수 있다. getclass는 디스패치를 하기 때문에 그렇다. 근데 jvm에 따라 다르다고 한다.

    둘 다 목적이 class를 얻는 것이기 때문에 사용하는 시점이 언제인지 그때그때 알맞게 사용하면 될 듯하다.

    stackoverflow.com/questions/10947768/what-is-the-difference-between-a-getclass-and-a-class-in-java

     

    What is the difference between a.getClass() and A.class in Java?

    In Java what pros/cons exist surrounding the choice to use a.getClass() or A.class? Either can be used wherever a Class is expected, but I imagine that there would be performance or other ...

    stackoverflow.com

     

     

     

     

     

    이제 클래스를 얻어 사용하는 리플렉션 예를 보자.

     

    리플렉션을 사용하면  getter 없이 private 한 필드의 값을 얻고 setter 없이 값을 변경이 가능하다.

     

    public class SonOne{

         public String publicName;
         private String privateName;

         public SonOne(String name) {
              this.publicName = name;
         }

         public String getPrivateName() {
              return privateName;
         }

    }

     

    1.. getClass를 이용하기

     

    //런타임 시점 인스턴스가 있어야 하니
    SonOne sonOne=new SonOne("public 필드 초기화");
        
    try {
        Field privateName = sonOne.getClass().getDeclaredField("privateName"); //파라미터 이름을 가진 필드를 get
        privateName.setAccessible(true); // 접근을 허용 false시 접근 예외 발생
       
        privateName.set(sonOne,"sample");  //해당 객체의 필드에 접근해 값 변경

        System.out.println(sonOne.getPrivateName());  // sample


    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

     

    2. .Class를 이용하기 ( 둘 다 해당 특정 객체의 값을 변경하기 위해 객체를 넘겨주긴 한다. )

     

    SonOne sonOne=new SonOne("public 필드 초기화");

    try {
        Field privateName = SonOne.class.getDeclaredField("privateName"); //특정 필드 값 지정
        privateName.setAccessible(true);

        privateName.set(sonOne,"ClassSample");
        System.out.println(sonOne.getPrivateName());  //ClassSample

        String getPrivateString = (String) privateName.get(sonOne);  //해당 객체의 필드 값을 얻기
        System.out.println(getPrivateString); //ClassSample


    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

     

     

     

    여기서 리플렉션을 하기 위해 사용하는 메소드를 보자. 

    getDeclaredField()를 사용했는데 getField()도 있다.

    둘의 차이점은 무엇일까?

     

    getField() : 해당 Class의 public 한 필드를 얻음 + 상속받았으면 부모의 public 필드도 보여줌 

    getDeclaredField() : 해당 Class 모든 필드를 보여줌 (public private) + 상속받은 부모의 public 필드는 보여주지 않음

     

    메소드도 같다.

     

     

    + forName을 이용해 런타임 시점에 객체를 동적으로 생성하는 포스트는 다음에..

    'TIL' 카테고리의 다른 글

    서비스 로더 (service loader)사용하기  (0) 2021.02.07
    객체를 런타임 시점에 동적으로 생성하기  (0) 2021.02.07
    2021.02.07 기록장  (0) 2021.02.06
    Comparable과 Comparator  (0) 2021.02.06
    3항 연산자  (0) 2021.02.06

    댓글

Designed by Tistory.