十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
最基本的反射功能是獲取 Kotlin 類的運(yùn)行時(shí)引用。要獲取對(duì)靜態(tài)已知的 Kotlin 類的引用,可以使用 類字面值 語法
請注意,Kotlin 類引用與 Java 類引用不同。要獲得 Java 類引用,請?jiān)?KClass 實(shí)例上使用 .java 屬性
綁定的類引用(自 1.1 起)
通過使用對(duì)象作為接收者,可以用相同的 ::class 語法獲取指定對(duì)象的類的引用
val widget: Widget = ...... assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }你可以獲取對(duì)象的精確類的引用,例如 GoodWidget 或 BadWidget,盡管接收者表達(dá)式的類型是 Widget
可調(diào)用引用
函數(shù)屬性以及構(gòu)造函數(shù)的引用,除了作為自省程序結(jié)構(gòu)外, 還可以用于調(diào)用或者用作函數(shù)類型的實(shí)例 。
所有可調(diào)用引用的公共超類型是 KCallable
函數(shù)引用
當(dāng)我們有一個(gè)具名函數(shù)聲明如下
fun isOdd(x: Int) = x % 2 != 0我們可以很容易地直接調(diào)用它( isOdd(5) ),但是我們也可以將其作為一個(gè)函數(shù)類型的值,例如將其傳給另一個(gè)函數(shù)。為此,我們使用 :: 操作符
val numbers = listOf(1, 2, 3) println(numbers.filter(::isOdd))函數(shù)引用屬于 KFunction
當(dāng)上下文中已知函數(shù)期望的類型時(shí),:: 可以用于重載函數(shù)。例如
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)或者,你可以通過將方法引用存儲(chǔ)在具有顯式指定類型的變量中來提供必要的上下文
val predicate: (String) -> Boolean = ::isOdd // 引用到 isOdd(x: String)如果我們需要使用類的成員函數(shù)或擴(kuò)展函數(shù),它需要是限定的,例如 String::toCharArray 。
請注意,即使以擴(kuò)展函數(shù)的引用初始化一個(gè)變量,其推斷出的函數(shù)類型也會(huì)沒有接收者(它會(huì)有一個(gè)接受接收者 對(duì)象的額外參數(shù))。如需改為帶有接收者的函數(shù)類型,請明確指定其類型
val isEmptyStringList: List示例:函數(shù)組合
考慮以下函數(shù)
fun compose(f: (B) -> C, g: (A) -> B): (A) -> C { return { x -> f(g(x)) } }它返回一個(gè)傳給它的兩個(gè)函數(shù)的組合:compose(f, g) = f(g(*)) ?,F(xiàn)在,你可以將其應(yīng)用于可調(diào)用引用
fun length(s: String) = s.length val oddLength = compose(::isOdd, ::length) val strings = listOf("a", "ab", "abc") println(strings.filter(oddLength))屬性引用
要把屬性作為 Kotlin中 的一等對(duì)象來訪問,我們也可以使用 :: 運(yùn)算符
val x = 1 fun main() { println(::x.get()) println(::x.name) }表達(dá)式 ::x 求值為 KProperty
對(duì)于可變屬性,例如 var y = 1 ,::y 返回 KMutableProperty
屬性引用可以用在預(yù)期具有單個(gè)泛型參數(shù)的函數(shù)的地方
val strs = listOf("a", "bc", "def") println(strs.map(String::length))要訪問屬于類的成員的屬性,我們這樣限定它
class A(val p: Int) val prop = A::p println(prop.get(A(1)))對(duì)于擴(kuò)展屬性
val String.lastChar: Char get() = this[length - 1] fun main() { println(String::lastChar.get("abc")) }與 Java 反射的互操作性
在 JVM 平臺(tái)上,標(biāo)準(zhǔn)庫包含反射類的擴(kuò)展,它提供了與 Java 反射對(duì)象之間映射(參? kotlin.reflect.jvm包)。例如,要查找一個(gè)用作 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" }要獲得對(duì)應(yīng)于 Java 類的 Kotlin 類,請使用 .kotlin 擴(kuò)展屬性
fun getKClass(o: Any): KClass構(gòu)造函數(shù)引用
構(gòu)造函數(shù)可以像方法和屬性那樣引用。他們可以用于期待這樣的函數(shù)類型對(duì)象的任何地方:它與該構(gòu)造函數(shù)接 受相同參數(shù)并且返回相應(yīng)類型的對(duì)象。通過使用 :: 操作符并添加類名來引用構(gòu)造函數(shù)??紤]下面的函數(shù),它 期待一個(gè)無參并返回 Foo 類型的函數(shù)參數(shù)
class Foo fun function(factory: () -> Foo) { val x: Foo = factory() }使用 ::Foo ,類 Foo 的零參數(shù)構(gòu)造函數(shù),我們可以這樣簡單地調(diào)用它
function(::Foo)構(gòu)造函數(shù)的可調(diào)用引用的類型也是KFunction
綁定的函數(shù)與屬性引用(自 1.1 起)
你可以引用特定對(duì)象的實(shí)例方法
val numberRegex = "\d+".toRegex() println(numberRegex.matches("29")) val isNumber = numberRegex::matches println(isNumber("29"))取代直接調(diào)用方法 matches 的是我們存儲(chǔ)其引用。這樣的引用會(huì)綁定到其接收者上。它可以直接調(diào)用(如上 例所示)或者用于任何期待一個(gè)函數(shù)類型表達(dá)式的時(shí)候
val numberRegex = "\d+".toRegex() val strings = listOf("abc", "124", "a70") println(strings.filter(numberRegex::matches))比較綁定的類型和相應(yīng)的未綁定類型的引用。綁定的可調(diào)用引用有其接收者“附加”到其上,因此接收者的類型 不再是參數(shù)
val isNumber: (CharSequence) -> Boolean = numberRegex::matches val matches: (Regex, CharSequence) -> Boolean = Regex::matches屬性引用也可以綁定
val prop = "abc"::length println(prop.get())自 Kotlin 1.2 起,無需顯式指定 this 作為接收者:this::foo 與 ::foo 是等價(jià)的
綁定的構(gòu)造函數(shù)引用
inner 類的構(gòu)造函數(shù)的綁定的可調(diào)用引用可通過提供外部類的實(shí)例來獲得
class Outer { inner class Inner } val o = Outer() val boundInnerCtor = o::Inner