我如何通过反思来获得物业的价值?

我想使用具有一些注释的所有属性的值。 在大多数情况下,我的代码工作,我得到所有的属性,只拿那些注释。

private inline fun <reified A : Annotation> (target: Any) { target::class.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { // How do I get the value here? } } 

我想使用it.get(...)但期望一个Nothing作为参数。 getter 。 调用它it.call(target)确实有效,但是看起来不对,因为有一个我不知道如何调用的调用。

那么获取属性值的正确方法是什么?

问题归结为T::class给你一个KClass<T>的事实,而t::class给你一个KClass<out T> 。 考虑以下几点:

 class Foo { val foo = 2 val bar = 3 } fun f() { val any: Any = Foo() any::class.memberProperties.forEach { println(it.get(2)) // Oops } } 

这本质上会尝试访问2.foo2.bar ,但是它不被允许,因为在谨慎的方面get错误,而不是允许Any类型的参数。 看来做t.javaClass.kotlin会产生一个KClass<T> ,但是。 如上所述滥用它会导致IllegalArgumentException

您可以通过提供编译时保证KClass将用于类型,而不是别的:

 private inline fun <reified A : Annotation, reified T : Any> foo(target: T) { T::class.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { println(it.get(target)) } } 

不幸的是,我不知道在从target推导出T A时候是否可以指定A 我还没有找到一种方式来调用它像foo<Attr, Bar>(bar)

或者,你可以通过javaClass ,虽然我敢打赌,它不太便携:

 private inline fun <reified A : Annotation> foo(target: Any) { target.javaClass.kotlin.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { println(it.get(target)) } } 

我们知道这不会遇到上述问题,因为我们在两种情况下都传递相同的对象。 这也看起来更好的来电方,这可能是值得的便携性打击,假设有一个。