생성자에 대한 정보
@Test
fun `생성자에 대한 정보 얻기`() {
val clazz = Class.forName("java.lang.String")
val ctorlist = clazz.declaredConstructors
ctorlist.forEach {ct ->
println("생성자 이름 = ${ct.name}")
println("정의된 클래스 이름 = ${ct.declaringClass}")
val pvec = ct.parameterTypes
pvec.forEachIndexed {index, param ->
println("인자 $index = $param")
}
val evec = ct.exceptionTypes
evec.forEachIndexed { index, exception ->
println("익셉션 $index = $exception")
}
}
}
클래스 필드 정보
@Test
fun `클래스 필드 찾기`() {
val cls = Class.forName("java.lang.String")
val fieldList = cls.declaredFields
fieldList.forEach {
println("필드명 ${it.name}")
println("정의된 클래스 ${it.declaringClass}")
println("필드타입 ${it.type}")
println("접근제어자 ${Modifier.toString(it.modifiers)}")
}
}
메소드 이름으로 실행
@Test
fun `메소드 이름으로 실행`() {
val cls = Class.forName("java.lang.String")
val data = "Hello World"
val lengthMethod = cls.getMethod("length") // length() 메소드 찾기
val length = lengthMethod.invoke(data) // data.length()
assertEquals(11, length)
// 두개의 Int 타입이 있는 substring 메소드
val substringMethod = cls.getMethod("substring", Integer.TYPE, Integer.TYPE)
val subStr = substringMethod.invoke(data, 0, 5)
assertEquals("Hello", subStr)
}
private한 메소드도 invoke 할 수 있다
class A {
private fun show() {
println("가나다")
}
}
@Test
fun `private 메소드 invoke`() {
val a = A()
with(a.javaClass.getDeclaredMethod("show")) {
isAccessible = true
invoke(a)
}
}
getMethod()는 public한 메소드를 가져온다
getDeclaredMethod()는 private한 메소드를 포함한 클래스에 선언된 모든 메소드를 가져온다
리플렉션으로 오브젝트 생성
class Person(val name: String, val age: Int) {
fun sayMyName() {
println("이름 = $name, 나이 = $age")
}
}
@Test
fun `오브젝트 생성`() {
val personClass = Class.forName("jo.xyz.appstudy.Person")
val personConstructor = personClass.getConstructor(String::class.java, Integer.TYPE)
val person = personConstructor.newInstance("seongjun", 33) as Person
person.sayMyName()
}
필드의 값 변경
@Test
fun `필드의 값 변경`() {
val cls = Class.forName("jo.xyz.appstudy.Person")
val ageField = cls.getDeclaredField("age")
ageField.isAccessible = true
val person = Person("seongjun", 33)
assertEquals(33, person.age)
ageField.setInt(person, 23)
assertEquals(23, person.age)
}
실제 제가 사용했던 코드
private fun setDividerColor(vararg pickers: NumberPicker) {
try {
val selectionDivider = NumberPicker::class.java.getDeclaredField("mSelectionDivider")
selectionDivider.isAccessible = true
for (picker in pickers) {
selectionDivider.set(picker, dividerColor)
}
} catch (e: NoSuchFieldException) {
} catch (e: IllegalAccessException) {
}
}
번외
@Test
fun `궁금하다 알아보자`() {
val intClass1 = Int::class.java
val intClass2 = Integer.TYPE
val intClass3 = Int::class
val intClass4 = Int.javaClass
println("intClass1 = $intClass1") // int
println("intClass2 = $intClass2") // int
println("intClass3 = $intClass3") // class kotlin.Int
println("intClass4 = $intClass4") // class kotlin.jvm.internal.IntCompanionObject
assertTrue(Integer.TYPE == Int::class.java)
val i = 0
println("i.javaClass = ${i.javaClass}") // int
println("i::class.java = ${i::class.java}") // int
println("i::class = ${i::class}") // class kotlin.Int
assertTrue(Int.javaClass != i.javaClass)
assertTrue(Int::class == i::class)
assertTrue(Int::class.java == i::class.java)
}
출처
- 도서, 아키텍처를 알아야 앱 개발이 보인다
- 블로그, 찰스의 안드로이드 https://www.charlezz.com/?p=756
'Kotlin' 카테고리의 다른 글
Reflection #1 (0) | 2020.06.29 |
---|