簡體   English   中英

如何通過反射獲取屬性的值

[英]How do I get the value of a property with reflection

我想使用帶有注釋的所有屬性的值。 在大多數情況下,我的代碼都能正常工作,我會獲取所有屬性,而僅接受那些具有該批注的屬性。

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(...)get期望Nothing作為參數。 getter 調用it.call(target)確實可以,但是它看起來不對,因為有一個我不知道如何調用的實際get

那么獲得屬性值的正確方法是什么?

問題歸結為以下事實: 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適用於該類型, 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 我還沒有找到像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))
            }
}

我們知道這不會遇到上述問題,因為在兩種情況下我們都傳遞相同的對象。 從調用者的角度來看,這看起來也更好,假設有一個,這可能值得移植。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM