Kotlin-反射看這篇就夠了

在這裏插入圖片描述

前言


獲取靜態已知Kotlin類的引用

使用::class

val c = MyClass::class

若要獲得 Java 類引用, 需在 KClass 實例上使用 .java 屬性

val c = MyClass::class
c.java

通過已有的對象獲取類的引用

也是用::class獲取

val widget: Widget = ……
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }

獲取函數引用

還是使用 :: 操作符

範例
fun isOdd(x: Int) = x % 2 != 0

fun main() {
    val numbers = listOf(1, 2, 3)
    isOdd(4) //這是函數調用
    println(numbers.filter(::isOdd)) //這裏的::isOdd是函數引用
}

::isOdd 是函數類型爲 (Int) -> Boolean 的一個值

::可用於重載函數

重載函數還是::

這個範例定義了兩個isOdd
fun main() {
    fun isOdd(x: Int) = x % 2 != 0
    fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove"

    val numbers = listOf(1, 2, 3)
    println(numbers.filter(::isOdd)) // 引用到 isOdd(x: Int)
    println(isOdd("dd")) // 引用到 isOdd(x: Int)
}

倒數兩行,可以自動進行重載

獲取到的函數引用

就相當於一個fun
可以通過val myMethod: (String) -> Boolean = ::isOdd 進行賦值


獲取屬性引用

這也是使用 ::

範例
val x = 1

fun main() {
    println(::x.get())
    println(::x.name) 
}

若函數不需要參數

可以這樣用
fun main() {
    val strs = listOf("a", "bc", "def")
    println(strs.map(String::length))
}

獲取類的成員屬性

fun main() {
    class A(val p: Int)
    val prop = A::p
    println(prop.get(A(1)))
}

支持擴展屬性

val String.lastChar: Char
    get() = this[length - 1]

fun main() {
    println(String::lastChar.get("abc"))
}

kotlin轉換爲java的反射引用

需要用到kotlin.reflect.jvm 包

範例

查找一個用作 Kotlin 屬性 getter 的 幕後字段或 Java方法

import kotlin.reflect.jvm.*

class A(val p: Int)

fun main() {
    println(A::p.javaGetter) // 輸出 "public final int A.getP()"
    println(A::p.javaField)  // 輸出 "private final int A.p"
}

java轉kotlin的反射引用

使用 .kotlin 擴展屬性

fun getKClass(o: Any): KClass<Any> = o.javaClass.kotlin

是不是很方便


引用構造函數

通過使用 :: 操作符並添加類名來引用

範例
class Foo

fun function(factory: () -> Foo) {
    val x: Foo = factory()
    println("111" + x)
}

fun main() {
    function(::Foo)
}

這裏有個class和一個function,() -> Foo是零參的lambda寫法,
向function傳入這個Foo的實例,使用::Foo可以直接引用構造函數
factory獲取引用後,methodName後➕(),進行實例化

輸出:

111Foo@63961c42


保存 函數與屬性的引用

範例

fun main() {
    val numberRegex = "\\d+".toRegex()
    println(numberRegex.matches("29"))

    val isNumber = numberRegex::matches
    println(isNumber("29"))
}

numberRegex::matches被保存到了isNumber上
這裏就相當於是一個fun
這是js中的一個寫法,fun也可以當變量一樣隨意保存


保存 類的內部類

inner 類的構造函數 可以被保存起來

class Outer {
    inner class Inner
}

val o = Outer()
val boundInnerCtor = o::Inner

小結

反射,哪哪都是::操作符,然後各種搭配就行了。
回想一下,java的反射,那可是厚厚厚厚厚厚厚厚厚厚厚的代碼。

::操作符的設計思路是,::指向哪,就獲取 對應的引用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章