-
리플렉션을 이용해 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
이제 클래스를 얻어 사용하는 리플렉션 예를 보자.
리플렉션을 사용하면 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