反射的簡(jiǎn)單使用
前置條件三個(gè)類(lèi):A 、B:A汇陆、C怒炸;
目標(biāo):分別在獲取 B 和 C 中獲取 A 的 私有變量 以及 調(diào)用私有方法
1. 三個(gè)類(lèi)
- A:
package mm.chenme.lib.commutillibdemo.ui.other
open class A {
private val v1 = 100
private val v2 = "reflex"
companion object {
@JvmStatic
private fun printStatic(): String {
println("Hello reflex in static!")
return "execute complete!\n"
}
}
private fun printNoParam(): String {
println("Hello reflex without param!")
return "execute complete!\n"
}
private fun printHasParams(param1: String, param2: Int): String {
println("Hello reflex with params. param1:$param1, param2:$param2")
return "execute complete!\n"
}
}
- B:
class B : A()
- C:
class C
2. 步驟:
- 獲取類(lèi) A 的 class,提供以下兩種方法毡代;
val clz = A::class.java
val clz = Class.forName("mm.chenme.lib.commutillibdemo.ui.other.A")
1. 操作私有變量:
- 獲取 A 的成員變量阅羹;
val field = clz.getDeclaredField("v2")
- 修改訪問(wèn)權(quán)限;
field.isAccessible = true
- 獲取
v2
的值并打咏碳拧捏鱼;
println(field.get(this) as String)
// 執(zhí)行結(jié)果:
// reflex
- 設(shè)置
v2
的值并打印酪耕;
field.set(this, "Hello reflex!\n")
println(field.get(this) as String)
// 執(zhí)行結(jié)果:
// Hello reflex!
2. 獲取私有函數(shù)并執(zhí)行:
- 獲取函數(shù)穷躁;
val method = clz.getDeclaredMethod("printStatic")
getDeclaredMethod()
函數(shù)源碼public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { return getMethod(name, parameterTypes, false); }
name
:要獲取的函數(shù)函數(shù)名稱(chēng)
parameterTypes
:要獲取的函數(shù)參數(shù)類(lèi)型的列表(對(duì)于無(wú)參的函數(shù),該可變參數(shù)不寫(xiě))
- 修改訪問(wèn)權(quán)限因妇;
method.isAccessible = true
- 執(zhí)行該函數(shù)并打印返回值问潭;
println(method.invoke(null) as String)
// 執(zhí)行結(jié)果:
// Hello reflex in static!
// execute complete!
invoke()
函數(shù)源碼public native Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
obj
:被反射 class 的實(shí)例或其子類(lèi)的實(shí)例(當(dāng)函數(shù)為靜態(tài)函數(shù)時(shí),可以傳null
)婚被;invoke 函數(shù)參數(shù)1可傳的的數(shù)據(jù)類(lèi)型為:
① clz 的實(shí)例狡忙;
② clz 子類(lèi)的實(shí)例;
③ null址芯;
args
:函數(shù)所對(duì)應(yīng)的參數(shù)(對(duì)于無(wú)參的函數(shù)灾茁,該可變參數(shù)不寫(xiě))
3. 類(lèi) B 的完整代碼
class B : A() {
fun reflexVariable() {
val clz = A::class.java
val field = clz.getDeclaredField("v1")
field.isAccessible = true
println(field.get(this) as Int)
val field2 = clz.getDeclaredField("v2")
field2.isAccessible = true
println(field2.get(this) as String)
field2.set(this, "Hello reflex!\n")
println(field2.get(this) as String)
}
fun reflexMethod() {
val clz = A::class.java
/**
* 靜態(tài)無(wú)參數(shù)函數(shù)反射
* invoke 函數(shù)參數(shù)1可傳的的數(shù)據(jù)類(lèi)型為:
* ① clz 的實(shí)例窜觉;
* ② clz 子類(lèi)的實(shí)例;
* ③ null
*/
val method = clz.getDeclaredMethod("printStatic")
method.isAccessible = true
println(method.invoke(null) as String)
/**
* 普通無(wú)參數(shù)函數(shù)反射
* invoke 函數(shù)參數(shù)1可傳的的數(shù)據(jù)類(lèi)型為:
* ① clz 的實(shí)例北专;
* ② clz 子類(lèi)的實(shí)例禀挫;
*/
val method1 = clz.getDeclaredMethod("printNoParam")
method1.isAccessible = true
println(method1.invoke(this) as String)
/**
* 帶有參數(shù)的函數(shù)反射
*/
val method2 = clz.getDeclaredMethod("printHasParams", String::clas
method2.isAccessible = true
println(method2.invoke(this, "arg1", 100) as String)
}
}
- 調(diào)用
reflexVariable()
和reflexMethod()
執(zhí)行結(jié)果
100
reflex
Hello reflex!
Hello reflex in static!
execute complete!
Hello reflex without param!
execute complete!
Hello reflex with params. param1:arg1, param2:100
execute complete!
4. 在類(lèi) C 中使用反射
- 操作變量時(shí),將
get() set()
中的實(shí)例參數(shù)改為clz.newInstance()
即可拓颓;
println(field.get(this) as Int)
field2.set(this, "Hello reflex!\n")
// 改為
println(field.get(clz.newInstance()) as Int)
field2.set(clz.newInstance(), "Hello reflex!\n")
- 在執(zhí)行函數(shù)時(shí)语婴,將
invoke()
中的實(shí)例參數(shù)改為clz.newInstance()
即可;
println(method1.invoke(this) as String)
println(method2.invoke(this, "arg1", 100) as String)
// 改為
println(method1.invoke(clz.newInstance()) as String)
println(method2.invoke(clz.newInstance(), "arg1", 100) as String)