java/kotlin反射调用私有方法

90 阅读1分钟
  1. 使用getSuperclass()获取父类的Class对象

在Java中,每个类都有一个对应的Class对象。通过调用一个对象的getClass()方法,可以获得该对象的Class对象。然后,通过调用Class对象的getSuperclass()方法,可以获得这个类的父类的Class对象。

  1. 使用getDeclaredMethod()获取私有方法

Class对象的getDeclaredMethod()方法可以获取该类中声明的所有方法,包括公有、保护、默认(包)访问和私有方法,但不包括继承的方法。因此,可以使用这个方法来获取父类的私有方法。

  1. 设置私有方法可访问

由于私有方法默认不可访问,所以需要通过setAccessible(true)方法来改变其可访问性。这是反射的一个重要特性,它允许Java代码访问本不可访问的方法。

  1. 调用私有方法

有了方法对象后,就可以调用该方法了。可以使用invoke()方法来调用,该方法的第一个参数是方法的调用者,第二个参数开始是调用该方法时需要传入的参数。

package local.my.demojdk

/**
 * 反射调用方法,通过对象调用方法,通过类Class调用静态方法
 * @param name 方法明朝
 * @arg 参数
 */
fun Any?._ivk_j(name: String, vararg arg: Any?) : Any?{
    if (this == null){
        return null
    }
    val isSt = this is Class<*> //当类调用时
    var clz:Class<*> = if(isSt)this else this::class.java
    do {
        lm@for (m in clz.declaredMethods) {
            if (m.name.equals(name)){
                if(m.parameterCount==0&&(arg.size==0)){
                    m.isAccessible=true
                    return m.invoke(if(isSt)null else this)
                }else if (m.parameterCount== arg.size){
                    for (i in 0..<m.parameterCount){
                        if (arg[i]!=null&&m.parameterTypes[0]!=arg[i]::class.java){
                            continue@lm
                        }
                    }
                }else continue
                m.isAccessible=true
                return m.invoke(if(isSt)null else this,arg)
            }
        }
        clz = clz.superclass
        //循环从父类查找私有方法
    }while (clz!=Object::class.java)
    return null;
}

fun main() {
    //调用对象方法
    println(Object()._ivk_j("toString"))
    //调用静态方法
    println(java.util.List::class.java._ivk_j("of"))
    //log:
    //java.lang.Object@69663380
    //[]
}