如何通过java反射获取kotlin扩展中声明的Properties或Function

赵小鱼*_*赵小鱼 6 java kotlin

如果我像这样在 Kotlin 中声明一个扩展函数或一些扩展属性

var View.newPosition: Int
    get():Int {
        return newPosition
    }
    set(value) {
        this.newPosition=value
        Log.e("test","newPosition"+newPosition)
    }


fun View.setPosition(value:Int ){
    Log.e("test", "Position" + value)
}
Run Code Online (Sandbox Code Playgroud)

然后我想通过Java反射来获取它们,如下所示

    Class stuClass = null;
    try {
        stuClass = Class.forName("android.view.View");
    } catch (Exception e) {
        Log.e("test", e.toString());
    }
    Field f = null;
    try {
        f = stuClass.getField("newPosition");
    } catch (Exception e) {
        Log.e("test", e.toString());
    }
    Object obj = null;
    try {
        obj = stuClass.getConstructor().newInstance();
    } catch (Exception e) {
        Log.e("test", e.toString());
    }

    try {
        f.set(obj, 555);
    } catch (Exception e) {
        Log.e("test", e.toString());
    }

    try {
        Method setPosition = stuClass.getDeclaredMethod("setPosition", int.class);
        setPosition.setAccessible(true);
        try {
            setPosition.invoke(obj, 20);
        } catch (Exception e) {
            Log.e("test", e.toString());
        }

    } catch (Exception e) {
        Log.e("test", e.toString());
    }
Run Code Online (Sandbox Code Playgroud)

但我只是得到一些错误说

NoSuchFieldException: newPosition
NoSuchMethodException: <init> []
NoSuchMethodException: setPosition [int]
Run Code Online (Sandbox Code Playgroud)

所以我想知道是否我的代码写错了或者我们无法像常见的java方法或字段一样通过java反射获取kotlin扩展Properties或Function?

Mic*_*oka 8

扩展函数和属性并没有真正添加到现有类中。Kotlin 编译器允许您引用它们,就好像它们是类的一部分一样。

如果您在 Kotlin 中名为“Funs.kt”的 Kotlin 文件中编写函数“setPosition”:

//in file Funs.kt
fun View.setPosition(value: Int) {
    //smth
}
Run Code Online (Sandbox Code Playgroud)

编译器会将其设为 FunsKt.class,其中包含静态方法“setPosition”。

public final class FunsKt {

    public static void setPosition(View $receiver, int value) {
        //smth
    }

}
Run Code Online (Sandbox Code Playgroud)

这只是 Kotlin 编译器的魔力,它允许您像使用 View 类一样使用它(请注意,因此您无法从扩展函数访问私有/受保护的值)。从 java 中,您必须按原样使用它。

要获取方法 setPosition,请执行以下操作:

Class c = Class.forName("[your package].[kotlin file name + "Kt"]");
Method m = c.getMethod("setPosition", View.class, int.class);
Run Code Online (Sandbox Code Playgroud)

扩展属性以类似的方式工作。没有创建真正的变量 - 只有两个静态方法(getter 和 setter)。这些方法没有用于存储值的实际变量,但它们会动态计算该值。您无法将它们作为 Field 对象获取,但可以以与 setPosition 相同的方式将它们作为方法获取。