Kotlin函數(shù)
1.函數(shù)聲明
kotlin中的函數(shù)用fun聲明
fun test(a : Int){
}
2.中綴符號
滿足以下條件(成員函數(shù)或者擴(kuò)展函數(shù)臀防,只有一個參數(shù),使用infix關(guān)鍵詞進(jìn)行標(biāo)記)的边败,函數(shù)可以通過使用infix修飾的中綴符號調(diào)用
infix fun Int.shl(x :Int){
}
1 shl 2
3.參數(shù)&默認(rèn)參數(shù)
函數(shù)接收參數(shù) 使用(形參 :參數(shù)類型)這種方式袱衷。這點(diǎn)與java不同
kotlin函數(shù)的參數(shù)可以指定默認(rèn)值
fun test(string : String = "str",int : Int =0){
}
在調(diào)用時候,如果參數(shù)未傳入就會使用指定的默認(rèn)值
這種特性類似java中的方法重載笑窜,在調(diào)用時候如果不傳入?yún)?shù)致燥,就會直接使用默認(rèn)值。
4.命名參數(shù)
命名參數(shù)可以增加函數(shù)的可讀性排截,但是java不能使用命名參數(shù)這種方式來調(diào)用kotlin的函數(shù)
fun test(name :String = "zhangsan" ,age : Int =12){
}
test("lisi")
test("wangwu",16)
test(name = "zhaoliu",age = 18)
命名參數(shù) 就是在調(diào)用的時候使用 (形參名 = value)這種方法來傳值嫌蚤。如果參數(shù)命名比較好的話,增加代碼的可讀性
5.不帶返回值的參數(shù)
如果函數(shù)不會返回任何值断傲,那么返回值類型就是Unit脱吱。Unit是一個只有唯一值Unit的類型。這個類型可以被省略
fun test(name :String?) : Unit{
//...
}
fun test(name :String?){
//...
}
6.單表達(dá)式函數(shù)
當(dāng)函數(shù)返回的只是單個表達(dá)式的時候认罩,可以省略大括號箱蝠,并在=后面跟上表達(dá)式
fun testAdd(a: Int, b: Int) = a + b
7.變長參數(shù)
kotlin中也存在變長參數(shù) 與java中的變長參數(shù)類似 (使用vararg修飾符標(biāo)記 通常是最后一個參數(shù))
fun printVararg(vararg strs :String?){
for (str in strs){
println("str=$str")
}
}
printVararg("zhangsan","lisi","wangwu")
// public void printVararg(String... strs){
// java中的變長參數(shù)
// }
函數(shù)中只有一個參數(shù)可以被標(biāo)記為vararg。如果vararg參數(shù)不是最后一個垦垂,后面的參數(shù)需要通過命名函數(shù)進(jìn)行傳值宦搬。
調(diào)用變長參數(shù)的時候,我們可以一個一個的傳遞參數(shù)劫拗,或者使用*前綴操作符傳遞一個array當(dāng)作參數(shù)
val a = arrayListOf<String>("zhangsan", "lisi", "wangwu")
printVararg(*a)//變長參數(shù)直接傳入array
8.函數(shù)范圍
Kotlin中的函數(shù)可以在文件頂級聲明(也就是說不用創(chuàng)建一個類來持有)
除此之外间校,函數(shù)也可以定義為局部函數(shù),作為成員函數(shù)或者擴(kuò)展函數(shù)
fun test(name: String) {
var mName = name
fun test(name: String, age: Int) {
if (name == mName) {
return
}
println("name = $name,age = $age")
}
test("zhangsan",12)//調(diào)用內(nèi)部函數(shù)
}
局部函數(shù)可以訪問外部函數(shù)的局部變量
9.擴(kuò)展函數(shù)
在kotlin中页慷,擴(kuò)展函數(shù)是指可以通過在一個類上增加一個方法撇簿,該類以及其子類都可以使用。
//如果有同名同參數(shù)的成員函數(shù) 和 擴(kuò)展參數(shù)時差购,必定調(diào)用成員函數(shù)
//為什么要這么做四瘫?我們可以通過擴(kuò)展類的方法方便我們的直接調(diào)用,而不是通過定義一個工具類來調(diào)用方法
fun Context.toast(message :String,duration : Int = Toast.LENGTH_SHORT){
Toast.makeText(this,message,duration).show()
}
同樣 Kotlin也可以擴(kuò)展參數(shù)
public var TextView.text : CharSequence
get() = text
set(value) {
text = value
}
高階函數(shù)
1.高階函數(shù)就是一個能接收函數(shù)作為參數(shù)并返回一個函數(shù)的函數(shù)。
//高階函數(shù) 可以接收一個函數(shù)作為參數(shù)
fun doPrintBeforeAndAfterFunction(doSth: () -> Unit) {//其中doSth是參數(shù)名 ()里是參數(shù)欲逃,這里是沒有傳參數(shù)找蜜,Unit是返回值
println(TAG, "before do sth -->")
doSth()
println(TAG, "after do sth -->")
}
//調(diào)用 傳入一個字面函數(shù)
doPrintBeforeAndAfterFunction({ doSth() })
fun doSth() {
println("$TAG,this is a method ,i will do sth before and after this method")
}
字面函數(shù)或者函數(shù)表達(dá)式就是一個匿名函數(shù)。就是沒有聲明的函數(shù)
2.內(nèi)聯(lián)函數(shù)
高階函數(shù)會帶來一些運(yùn)行時的效率損失:每一個函數(shù)都是一個對象稳析,內(nèi)存分配(對于函數(shù)對象和類)和虛擬調(diào)用會引入運(yùn)行時間開銷洗做。
內(nèi)聯(lián)可能導(dǎo)致生成的代碼增加(內(nèi)聯(lián)在編譯器生成代碼)弓叛,但是如果我們使用得當(dāng)(不內(nèi)聯(lián)大函數(shù)),它將在性能上有所提升诚纸。
(非內(nèi)聯(lián)函數(shù)在傳入lambda表達(dá)式后會生成一個對象撰筷,并作虛擬調(diào)用 。而使用內(nèi)聯(lián)函數(shù)后在編譯器就會把內(nèi)聯(lián)函數(shù)的代碼生成到調(diào)用的位置畦徘。這樣在運(yùn)行時就不會再生成對象而是直接運(yùn)行毕籽。這樣會減少開銷但是也會增加代碼量,要慎重使用)
如果內(nèi)聯(lián)函數(shù)的某些參數(shù)不需要使用內(nèi)聯(lián)井辆,可以用noinline來修飾关筒,這樣在編譯期就不會對該參數(shù)進(jìn)行內(nèi)聯(lián)
內(nèi)聯(lián)函數(shù)使用inline關(guān)鍵字修飾
比如Kotlin標(biāo)準(zhǔn)函數(shù)with
inline fun <T> with(t: T,body :T.()->Unit){
t.body()
}
這個函數(shù)接收一個對象和一個函數(shù),它的實(shí)現(xiàn)是把接收的函數(shù)作為傳入對象的擴(kuò)展函數(shù)來使用杯缺。這樣在函數(shù)內(nèi)部就可以使用傳入對象的屬性和方法蒸播。等于擴(kuò)展了傳入對象
這個函數(shù)通常用于針對同一個對象做很多操作的時候∑妓粒可以簡化代碼
內(nèi)聯(lián)函數(shù)與普通的函數(shù)有點(diǎn)不同袍榆。一個內(nèi)聯(lián)函數(shù)會在編譯的時候被替換
掉,而不是真正的方法調(diào)用塘揣。這在一些情況下可以減少內(nèi)存分配和運(yùn)行時
開銷蜡塌。舉個例子,如果我們有一個函數(shù)勿负,只接收一個函數(shù)作為它的參數(shù)馏艾。
如果是一個普通的函數(shù),內(nèi)部會創(chuàng)建一個含有那個函數(shù)的對象奴愉。另一方
面琅摩,內(nèi)聯(lián)函數(shù)會把我們調(diào)用這個函數(shù)的地方替換掉,所以它不需要為此生
成一個內(nèi)部的對象锭硼。
//該函數(shù)可以作為模版函數(shù)房资,處理Android的版本兼容問題
inline fun supportLollipop(code : ()->Unit){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
code()
}
}
supportLollipop {
//doSth when version higher than LOLLIPOP
}
Lambda表達(dá)式
在kotlin中,lambda表達(dá)式就是一個匿名函數(shù)檀头,是Function接口的實(shí)現(xiàn)轰异。(最多接受22個參數(shù)。暑始。)表達(dá)式的寫法如下:
lambda 表達(dá)式總是被大括號括著搭独,
其參數(shù)(如果有的話)在 -> 之前聲明(參數(shù)類型可以省略),
函數(shù)體(如果存在的話)在 -> 后面廊镜。
{ string -> println("$string,lambda") }
參考資料:https://www.kotliner.cn/2017/02/13/細(xì)說%20Lambda%20表達(dá)式/
函數(shù)相關(guān)牙肝,操作符重載:https://www.kotliner.cn/2017/04/07/KotlinPrimerFunction/