KClass
kt 中 Classs 類。其對應的是
java.lang.Class
。
下面所使用的 Test 類定義如下:
class Test {
var name: String = ""
fun test(sex: String, age: Int) = "$sex+$age"
}
-
通過
MyClass::class
獲取指定類對應的 KClass 對象。就像在 java 中通過MyClass.class
獲取指定類的 Class 對象一樣。fun main(args: Array<String>) { val t = Test() val clazz:KClass<Test> = Test::class // 返回一個 KClass 對象 }
-
通過
對象.javaClass.kotlin
獲取指定實例對應的 KClass 實例。其中對象.javaClass
可以獲取指定類的 java Class 實例。fun main(args: Array<String>) { val t = Test() println(t.javaClass is Class) // true }
-
KClass 與 Class 轉換:
對象.javaClass
得到 Class 對象,再.kotlin
得到 KClass 對象類名::class
得到 KClass 對象,再.java
得到 Class 對象。對象::class
得到 KClass 對象,再.java
得到 Class 對象。
屬性
KClass 屬性如下:
屬性 | 含義 |
---|---|
memberProperties | 所有屬性,含從父類中繼承的 |
annotations | 獲取元素上的所有注解。定義于 KAnnotatedElement 中 |
createInstance() | 方法。通過 KClass 創建一個實例 |
objectInstance | 如果類是單例的,則存儲其唯一實例。否則為空 |
object Test {
val name = "naan"
fun test() = println("tesss")
}
則 Test::class.objectInstance
其不為空,如果將 object 換成 class ,則值為空
KCallback 與 KFunction,KProperty
KCallback 是函數和屬性的超接口。其內部定義有 call 方法,調用該方法就相當于調用函數或者屬性的 getter ;KFunction 是 KCallback 的子類,它是函數的接口;KProperty 是 KCallback 的子類,它是屬性的接口。
屬性 | 含義 |
---|---|
name | 獲取方法或屬性名 |
parameters | 參數列表 |
三者接收的第一個參數均為執行該方法所需要的對象。就像 java 中執行某個反射方法時,需要為該方法指定一個執行對象。
KFunction 的泛型說明:除最后一個泛型外,其余的均為調用其 invoke 方法時需要傳遞參數類型,最后一個泛型為 invoke 方法返回值類型。也即對應方法的參數類型列表和返回值類型。
使用 成員引用函數時,返回的是一個 KFunction 實例。調用其 invoke 就相當于執行該方法:
-
使用 成員引用屬性時,返回的是一個 KProperty 實例。調用其
get
相當于調用該實例的 getter 方法:KProperty KProperty 泛型說明:第一個參數表示接收者類型,第二個參數表示屬性類型。
對于 var 修飾的變量,通過 KProperty 定義 set 方法修改其值。但對不可變變量,沒有 set 方法。
parameters 返回的參數列表中,第一個參數為 receiver,表示執行當前方法的實例。
繼承關系
因為所有的聲明都可以被注解(KAnnotatedElement 類的作用),所以 KClasss,KCallback,KParameter 都繼承于 KAnnotatedElement。
KProperty 只有 get 方法,用于 val 聲明的變量
KMutableProperty 有 set 方法,用于 var 聲明的變更。
兩者內部有 getter/setter 接口,用于獲取相應屬性的 getter/setter 方法。getter/setter 接口都繼承于 KFunction,因此可以把他們當作函數調用。
fun main(args: Array<String>) {
val test = Test::name
val t = Test()
println(test.getter.invoke(t))
test.setter.invoke(t,"yyy")
println(test.getter.invoke(t))
}
構造函數
通過
KClass#constructors
可以獲取所有的構造函數。
構造函數也是函數,因此每一個構造函數都是 KFunction 的子類。故而可以調用 call 方法創建實例
fun main(args: Array<String>) {
val kclzzz = Test::class
val t = kclzzz.constructors
t.forEach {
val i = it.call("name", 20)
println(i)
}
}
data class Test(val name: String, var age: Int = 10)
但 call 方法不支持默認參數,即上面創建實例時,即使 Test 類中 age 已經指定了默認值 10 ,調用 call() 時也必須傳入一個對應的實參。
callBy
callBy 定義在 KCallback 類中。
與 call() 方法相比,它接收一個 map —— map 存儲了方法形參與其實參之間的對應關系。
- 如果 map 缺少形參,則該形參會使用默認值,如果有默認值的話
2.形參的順序不必和方法中一樣
- map 中值的類型需要跟構造方法中參數類型一致。
KParameter
方法參數
name 表示參數名
type 表示參數類型
isOptional 表示該參數是否有默認值。true 表示有默認值,false 沒有。