本文參考Kotlin中文官網(wǎng)蓄坏,官網(wǎng)寫的很詳細(xì),是很好的入門參考資料。這篇文章主要是作為對官方文檔的整理勃黍,不對原理做過多解釋踱蛀,方便新手快速入門。需要注意的是馋辈,你需要有java基礎(chǔ)抚芦。
一、Kotlin是什么
Kotlin和java一樣,是一門編程語言叉抡,運(yùn)行在JVM之上尔崔,都需要經(jīng)過編碼——編譯——執(zhí)行的過程,不同的是java代碼編譯使用的是javac編譯器褥民,而kotlin代碼使用的是kotlinc編譯器季春。語言沒有高低之分,只有使用場景和特性的區(qū)別消返。
二载弄、Kotlin能做什么
kotlin完整包含java特性,所以java能做的kotlin都能做撵颊,比如服務(wù)器宇攻,Android開發(fā)。
三倡勇、實(shí)踐
1逞刷、創(chuàng)建一個類
class MyClass {
}
這樣聲明的類默認(rèn)是final的,無法被繼承译隘,要想開放繼承亲桥,使用open
修飾符
open class MyClass {
}
kotlin沒有new
關(guān)鍵字,創(chuàng)建對象直接使用 類名(參數(shù))
的格式
val myClass = MyClass()
1.1固耘、構(gòu)造函數(shù)
java中的構(gòu)造函數(shù)
public class MyClass {
// 無參構(gòu)造器题篷,默認(rèn)。如果顯式寫出來厅目,則會被帶參構(gòu)造器覆蓋
public MyClass() {
}
// 帶參構(gòu)造器
public MyClass(String s) {
}
}
kotlin中一個類可以有一個主構(gòu)造函數(shù)和一個或者多個次構(gòu)造函數(shù)番枚。如果主構(gòu)造函數(shù)沒有任何注解和可見性修飾符,則可省略constructor
關(guān)鍵字
// 主構(gòu)造函數(shù)
class MyClass constructor() {
}
// 次構(gòu)造函數(shù)
class MyClass {
constructor() {
}
}
// 沒有注解和修飾符的著構(gòu)造函數(shù)
class MyClass() {
}
如果有注解或者可見性修飾符损敷,則constructor
關(guān)鍵字不能省略葫笼,且這些注解和修飾符在它前面
// 有注解和修飾符的主構(gòu)造函數(shù)不能省略constructor關(guān)鍵字
class MyClass private @Inject constructor() {
}
如果類有一個主構(gòu)造函數(shù),那么次級函數(shù)都要直接或間接委托給主構(gòu)造函數(shù)拗馒,使用this
關(guān)鍵字
// kotlin
class MyClass constructor() {
constructor(s: String): this() {
}
}
// 或者
class MyClass() {
constructor(s: String): this() {
}
}
如果需要在類中進(jìn)行初始化路星,使用init
關(guān)鍵字修飾的初始化代碼塊,
class MyClass() {
init {
// init job1
}
init {
// init job2
}
...
}
初始化代碼塊是主構(gòu)造函數(shù)的一部分诱桂,因此所有初始化代碼塊都會在主構(gòu)造函數(shù)中優(yōu)先執(zhí)行洋丐,其次才會執(zhí)行次構(gòu)造函數(shù)中的代碼。
1.2挥等、變量
var
:修飾可變量
val
:修飾不可變量
成員變量可以和java一樣友绝,在類體內(nèi)聲明,注意此時(shí)聲明變量是必須初始化(或使用lateinit
關(guān)鍵字懶初始化)
// 必須初始化
class MyClass {
lateinit var s1: String
val s2: String = "S2"
}
也可以在主構(gòu)造器中聲明肝劲,此時(shí)可以不初始化
// 可以不初始化
class MyClass constructor(
var s1: String,
val s2: String = "S2"
) {
}
// 或者
class MyClass(
var s1: String,
val s2: String = "S2"
) {
}
使用類型推斷迁客,可以把類型去掉郭宝,變成
var s1 = "S1"
1.3、函數(shù)
1.3.1掷漱、具名函數(shù)
使用fun
關(guān)鍵字聲明
fun getName(): String {
return name
}
區(qū)別于java粘室,返回類型在函數(shù)聲明后面,用:
隔開卜范,如果沒有返回值育特,用Unit
接收,可以省略不寫先朦。上面函數(shù)還可以簡化為單表單表達(dá)式函數(shù)
fun getName(): String = name
// 或簡化為
fun getName() = name
1.3.2、匿名函數(shù)
顧名思義就是沒有名字的函數(shù)犬缨,比如下面這種寫法
private fun getName() {
// 變量name接收匿名函數(shù)喳魏,name表示一個函數(shù),需要兩個Int類型入?yún)⒒逞Γ祷豂nt
val name: (Int, Int) -> Int = { a: Int, b: Int ->
a+b
}
// 調(diào)用name函數(shù)刺彩,傳入1,2作為參數(shù)枝恋,函數(shù)結(jié)果傳遞給value
val value: Int = name(1, 2)
println(value)
}
// 以上函數(shù)調(diào)用部分可以直接寫成這樣
{ a: Int, b: Int ->
a+b
}(1, 2)
注意创倔,匿名函數(shù)如果有返回值,一般不用
return
焚碌,函數(shù)體中最后一行的結(jié)果默認(rèn)作為返回值畦攘。匿名函數(shù)只能出現(xiàn)在其他函數(shù)體中,不能獨(dú)立存在十电。更多具名函數(shù)和匿名函數(shù)的介紹知押,參考這篇文章
Kotlin學(xué)習(xí)筆記函數(shù)篇(1)具名函數(shù)和匿名函數(shù)
1.3.3、局部函數(shù)
kotlin支持局部函數(shù)鹃骂,即一個函數(shù)在另一個函數(shù)內(nèi)部
fun getName(s1: String) {
fun setName(s2: String) {
println(s1)
}
}
成員函數(shù)可以訪問外部函數(shù)(閉包)的局部變量台盯。
2、內(nèi)部類
這部分和java基本相同畏线,在kotlin中普通內(nèi)部類(也叫嵌套類)默認(rèn)是static的静盅,不持有外部類引用,
class Outer {
class Nested {
}
}
使用inner
關(guān)鍵字修飾寝殴,那么就不是static的蒿叠,會持有外部類對象的引用
class Outer {
private val s: String = "S"
inner class Nested {
println(s)
}
}
匿名內(nèi)部類
Android中會經(jīng)常寫如下代碼
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// click event
}
});
使用kotlin可以這樣寫
mView.setOnClickListener(object: View.OnClickListener {
override fun onClick(view: View) {
// click event
}
})
3、集合
3.1杯矩、構(gòu)造集合
可以完全使用Java創(chuàng)建集合的方式栈虚,比如
val list = ArrayList<String>()
val map = HashMap<Int, String>()
val set = HashSet<String>()
val sparseArray = SparseArray<String>()
也可以使用kotlin原生庫,比如
val list = arrayListOf<String>()
val map = hashMapOf<Int, String>()
val set = hashSetOf<String>()
// SparseArray沒有kotlin原生構(gòu)建方式
val sparseArray = SparseArray<String>()
在構(gòu)造集合的同時(shí)可以初始化史隆,
val list = arrayListOf<String>("1", "2", "3")
3.2魂务、遍歷集合
3.2.1、forEach
val list = arrayListOf<String>()
list .forEach { s ->
println(s)
}
val map = hashMapOf<Int, String>()
map .forEach { entry ->
println("${entry .key} -> ${entry .value}")
}
3.2.2、for
val list = arrayListOf<String>()
for (s in list) {
println(s)
}
val map = hashMapOf<Int, String>()
for (entry in map ) {
println("${entry.key} -> ${entry.value}")
}
3.2.3粘姜、iterator
val list = arrayListOf<String>()
val iterator = list .iterator()
while (iterator.hasNext()) {
println(iterator.next())
}
val map = hashMapOf<Int, String>()
val iterator = map .iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
println("${entry.key} -> ${entry.value}")
}
4鬓照、條件判斷
4.1、if else
用法上kotlin基本和java一致孤紧,不同的是豺裆,koltin中if else是可以有返回值的,比如
val value = if (條件一) {
"這是條件一的返回值"
} else {
"這是else的返回值"
}
if else條件代碼塊中最后一行代碼的結(jié)果會默認(rèn)作為整體的返回值号显。另外臭猜,由于kotlin沒有三目運(yùn)算符,所以可以用if else來提代押蚤。
4.2蔑歌、when
kotlin中的when
對應(yīng)java中的switch case
when (條件) {
匹配值1 -> {
println("這是匹配值1的結(jié)果")
}
匹配值2 -> {
println("這是匹配值2的結(jié)果")
}
匹配值3 -> {
println("這是匹配值3的結(jié)果")
}
...
else -> {
println("這是沒有匹配到的結(jié)果")
}
}
同樣,when
也可以作為表達(dá)式來使用揽碘,返回的是條件代碼塊中最后一行代碼的執(zhí)行結(jié)果
val value = when (條件) {
匹配值1 -> {
"這是匹配值1的結(jié)果"
}
匹配值2 -> {
"這是匹配值2的結(jié)果"
}
匹配值3 -> {
"這是匹配值3的結(jié)果"
}
...
else -> {
"這是沒有匹配到的結(jié)果"
}
}
5次屠、空判斷
kotlin中默認(rèn)參數(shù)不能為null,在聲明一個變量的時(shí)候需要初始化雳刺,如果定義的變量可以為null劫灶,使用?
進(jìn)行標(biāo)識
val s: String = "S" // 必須初始化,且不能為null
var s1: String? = null // 必須初始化掖桦,但可以為null
如果一個變量在聲明的時(shí)候無法初始化本昏,但又不能為null,此時(shí)可以用lateinit
來修飾枪汪,
lateinit var s3: String // 聲明時(shí)不必初始化凛俱,不可null
注意,lateinit
修飾的變量可以不在聲明時(shí)初始化料饥,但定要在使用前進(jìn)行初始化蒲犬,否則會拋異常。
6岸啡、作用域函數(shù)
作用域函數(shù)唯一的作用就是在對象的上下文中執(zhí)行代碼塊原叮,也就是說這個作用域指的就是對象的上下文。作用域函數(shù)一共5種:let
巡蘸、run
奋隶、with
、apply
以及 also
悦荒。作用域函數(shù)的詳細(xì)介紹參考Kotlin學(xué)習(xí)筆記_作用域函數(shù)