1.Kotlin 變量沒(méi)有默認(rèn)值,需要初始化
var view:View //報(bào)錯(cuò),需要初始化,否則就設(shè)置為抽象的
var view:View = null //報(bào)錯(cuò),kotlin中需要做非空判斷
//怎么辦?
lateinit var view:View //lateinit關(guān)鍵字表示,我第一時(shí)間無(wú)法給他初始化,但使用的時(shí)候肯定會(huì)初始化
2.kotlin中的空安全
var name: String? = null //String?代表可以為空
//可空變量引發(fā)新的問(wèn)題
name.length //假如name設(shè)置為可空,那么調(diào)用.length,就有報(bào)空指針異常的可能,kotlin會(huì)在編譯時(shí)就報(bào)錯(cuò)
//怎么解決呢?
if(null != name) {
print(name.length)
} //還是報(bào)錯(cuò),不讓使用,原因: 多線程情況下,其他線程可能在你檢查之后把name再改成空的
//怎么解決呢?
name?.length name!!.length
- 變量需要手動(dòng)初始化,所以不初始化會(huì)標(biāo)錯(cuò)
- 變量默認(rèn)為非空,所以初始化時(shí)賦值為null也會(huì)報(bào)錯(cuò)
- 變量使用 ? 設(shè)置為可空,使用時(shí)又報(bào)錯(cuò)
所謂可空不可空,關(guān)注的是----使用時(shí)---- 這個(gè)變量在使用時(shí),是否可能為空
3.kotlin的類型推斷
Groovy: 動(dòng)態(tài)類型,是變量的類型能發(fā)生改變
var args = "你好" args = 0; 類型發(fā)生改變,但不報(bào)錯(cuò)
Kotlin: 類型推斷,根據(jù)值去推斷類型
var args = "你好" arg = 0 報(bào)錯(cuò)
4.變量的聲明,用var 和 val(只讀) 類似于java的final,但有區(qū)別
5.函數(shù)聲明方式
//如果沒(méi)有返回值,使用Unit,默認(rèn)不寫
fun test(arg1:Int,arg2:String?):String {
return "你好 "
}
6.int,float這些基本類型被Kotlin拋棄,在語(yǔ)言層面,Kotlin已經(jīng)沒(méi)有基本類型了,使用Int,Float
7.getter,setter
val user = UserData()
user.name = "Marry" 不管set,還是get,都直接 .變量名稱
println(user.name)
class UserData : IMainActiity{
var name:String = "Mike"
get() {
return field+"--nb"
}
set(value) {
field = "Cute"+value
}
}
- is as 關(guān)鍵字
//利用多態(tài)的特性,創(chuàng)建的對(duì)象可以被對(duì)象事件的接口引用,但如果調(diào)用的方法不是接口中的方法,就需要判斷了
//java: a instanceof b
//kotlin: a is b a as b
java中
Activity activity = new NewActivity();
if (activity instanceof NewActivity) {
((NewActivity) activity).action();
}
kotlin中
var iuser:IUser = UserData()
if(user is UserData) {
user.sleep()
}
//使用as進(jìn)行強(qiáng)轉(zhuǎn),而不進(jìn)行判斷
Exception in thread "main" kotlin.TypeCastException: null cannot be cast to non-null type com.myself.learningkotlin.UserData
(user as UserData).sleep() --這種寫法如果強(qiáng)轉(zhuǎn)類型操作是正確的當(dāng)然沒(méi)問(wèn)題唁奢,但如果強(qiáng)轉(zhuǎn)成一個(gè)錯(cuò)誤的類型,程序就會(huì)拋出一個(gè)異常。
(user as? UserData)?.sleep() --如果強(qiáng)轉(zhuǎn)成功就執(zhí)行之后的調(diào)用魂仍,如果強(qiáng)轉(zhuǎn)不成功就不執(zhí)行。
(user as? UserData?)?.sleep()
9.open 關(guān)鍵字
kotlin中的類默認(rèn)是final修飾的,不可被繼承,如果想作為父類被繼承,就應(yīng)該使用open關(guān)鍵字
不想被繼承就使用final關(guān)鍵字
open class MainActivity {
}
10.override 的不同
- Java 里面 @Override 是注解的形式愚战。
- Kotlin 里的 override 變成了關(guān)鍵字春缕。
- Kotlin 省略了 protected 關(guān)鍵字,也就是說(shuō)忌栅,Kotlin 里的 override 函數(shù)的可見(jiàn)性是繼承自父類的。
open 沒(méi)有父類到子類的遺傳性 父類使用open修飾,子類默認(rèn)還是final修飾
而剛才說(shuō)到的 override 是有遺傳性的 父類有個(gè)override fun eat() 子類也會(huì)默認(rèn)override fun eat() ,想要停掉這種遺傳,前面使用final
open class MainActivity : AppCompatActivity() {
// ??加了 final 關(guān)鍵字曲稼,作用和 Java 里面一樣索绪,關(guān)閉了 override 的遺傳性
final override fun onCreate(savedInstanceState: Bundle?) {
...
}
}
11.創(chuàng)建一個(gè)新的對(duì)象
java中
User user = new User();
kotlin 中
var user:User = User()
12.不定量參數(shù)
使用關(guān)鍵字vararg
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts 是一個(gè) Array
result.add(t)
return result
}
注意事項(xiàng):
- 一個(gè)函數(shù)的所有參數(shù)中,只能有一個(gè)參數(shù)使用
vararg
修飾
在java中不定量參數(shù)必須是參數(shù)的最后一個(gè),但kotlin中不用這樣,如果后面還有參數(shù),需要使用具名參數(shù)來(lái)表示.如果是一個(gè)類參數(shù),可以使用lambda來(lái)表示
fun main(args: Array<String>) {
fruit("apple", "banana", address = "Minhang")
}
fun fruit(vararg fruits: String, address: String) {
for (fruit in fruits) {
println("fruit:$fruit, from address: $addr")
}
}
// Log
fruit:apple, from address: Minhang
fruit:banana, from address: Minhang
- 我們調(diào)用vararg函數(shù)時(shí),我們可以一個(gè)接一個(gè)地傳參贫悄,例如 asList(1, 2, 3)瑞驱,或者,如果我們已經(jīng)有一個(gè)數(shù)組并希望將其內(nèi)容傳給該函數(shù)窄坦,我們使用伸展spread操作符(在數(shù)組前面加 *):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)