1.除非一個變量需要被修改,否則就是使用 val 聲明
2.函數(shù)聲明
fun methodNmae(param : String, ...): String {
return ""
}
3.當(dāng)函數(shù)只用一行代碼時,可用 = 連接, = 表示 返回值的意思
如:fun largerNumber(num1 : Int , num2 : Int) = max(num1,num2)
4.if 、when 語句 都有返回值
val str = ""
val v2 = when (str) {
"" -> 1
"1" -> 2
else -> 3
}
fun getNum(str : String)= when {
str.startsWith("") -> 1
str == "123" -> 2
str is String -> 4
else -> 3
}
5.
is 相當(dāng)于 instanceof
as 相當(dāng)于 強轉(zhuǎn)
6.for in
for( i in 0..10){
}
0..10 0.rangeTo(10) 包含 0 和 10 相當(dāng)于 [0,10]
0 until 10 包含 0 不含 10 相當(dāng)于 [0,10)
downTo 表示 降序
step 表示 步
7.File 通常是用于編寫Kotlin 頂層函數(shù) 和 擴展函數(shù)的
8.Kotlin中的 非抽象類 默認是不可被繼承的 open
open class Person(){
}
class Student() : Person(){
}
沒有參數(shù)時,Student() 的 () 可以省略
Person() 的 () 不可以省略,表示使用父類的 無參構(gòu)造函數(shù)
主構(gòu)造函數(shù),次構(gòu)造函數(shù)
每個類都會默認有一個無參的主構(gòu)造函數(shù)
子類中的構(gòu)造函數(shù)必須父類中的構(gòu)造函數(shù)
當(dāng)一個類既有主構(gòu)造函數(shù),又有次構(gòu)造函數(shù)的時候,次構(gòu)造函數(shù)必須直接和間接調(diào)用主構(gòu)造函數(shù)
父類主構(gòu)造函數(shù)總聲明為 val/var 的參數(shù)將自動生成為該類的字段,子類中不能再聲明為 val/var
主構(gòu)造函數(shù):沒有函數(shù)體,直接定義在類名的后面()
次構(gòu)造函數(shù):通過 constructor 關(guān)鍵字定義
constructor(name : String) : this.() { }
init{ } 結(jié)構(gòu)體 用來 編寫主構(gòu)造函數(shù)的邏輯
9.接口 interface Inter{} 沒有構(gòu)造函數(shù)
支持函數(shù)默認實現(xiàn)
10.kotlin 默認修飾符 public
修飾符 java kotlin
public 所有類可見
private 當(dāng)前類可見
protected 當(dāng)前類、子類
同一個包路徑下
default 同一個包路徑下
internal 同一個模塊
11.數(shù)據(jù)類 data class className(val name : String,...)
單例類 object className{}
12.Lambda 就是一小段可以作為參數(shù)傳遞的代碼
{param : paramType,... -> 函數(shù)體}//和oc的block比較像
最后一行代碼會自動作為lambda表達式的返回值
當(dāng)lambda作為函數(shù)參數(shù)的最后一個時,可以將Lambda表達式移到函數(shù)表達式外面
如果是函數(shù)唯一參數(shù)的話,可以省略函數(shù)的()
val value = 函數(shù){Lambda}
當(dāng)Lambda 只有一個參數(shù)時 可以直接用 it 代替 參數(shù)使用
13.
map 函數(shù) 對集合中的元素進行映射
filter 過濾數(shù)據(jù)
any 判斷集合中是否至少有一個元素滿足指定條件
all 所以元素
14.kotlin調(diào)用java 使用函數(shù)式api
該方法只接受一個參數(shù):java單抽象方法接口(接口中只有一個待實現(xiàn)方法)參數(shù)
15.匿名函數(shù)使用 object 關(guān)鍵字聲明
16.空指針檢測
? 可空類型 必須用? 標(biāo)明
操作符
?. 對象為空時,什么都不做,不為空時再執(zhí)行 ?. 后的代碼
?: val v = a ?: b a不為空 返回 a 為空則返回 b
!! 非空斷言,不對對象進行指針檢測
17.
let{ it -> } 函數(shù) {}中 參數(shù)(it) 為 調(diào)用者 對象,let函數(shù)返回值 block 的值
在let中多條語句使用全局變量時是安全的,不擔(dān)心其他線程修改
可以和 ?. 一起用 進行輔助判空處理 obj?.let{ it -> }
with(obj,{}) 函數(shù) {}中提供 obj 對象的 上下文,Lambda 最后一句作為返回值
連續(xù)調(diào)用同一個對象的多個方法時可用
run{} 函數(shù) obj.run{} {}中提供 obj 對象的 上下文,Lambda 最后一句作為返回值
apply{} 函數(shù) obj.apply{} {}中提供 obj 對象的 上下文,apply函數(shù)返回 調(diào)用者對象 obj
18.字符串內(nèi)嵌表達式 ${}
19.companion object (名字為Companion?默認沒有,可指定){ } 伴生對象,每個類只能有一個伴生類
真正的靜態(tài)方法 需要在方法上 @JvmStatic ,只能加在單例類 或者 companion object的方法上
頂層方法 被kotlin編譯器編譯成靜態(tài)方法
20.密封類 sealed class 可被繼承,本身及所有子類都只能定義在同一個文件的頂層位置,不能嵌套在其他類中
sealed class Result
class Success(val msg : String) : Result()
class Failure(val error : Exception) : Result()
可結(jié)合 when/if 條件語句使用
21.高階函數(shù) 一個函數(shù)作為另一個函數(shù)的參數(shù) 或者 返回值類型
(param , ...)-> Unit
::method 函數(shù)引用
className.() -> String 表示 將 () -> String 函數(shù)定義在 className 這個類中
22.內(nèi)聯(lián)函數(shù) inline ,在編譯時,會將inline函數(shù)替換到調(diào)用的地方
Lambda表達式 在底層都會轉(zhuǎn)換成匿名類(Function接口,kotlin內(nèi)置接口,包含一個待實現(xiàn)的invoke函數(shù))的方式實現(xiàn),
每次調(diào)用都會產(chǎn)生一個匿名類對象,造成性能和內(nèi)存的開銷
函數(shù)加上 inline 編譯時會將 函數(shù)的所有函數(shù)類型參數(shù)進行內(nèi)聯(lián), 使用 noinline 聲明不需要內(nèi)聯(lián)的 函數(shù)型參數(shù)
inline 的函數(shù)型參數(shù)(因為在編譯時會替換到使用位置,它沒有參數(shù)屬性)只能傳給 另外一個 inline函數(shù),
非內(nèi)聯(lián)函數(shù)參數(shù)(是真正的參數(shù))可以自由傳遞
inline 函數(shù)可以使用return 進行函數(shù)返回(返回最外層函數(shù),相當(dāng)于在調(diào)用函數(shù)的地方 return),
非內(nèi)聯(lián)函數(shù)只能進行局部返回(返回Lambda 函數(shù)外面) return@當(dāng)前函數(shù)名稱 且不再執(zhí)行Lambda中后面的語句
如果在inline高階函數(shù)中,創(chuàng)建了另外的Lambda或者匿名類的實現(xiàn),并在這些實現(xiàn)中調(diào)用函數(shù)型參數(shù),會報錯
(非inline函數(shù)沒問題,應(yīng)為inline函數(shù)允許 return)
使用 crossline關(guān)鍵字修飾 函數(shù)型參數(shù),表示在inline函數(shù)的Lambda表達式中不適用return,可以局部返回
23.可變參數(shù) vararg ( var array )
24.泛型 上界限 Any?
25.類委托,屬性委托 by
委托,設(shè)計模式,操作對象不想自己處理某個邏輯,而是把工作委托給另外一個對象去處理
類委托:將一個類的具體實現(xiàn)委托給另外一個類去完成
class MySet<T> (val helperSet : HashSet<T>) : Set<T> by helperSet{
對某個方法重寫
新的方法
}
屬性委托:將一個屬性/字段 委托給另一個類去完成
var p by Delegate()
將p 的具體實現(xiàn)委托給 Delegate() 類實現(xiàn),獲取p時,調(diào)用 Delegate 的 getValue() 方法,賦值時調(diào)用 setValue()
class MyLazy<T>(val bolck: () -> T) {
var value: Any? = null
operator fun getValue(any: Any?, prop: KProperty<*>): T {
if (value == null) {
value = bolck()
}
return value as T
}
}
委托類中的 getVale/setValue 方法必須使用 operator 聲明
方法中第一個參數(shù):表示委托可以在哪個類中使用
第二個參數(shù):kotlin中的屬性操作類,可以獲取各種屬性相關(guān)的值
<*>星投影 泛型 表示不關(guān)心泛型的具體類型,類似java <?>
by lazy 懶加載 lazy 是一個頂層高階函數(shù)
lateinit 延遲初始化
26.infix 中綴表達式 to 不是關(guān)鍵字
A to B 實為 A.to(B)
使用 infix 聲明函數(shù),不能定義頂層函數(shù),只能是某個類的成員函數(shù),并且函數(shù)有且只有1個參數(shù)
27.運算符重載 operator
28.
Class<T> A : B
協(xié)變 out 生產(chǎn)者(我從生產(chǎn)者這里拿東西) 只能讀取數(shù)據(jù) <? extend T>
Class<A> 相當(dāng)于 Class<B> 的子類型 Class 在泛型T上是協(xié)變 如 List<T>
class Data<out T>(val data : T?) 此時的構(gòu)造函數(shù)上的 T 因為使用 val 修飾 可以 出現(xiàn)在 in 位置
或者 private var data : T? 保證這個泛型 T 對應(yīng)于外部是不可修改的 就可以
逆變 in 消費者(我給消費者添加?xùn)|西) 只能接受數(shù)據(jù) <? super T>
Class<B> 相當(dāng)于 Class<A> 的子類型 Class 在泛型T上是逆變 如 Comparable<T>
PECS PEO-CSI
可以 聲明處 型變
使用 @UnsafeVariance 注解
29.泛型的實化
java的泛型是通過類型擦除機制來實現(xiàn),泛型只在編譯時起作用,JVM識別不出來泛型類型
由于inline函數(shù) 會直接替換到使用它的位置,這樣就不存在泛型擦除的問題了
inline fun <reified T> getGenericType() = T::class.java
30.協(xié)成 在單線程下模擬多線程的效果,通過掛起、恢復(fù)來調(diào)度
Global.launch{} 可以創(chuàng)建一個協(xié)成作用域,創(chuàng)建的是頂層協(xié)成,該協(xié)成當(dāng)應(yīng)用程序結(jié)束時也會一起結(jié)束
deley(1000) 函數(shù)可以讓當(dāng)前協(xié)成延遲指定時間后再運行,非阻塞式掛起函數(shù),只會掛起當(dāng)前協(xié)成,不影響其他協(xié)成
只能在協(xié)成作用域或掛起函數(shù)中調(diào)用
runBlocking{} 可以創(chuàng)建一個協(xié)成作用域,當(dāng)該協(xié)成內(nèi)的代碼,或子協(xié)成沒有執(zhí)行完之前,會阻塞當(dāng)前線程(不建議正式環(huán)境使用)
launch{} 必須在協(xié)成作用域中調(diào)用,會創(chuàng)建一個子協(xié)成
子協(xié)成特點:當(dāng)外部作用域的協(xié)成結(jié)束了,該作用域下的多有子協(xié)成也會一同結(jié)束
suspend 關(guān)鍵字 修飾的函數(shù) 會被聲明成 掛起函數(shù) 但是 不提供 協(xié)成作用域,掛起函數(shù)之間可以相互調(diào)用
coroutineScope{} 函數(shù)是一個 掛起函數(shù) ,會繼承外部的協(xié)成作用域,并創(chuàng)建一個子作用域,
保證作用域中的代碼和子協(xié)成在全部執(zhí)行完之前,阻塞當(dāng)前 協(xié)成
取消協(xié)成
Global.launch{},luanch{} 函數(shù)會返回 一個 Job 對象 調(diào)用 job.cancel() 取消協(xié)成
常用用法:先創(chuàng)建Job對象,把job對象傳入 CoroutineScope() 函數(shù)中 獲取CoroutineScope對象 調(diào)用對象的launch創(chuàng)建協(xié)成
這樣創(chuàng)建的協(xié)成都會關(guān)聯(lián)到j(luò)ob對象的作用域下 調(diào)用一次 cancel() 取消該作用域中全部協(xié)成
val job = Job()
val scope = CoroutineScope(job)
scope.launch{}
job.cancel()
async{} 函數(shù)可以創(chuàng)建一個協(xié)成并返回 Deferred 對象,調(diào)用Deferred對象await()獲取它的執(zhí)行結(jié)果
須在協(xié)成作用域中調(diào)用
val v = async{}.await() 這樣調(diào)用 async中代碼會立即執(zhí)行,
但是如果代碼塊中代碼未執(zhí)行完畢,await()會阻塞當(dāng)前協(xié)成,直到獲取到結(jié)果
可修改為 val deferred = async{}
...
在協(xié)成最后調(diào)用 deferred.await() 多個協(xié)成可同時執(zhí)行
withContext(指定線程參數(shù)) 函數(shù) 相當(dāng)于 async{}.await()
Dispathcers.Defult 默認低并發(fā)線程
IO 高并發(fā)線程
Main Android中主線程
suspendCoroutine{ continuation -> } 在協(xié)成作用域或掛起函數(shù)中調(diào)用
作用:將當(dāng)前協(xié)成掛起,在一個普通線程中執(zhí)行Lambda中代碼,Lambda 參數(shù) 為對象 continuation,
通過調(diào)用 continuation.resume() 或 continuation.resumeWithException() 恢復(fù)協(xié)成
liveData(){} 函數(shù)是 lifecycle-livedata-ktx 庫提供的,可以自動構(gòu)建并返回一個LiveData對象,
并在它的代碼塊中提供一個掛起函數(shù)的上下文
可以通過 kotlin 內(nèi)置 Result.success()/.failure()包裝數(shù)據(jù)
通過emit(result)將包裝的數(shù)據(jù)返回
Kotlin 中 雙冒號操作符 表示把一個方法當(dāng)做一個參數(shù),傳遞到另一個方法中進行使用,通俗的來講就是引用一個方法
引用的方法參數(shù)必須和引用方法的方法參數(shù)一致,一致性
https://blog.csdn.net/weixin_34174422/article/details/88012921?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control
//const 必須修飾val
//const 只允許在top-level級別和object中聲明
//const val 可見性為public final static,可以直接訪問。
//val 可見性為private final static,并且val 會生成方法getNormalObject(),通過方法調(diào)用訪問。