Java/Android/Kotlin:对私有字段的反思和对其调用公共方法

Java/Android/Kotlin:对私有字段的反思和对其调用公共方法,java,android,kotlin,Java,Android,Kotlin,是否可以使用反射来访问对象的私有字段并在此字段上调用公共方法 i、 e 使用反射可以使私有字段可访问。下面的示例(都是用Kotlin编写的)展示了它 使用Java反射: val hello = Hello() val f = hello::class.java.getDeclaredField("world") f.isAccessible = true val w = f.get(hello) as World println(w.foo()) val hello = Hello() val

是否可以使用反射来访问对象的私有字段并在此字段上调用公共方法

i、 e


使用反射可以使
私有
字段
可访问
。下面的示例(都是用Kotlin编写的)展示了它

使用Java反射:

val hello = Hello()
val f = hello::class.java.getDeclaredField("world")
f.isAccessible = true
val w = f.get(hello) as World
println(w.foo())
val hello = Hello()
val f = Hello::class.memberProperties.find { it.name == "world" }
f?.let {
    it.isAccessible = true
    val w = it.get(hello) as World
    println(w.foo())
}
inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? {
    val classArray: Array<Class<*>> = args.map { it!!::class.java}.toTypedArray()
    return T::class.java.getDeclaredMethod(name, *classArray)
        .apply { isAccessible = true }
        .invoke(this, *args)
}
使用Kotlin反射:

val hello = Hello()
val f = hello::class.java.getDeclaredField("world")
f.isAccessible = true
val w = f.get(hello) as World
println(w.foo())
val hello = Hello()
val f = Hello::class.memberProperties.find { it.name == "world" }
f?.let {
    it.isAccessible = true
    val w = it.get(hello) as World
    println(w.foo())
}
inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? {
    val classArray: Array<Class<*>> = args.map { it!!::class.java}.toTypedArray()
    return T::class.java.getDeclaredMethod(name, *classArray)
        .apply { isAccessible = true }
        .invoke(this, *args)
}

Kotlin的两个有用的扩展函数:

inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? =
    T::class
        .declaredMemberFunctions
        .firstOrNull { it.name == name }
        ?.apply { isAccessible = true }
        ?.call(this, *args)

inline fun <reified T : Any, R> T.getPrivateProperty(name: String): R? =
    T::class
        .memberProperties
        .firstOrNull { it.name == name }
        ?.apply { isAccessible = true }
        ?.get(this) as? R
inline fun T.callPrivateFunc(名称:String,vararg args:Any?):Any=
T::类
.declaredMemberFunctions
.firstOrNull{it.name==name}
?应用{isAccessible=true}
?呼叫(此,*args)
内联fun T.getPrivateProperty(名称:字符串):R=
T::类
.memberProperties
.firstOrNull{it.name==name}
?应用{isAccessible=true}
把(这个)当作?R
使用这些扩展函数,我们可以访问类的私有属性和函数。例如:

class SomeClass {

    private val world: World = World()

    private fun somePrivateFunction() {
        println("somePrivateFunction")
    }

    private fun somePrivateFunctionWithParams(text: String) {
        println("somePrivateFunctionWithParams()  text=$text")
    }
}

class World {
    fun foo(): String = "Test func"
}

// calling private functions:

val someClass = SomeClass()
someClass.callPrivateFunc("somePrivateFunction")
someClass.callPrivateFunc("somePrivateFunctionWithParams", "test arg")

// getting private member and calling public function on it:

val world = someClass.getPrivateProperty<SomeClass, World>("world")
println(world?.foo())
class-SomeClass{
private val world:world=world()
private fun somePrivateFunction(){
println(“somePrivateFunction”)
}
private fun somePrivateFunctionWithParams(文本:字符串){
println(“somePrivateFunctionWithParams()text=$text”)
}
}
阶级世界{
fun foo():String=“Test func”
}
//调用私有函数:
val someClass=someClass()
someClass.callPrivateFunc(“somePrivateFunction”)
调用privatefunc(“带有参数的someprivatefunction”,“测试参数”)
//获取私有成员并在其上调用公共函数:
val world=someClass.getPrivateProperty(“世界”)
println(world?.foo())
要在Kotlin中使用反射,请添加依赖项:

实现“org.jetbrains.kotlin:kotlin reflect:$kotlin_version”


使用Java反射调用带有参数的私有函数:

val hello = Hello()
val f = hello::class.java.getDeclaredField("world")
f.isAccessible = true
val w = f.get(hello) as World
println(w.foo())
val hello = Hello()
val f = Hello::class.memberProperties.find { it.name == "world" }
f?.let {
    it.isAccessible = true
    val w = it.get(hello) as World
    println(w.foo())
}
inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? {
    val classArray: Array<Class<*>> = args.map { it!!::class.java}.toTypedArray()
    return T::class.java.getDeclaredMethod(name, *classArray)
        .apply { isAccessible = true }
        .invoke(this, *args)
}
inline fun T.callPrivateFunc(名称:String,vararg args:Any?):Any?{
val classArray:Array=args.map{it!!::class.java}.toTypedArray()
返回T::class.java.getDeclaredMethod(名称,*classArray)
.apply{isAccessible=true}
.invoke(此,*args)
}

如果您喜欢可读的、可重复使用的、易于理解的解决方案:

在某处定义:

fun <T> Any.privateField(name: String): T {
    val field = this::class.java.getDeclaredField(name)
    field.isAccessible = true
    @Suppress("UNCHECKED_CAST")
    return field.get(this) as T
}
fun Any.privateField(名称:String):T{
val field=this::class.java.getDeclaredField(名称)
field.isAccessible=true
@抑制(“未选中的_CAST”)
返回字段。将(此)作为T获取
}
并在其他地方使用:

val <T : TextInputLayout> T.startIconView: CheckableImageButton
    get() = privateField("startIconView")
val T.startIconView:CheckableImageButton
get()=privateField(“startIconView”)

如何访问不在使用反射的类中的私有val?对于属性,您可能需要执行
it.getter.call(hello)
而不是
it.get(hello)
这是否适用于
private
Kotlin扩展函数??