Java 如何从Kotlin中的KClass获取方法

Java 如何从Kotlin中的KClass获取方法,java,android,class,kotlin,reflection,Java,Android,Class,Kotlin,Reflection,在java中,当我有一个类实例时,我有一个返回方法的getMethod,它非常容易使用。 正如我所见,科特林让生活变得更加艰难,因为这样的方法并不存在。除了将KClass转换为类,然后像在Java中一样使用它之外,还有什么好方法可以获得特定的方法吗?假设您有这个类: class Test { fun sayHello() = println("Hello world") companion object { fun foo() = print

在java中,当我有一个类实例时,我有一个返回方法的getMethod,它非常容易使用。
正如我所见,科特林让生活变得更加艰难,因为这样的方法并不存在。除了将KClass转换为类,然后像在Java中一样使用它之外,还有什么好方法可以获得特定的方法吗?

假设您有这个类:

class Test {
    fun sayHello() = println("Hello world")

    companion object {
        fun foo() = println("foo")
    }
}
这为您提供了一个可以使用invoke调用的函数实例,它是一个运算符函数,因此您可以像使用任何其他函数一样使用括号。如果像这样使用类名获取函数,则它不会绑定到实例。因此,在调用时将实例作为第一个参数传递。如果sayHello有额外的参数,它们将只跟随测试的第一个参数

val sayHelloFunction = Test::sayHello
val test = Test()
helloWorldFunction(test) // same as calling test.sayHello()
您还可以获得绑定到如下实例的函数引用。不能在其他测试实例上调用它

val test = Test()
val sayHelloFunction = test::sayHello
helloWorldFunction() // same as calling test.sayHello()
上述方法不需要Kotlin反射库

要按字符串名称获取成员,没有Java的getMethod这样的特定函数,因此必须从成员列表中选择它,这是可以调用的。KCallable没有运算符fun invoke,因此您必须使用call来调用它,或者将它强制转换为特定的函数类型,在这种情况下,它将是Test->Unit

这不会列出伴随对象的成员,因为它是另一个类。为此,您必须获得同伴的课程:

Test.Companion::class.members.single { it.name == "foo" }
我不知道是否有办法通过名称获得实例绑定版本


至于为什么KClass没有方便的getMethod函数,我只能猜测,因为Kotlin类有这么多不同类型的成员属性、函数、委托、支持字段,他们可能希望限制API膨胀,并认为像single这样的内联过滤函数已经足够了。

假设您有这样的类:

class Test {
    fun sayHello() = println("Hello world")

    companion object {
        fun foo() = println("foo")
    }
}
这为您提供了一个可以使用invoke调用的函数实例,它是一个运算符函数,因此您可以像使用任何其他函数一样使用括号。如果像这样使用类名获取函数,则它不会绑定到实例。因此,在调用时将实例作为第一个参数传递。如果sayHello有额外的参数,它们将只跟随测试的第一个参数

val sayHelloFunction = Test::sayHello
val test = Test()
helloWorldFunction(test) // same as calling test.sayHello()
您还可以获得绑定到如下实例的函数引用。不能在其他测试实例上调用它

val test = Test()
val sayHelloFunction = test::sayHello
helloWorldFunction() // same as calling test.sayHello()
上述方法不需要Kotlin反射库

要按字符串名称获取成员,没有Java的getMethod这样的特定函数,因此必须从成员列表中选择它,这是可以调用的。KCallable没有运算符fun invoke,因此您必须使用call来调用它,或者将它强制转换为特定的函数类型,在这种情况下,它将是Test->Unit

这不会列出伴随对象的成员,因为它是另一个类。为此,您必须获得同伴的课程:

Test.Companion::class.members.single { it.name == "foo" }
我不知道是否有办法通过名称获得实例绑定版本


至于为什么KClass没有方便的getMethod函数,我只能猜测,因为Kotlin类有太多不同类型的成员属性、函数、委托、支持字段,所以他们可能想限制API膨胀,并觉得像single这样的内联过滤函数就足够了。

要从KClass中获取类,您只需调用它,然后转到另一个方向。

要从KClass中获取类,您只需调用它,然后转到另一个方向。

是否需要按字符串名称获取方法?否则,您可以只使用::methodName。否则,您可以使用class.members.single{it.name==theFunctionName}获取KCallable。是的,我需要按名称。顺便说一句,当我尝试以下操作时::methodName不起作用:val str:String=dsasa var kclass:kclass=str::class str.touppercase我没有完全遵循您尝试的操作,可能是因为注释格式,但是如果您想问这个问题,您可以将它编辑成问题。@Tenfour04,我完全理解!非常感谢。你应该写一个正式的答案,这样我才能奖励你:你是lambda表达式的大师。只有两个小而重要的问题,1。此语法是否将实例绑定到函数?2.members集合是否包含伴生对象的方法?是否需要按字符串名称获取方法?否则,您可以只使用::methodName。否则,您可以使用class.members.single{it.name==theFunctionName}获取KCallable。是的,我需要按名称。顺便说一句,当我尝试以下操作时::methodName不起作用:val str:String=dsasa var kclass:kclass=str::class str.touppercase我没有完全遵循您尝试的操作,可能是因为注释格式,但是如果您想问这个问题,您可以将它编辑成问题。@Tenfour04,我完全理解!非常感谢。你应该写一个正式的答案,这样我才能奖励你:你是lambda表达式的大师。J
有两个小而重要的问题,1。此语法是否将实例绑定到函数?2.成员集合是否包含同伴对象的方法?非常感谢。很好的解释。也许您可以解释为什么说:上述方法不需要Kotlin反射库。为什么第一个示例使用反射,而第二个示例不使用反射?为了减少Kotlin应用程序的编译大小,该库中提供了不太常用的反射功能。是的:在没有反射库的情况下总是可以使用的。我的意思是它只是语言的一部分,而不是像类那样需要调用函数。就像Java中的原语一样。你可以在单个lambda中放入你想要的任何东西来选择你想要的,例如。single{it.name==foo&&it.parameters.size==2}非常感谢。很好的解释。也许您可以解释为什么说:上述方法不需要Kotlin反射库。为什么第一个示例使用反射,而第二个示例不使用反射?为了减少Kotlin应用程序的编译大小,该库中提供了不太常用的反射功能。是的:在没有反射库的情况下总是可以使用的。我的意思是它只是语言的一部分,而不是像类那样需要调用函数。原语在Java中的方式。您可以在单个lambda中放入任何您想要的内容来选择您想要的内容,例如。single{it.name==foo&&it.parameters.size==2}