본문 바로가기

안드로이드

Android & Java - Reflection

반응형

Reflection?

리플렉션은 자바 기능 중 하나로, 클래스나 인터페이스의 정보에 직접 접근할 수 있도록 하는 API이다.
private 변수나, 함수, 생성자 등의 정보에 접근이 가능하다.

테스트 클래스

class SampleClass private constructor(private val privateInt : Int, private val privateString: String) {
    private var privateField: Boolean = true

    private fun privateFunction(): Boolean {
        return false
    }
}

위의 코드와 함께 설명하려 한다.


코드를 보면 생성자, 변수, 함수 죄다 private이다.
리플렉션을 통해서 생성하고, 변수를 조작하고, 함수를 실행해 보겠다.

클래스 가져오기

val c = Class.forName("com.onetwothree.reflectionteest.SampleClass")

Class.forName 를 이용하면 클래스 정보를 가져올 수 있다.

인자로는 해당 패키 지명을 포함한 클래스의 풀네임을 넣어주면 된다.

클래스 생성하기

val constructor = c.getDeclaredConstructor(Int::class.java, String::class.java)
val sampleClass = constructor.newInstance(5,"Five")

c.getConstructor, c.getDeclaredConstructor 함수를 사용해서 생성자를 가져올 수 있다.

생성자가 private 이기 때문에 getDeclaredConstructor를 사용해야 한다.

 

인자로 해당 생성자가 실제로 사용하는 인자 타입을 넣어줘야 한다.

 

결과로 얻은 constructor의 newInstance 함수에 인자를 넣으면 해당 클래스를 생성할 수 있다.

변수 가져오기

val field = c.getDeclaredField("privateField")
val modifier = Modifier.toString(field.modifiers)

field.isAccessible = true

field.set(sampleClass, false)

val privateField = field.get(sampleClass) as Boolean

getDeclaredField 를 통해서 변수 필드를 가져올 수 있다.

 

private 이기 때문에 해당 필드를 사용하려면 isAccessible 를 통해서 액세스 가능하도록 해주어야 한다.

 

set 함수를 통해서 변수를 세팅할 수 있다.

인자로는 변수를 세팅할 대상 인스턴스와 값을 넣으면 된다.

예제에서는 인 스터 스는 위에서 만든 sampleClass를 넣고 값을 false를 주었다.

 

get 함수를 통해서 변수를 가져올 수 도 있다.

인자로 가져올 대상인 인스턴스를 넣으면 값을 주는데 타입은 지정이 안되기에 직접 변환해서 사용하면 된다.

 

modifiers 를 이용하면 대상 필드의 접근제어자를 확인할 수도 있다.

함수 사용하기

val method = c.getDeclaredMethod("privateFunction")
method.isAccessible = true
val privateFunction = method.invoke(sampleClass) as Boolean

함수를 사용하고 싶을 땐 getDeclaredMethod 를 사용하면 된다.

역시나 private 이기에 isAccessible 를 true로 주어야 한다,

 

invoke 함수로 대상 클래스의 함수를 호출할 수 있다.

역시나 결과 타입은 직접 변환해주면 된다.

반응형

'안드로이드' 카테고리의 다른 글

Android - java.time 패키지  (0) 2020.07.15
Android Hilt - WorkManager  (0) 2020.07.03
Android & Java - Dynamic Proxy  (0) 2020.06.30
Android Espresso #4 - ActivityRules  (0) 2020.06.29
Android Espresso #3 - RecyclerView  (0) 2020.06.26