前言
獲取靜態已知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的反射,那可是厚厚厚厚厚厚厚厚厚厚厚的代碼。
::操作符的設計思路是,::指向哪,就獲取 對應的引用