kotlin 學(xué)習(xí)筆記 一

Kotlin 是一種現(xiàn)代化豫领、靜態(tài)類型的編程語言怎炊,由 JetBrains 開發(fā)并于2016年發(fā)布。它旨在解決 Java 語言的一些繁瑣和冗長的問題祠墅,提供更簡潔、安全和高效的代碼編寫方式歌径。

Kotlin 具有以下特點(diǎn):

可與現(xiàn)有的 Java 代碼和庫協(xié)同工作:Kotlin 可以與 Java 代碼無縫集成毁嗦,可以逐步地在現(xiàn)有的 Java 項目中引入 Kotlin,或者通過 Kotlin 編寫新的代碼而與現(xiàn)有的 Java 庫協(xié)同工作回铛。

簡潔優(yōu)雅的語法:Kotlin 借鑒了其他一些現(xiàn)代編程語言的優(yōu)點(diǎn)狗准,擁有簡潔、易讀的語法茵肃,減少了冗長的代碼腔长,使代碼更加簡潔優(yōu)雅。

空安全:Kotlin 引入了空安全的概念验残,可以在編譯階段檢測出可能的空指針異常捞附,并具有相應(yīng)的語言機(jī)制來處理空值。

函數(shù)式編程:Kotlin 提供了許多函數(shù)式編程的特性您没,如 lambda 表達(dá)式鸟召、高階函數(shù)、擴(kuò)展函數(shù)等氨鹏,使得代碼更具表達(dá)力和簡潔性欧募。

協(xié)程支持:Kotlin 引入了協(xié)程(Coroutines)的概念,使異步編程變得更加簡單和可讀仆抵,同時避免了回調(diào)地獄跟继。

跨平臺開發(fā):Kotlin 為多平臺開發(fā)提供了支持,可以使用 Kotlin 編寫共享的業(yè)務(wù)邏輯代碼镣丑,然后在 Android舔糖、iOS、Web 等不同平臺上共享使用莺匠。

可擴(kuò)展性:Kotlin 提供了強(qiáng)大的語言特性剩盒,如擴(kuò)展函數(shù)、操作符重載等慨蛙,可以輕松擴(kuò)展現(xiàn)有類的功能辽聊。

總體而言,Kotlin 是一門非常強(qiáng)大和靈活的語言期贫,不僅適用于 Android 開發(fā)跟匆,還可以用于服務(wù)器端開發(fā)、桌面應(yīng)用和其他領(lǐng)域的開發(fā)通砍。它具有易讀易寫玛臂、安全烤蜕、高效和與 Java 無縫協(xié)作等特點(diǎn),受到越來越多開發(fā)者的喜愛和采用迹冤。

基本語法

這是一組基本語法元素及示例讽营。在每段的末尾都有一個指向相關(guān)主題詳述的鏈接。

也可以通過 JetBrains 學(xué)院的免費(fèi) Kotlin 核心課程學(xué)習(xí)所有 Kotlin 要領(lǐng)泡徙。

包的定義與導(dǎo)入

包的聲明應(yīng)處于源文件頂部橱鹏。

package com.test.demo

import kotlin.test.*

// ……

目錄與包的結(jié)構(gòu)無需匹配:源代碼可以在文件系統(tǒng)的任意位置。

參見堪藐。

程序入口點(diǎn)

Kotlin 應(yīng)用程序的入口點(diǎn)是 main 函數(shù)莉兰。

fun main() {
    println("Hello world!")
}

main 的另一種形式接受可變數(shù)量的 String 參數(shù)。

fun main(args: Array<String>) {
    println(args.contentToString())
}

輸出打到標(biāo)準(zhǔn)輸出

print 將其參數(shù)打到標(biāo)準(zhǔn)輸出礁竞。

fun main() {
//sampleStart
    print("Hello ")
    print("world!")
//sampleEnd
}

println 輸出其參數(shù)并添加換行符糖荒,以便接下來輸出的內(nèi)容出現(xiàn)在下一行。

fun main() {
//sampleStart
    println("Hello world!")
    println(42)
//sampleEnd
}

函數(shù)

帶有兩個 Int 參數(shù)模捂、返回 Int 的函數(shù)捶朵。

// fun <關(guān)鍵字>  sum<方法名> (a <參數(shù)名>:Int<參數(shù)類型 方法中參數(shù)類型必須寫>)
fun sum(a: Int, b: Int): Int {
    return a + b
}
//sampleEnd

fun main() {
    print("sum of 3 and 5 is ")
    println(sum(3, 5))
}

函數(shù)體可以是表達(dá)式。其返回類型可以推斷出來狂男。

//sampleStart
fun sum(a: Int, b: Int) = a + b
//sampleEnd

fun main() {
    println("sum of 19 and 23 is ${sum(19, 23)}")
}

返回?zé)o意義的值的函數(shù)综看。

//sampleStart
fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}
//sampleEnd

fun main() {
    printSum(-1, 8)
}

Unit 返回類型可以省略。

//sampleStart
fun printSum(a: Int, b: Int) {
    println("sum of $a and $b is ${a + b}")
}
//sampleEnd

fun main() {
    printSum(-1, 8)
}

參見函數(shù)并淋。

變量

定義只讀局部變量使用關(guān)鍵字 val 定義。只能為其賦值一次珍昨。

fun main() {
//sampleStart
    val a: Int = 1  // 立即賦值
    val b = 2   // 自動推斷出 `Int` 類型
    val c: Int  // 如果沒有初始值類型不能省略
    c = 3       // 明確賦值
//sampleEnd
    println("a = $a, b = $b, c = $c")
}

可重新賦值的變量使用 var 關(guān)鍵字县耽。

fun main() {
//sampleStart
    var x = 5 // 自動推斷出 `Int` 類型
    x += 1
//sampleEnd
    println("x = $x")
}

可以在頂層聲明變量。

//sampleStart
val PI = 3.14
var x = 0

fun incrementX() { 
    x += 1 
}
//sampleEnd

fun main() {
    println("x = $x; PI = $PI")
    incrementX()
    println("incrementX()")
    println("x = $x; PI = $PI")
}

參見屬性镣典。

創(chuàng)建類與實例

使用 class 關(guān)鍵字定義類兔毙。

class Shape

類的屬性可以在其聲明或主體中列出。

class Rectangle(var height: Double, var length: Double) {
    var perimeter = (height + length) * 2 
}

具有類聲明中所列參數(shù)的默認(rèn)構(gòu)造函數(shù)會自動可用兄春。

class Rectangle(var height: Double, var length: Double) {
    var perimeter = (height + length) * 2 
}
fun main() {
//sampleStart
    val rectangle = Rectangle(5.0, 2.0)
    println("The perimeter is ${rectangle.perimeter}")
//sampleEnd
}

類之間繼承由冒號(:)聲明澎剥。默認(rèn)情況下類都是 final 的;如需讓一個類可繼承赶舆, 請將其標(biāo)記為 open哑姚。

open class Shape

class Rectangle(var height: Double, var length: Double): Shape() {
    var perimeter = (height + length) * 2 
}

參見以及對象與實例

注釋

與大多數(shù)現(xiàn)代語言一樣芜茵,Kotlin 支持單行(或行末)與多行()注釋叙量。

// 這是一個行注釋

/* 這是一個多行的
   塊注釋。 */

Kotlin 中的塊注釋可以嵌套九串。

/* 注釋從這里開始
/* 包含嵌套的注釋 *&#8288;/     
并且在這里結(jié)束绞佩。 */

參見編寫 Kotlin 代碼文檔 查看關(guān)于文檔注釋語法的信息寺鸥。

字符串模板

fun main() {
//sampleStart
    var a = 1
    // 模板中的簡單名稱:
    val s1 = "a is $a" 

    a = 2
    // 模板中的任意表達(dá)式:
    val s2 = "${s1.replace("is", "was")}, but now is $a"
//sampleEnd
    println(s2)
}

參見字符串模板

條件表達(dá)式

//sampleStart
fun maxOf(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}
//sampleEnd

fun main() {
    println("max of 0 and 42 is ${maxOf(0, 42)}")
}

在 Kotlin 中品山,if 也可以用作表達(dá)式胆建。

//sampleStart
fun maxOf(a: Int, b: Int) = if (a > b) a else b
//sampleEnd

fun main() {
    println("max of 0 and 42 is ${maxOf(0, 42)}")
}

參見if 表達(dá)式

for 循環(huán)

fun main() {
//sampleStart
    val items = listOf("apple", "banana", "kiwifruit")
    for (item in items) {
        println(item)
    }
//sampleEnd
}

或者

fun main() {
//sampleStart
    val items = listOf("apple", "banana", "kiwifruit")
    for (index in items.indices) {
        println("item at $index is ${items[index]}")
    }
//sampleEnd
}

參見 for 循環(huán)肘交。

while 循環(huán)

fun main() {
//sampleStart
    val items = listOf("apple", "banana", "kiwifruit")
    var index = 0
    while (index < items.size) {
        println("item at $index is ${items[index]}")
        index++
    }
//sampleEnd
}

參見 while 循環(huán)笆载。

when 表達(dá)式

//sampleStart
fun describe(obj: Any): String =
    when (obj) {
        1          -> "One"
        "Hello"    -> "Greeting"
        is Long    -> "Long"
        !is String -> "Not a string"
        else       -> "Unknown"
    }
//sampleEnd

fun main() {
    println(describe(1))
    println(describe("Hello"))
    println(describe(1000L))
    println(describe(2))
    println(describe("other"))
}

參見 when 表達(dá)式

使用區(qū)間(range)

使用 in 操作符來檢測某個數(shù)字是否在指定區(qū)間內(nèi)酸些。

fun main() {
//sampleStart
    val x = 10
    val y = 9
    if (x in 1..y+1) {
        println("fits in range")
    }
//sampleEnd
}

檢測某個數(shù)字是否在指定區(qū)間外宰译。

fun main() {
//sampleStart
    val list = listOf("a", "b", "c")

    if (-1 !in 0..list.lastIndex) {
        println("-1 is out of range")
    }
    if (list.size !in list.indices) {
        println("list size is out of valid list indices range, too")
    }
//sampleEnd
}

區(qū)間迭代。

fun main() {
//sampleStart
    for (x in 1..5) {
        print(x)
    }
//sampleEnd
}

或數(shù)列迭代魄懂。

fun main() {
//sampleStart
    for (x in 1..10 step 2) {
        print(x)
    }
    println()
    for (x in 9 downTo 0 step 3) {
        print(x)
    }
//sampleEnd
}

參見區(qū)間與數(shù)列沿侈。

集合

對集合進(jìn)行迭代。

fun main() {
    val items = listOf("apple", "banana", "kiwifruit")
//sampleStart
    for (item in items) {
        println(item)
    }
//sampleEnd
}

使用 in 操作符來判斷集合內(nèi)是否包含某實例市栗。

fun main() {
    val items = setOf("apple", "banana", "kiwifruit")
//sampleStart
    when {
        "orange" in items -> println("juicy")
        "apple" in items -> println("apple is fine too")
    }
//sampleEnd
}

使用 lambda 表達(dá)式來過濾(filter)與映射(map)集合:

fun main() {
//sampleStart
    val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
    fruits
      .filter { it.startsWith("a") }
      .sortedBy { it }
      .map { it.uppercase() }
      .forEach { println(it) }
//sampleEnd
}

參見集合概述缀拭。

空值與空檢測

當(dāng)可能用 null 值時,必須將引用顯式標(biāo)記為可空填帽≈肓埽可空類型名稱以問號(?)結(jié)尾。

如果 str 的內(nèi)容不是數(shù)字返回 null

fun parseInt(str: String): Int? {
    // ……
}

使用返回可空值的函數(shù):

fun parseInt(str: String): Int? {
    return str.toIntOrNull()
}

//sampleStart
fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

    // 直接使用 `x * y` 會導(dǎo)致編譯錯誤篡腌,因為它們可能為 null
    if (x != null && y != null) {
        // 在空檢測后褐荷,x 與 y 會自動轉(zhuǎn)換為非空值(non-nullable)
        println(x * y)
    }
    else {
        println("'$arg1' or '$arg2' is not a number")
    }
}
//sampleEnd

fun main() {
    printProduct("6", "7")
    printProduct("a", "7")
    printProduct("a", "b")
}

或者

fun parseInt(str: String): Int? {
    return str.toIntOrNull()
}

fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

//sampleStart
    // ……
    if (x == null) {
        println("Wrong number format in arg1: '$arg1'")
        return
    }
    if (y == null) {
        println("Wrong number format in arg2: '$arg2'")
        return
    }

    // 在空檢測后,x 與 y 會自動轉(zhuǎn)換為非空值
    println(x * y)
//sampleEnd
}

fun main() {
    printProduct("6", "7")
    printProduct("a", "7")
    printProduct("99", "b")
}

參見空安全嘹悼。

類型檢測與自動類型轉(zhuǎn)換

is 操作符檢測一個表達(dá)式是否某類型的一個實例叛甫。 如果一個不可變的局部變量或?qū)傩砸呀?jīng)判斷出為某類型,那么檢測后的分支中可以直接當(dāng)作該類型使用杨伙,無需顯式轉(zhuǎn)換:

//sampleStart
fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        // `obj` 在該條件分支內(nèi)自動轉(zhuǎn)換成 `String`
        return obj.length
    }

    // 在離開類型檢測分支后其监,`obj` 仍然是 `Any` 類型
    return null
}
//sampleEnd

fun main() {
    fun printLength(obj: Any) {
        println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The object is not a string"} ")
    }
    printLength("Incomprehensibilities")
    printLength(1000)
    printLength(listOf(Any()))
}

或者

//sampleStart
fun getStringLength(obj: Any): Int? {
    if (obj !is String) return null

    // `obj` 在這一分支自動轉(zhuǎn)換為 `String`
    return obj.length
}
//sampleEnd

fun main() {
    fun printLength(obj: Any) {
        println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The object is not a string"} ")
    }
    printLength("Incomprehensibilities")
    printLength(1000)
    printLength(listOf(Any()))
}

甚至

//sampleStart
fun getStringLength(obj: Any): Int? {
    // `obj` 在 `&&` 右邊自動轉(zhuǎn)換成 `String` 類型
    if (obj is String && obj.length > 0) {
        return obj.length
    }

    return null
}
//sampleEnd

fun main() {
    fun printLength(obj: Any) {
        println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The object is not a string"} ")
    }
    printLength("Incomprehensibilities")
    printLength("")
    printLength(1000)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市限匣,隨后出現(xiàn)的幾起案子抖苦,更是在濱河造成了極大的恐慌,老刑警劉巖米死,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锌历,死亡現(xiàn)場離奇詭異,居然都是意外死亡峦筒,警方通過查閱死者的電腦和手機(jī)辩涝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勘天,“玉大人怔揩,你說我怎么就攤上這事捉邢。” “怎么了商膊?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵伏伐,是天一觀的道長。 經(jīng)常有香客問我晕拆,道長藐翎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任实幕,我火速辦了婚禮吝镣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昆庇。我一直安慰自己末贾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布整吆。 她就那樣靜靜地躺著拱撵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪表蝙。 梳的紋絲不亂的頭發(fā)上拴测,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音府蛇,去河邊找鬼集索。 笑死,一個胖子當(dāng)著我的面吹牛汇跨,可吹牛的內(nèi)容都是我干的务荆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼扰法,長吁一口氣:“原來是場噩夢啊……” “哼蛹含!你這毒婦竟也來了毅厚?” 一聲冷哼從身側(cè)響起塞颁,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吸耿,沒想到半個月后祠锣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咽安,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年伴网,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妆棒。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡澡腾,死狀恐怖沸伏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情动分,我是刑警寧澤毅糟,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站澜公,受9級特大地震影響姆另,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坟乾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一迹辐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甚侣,春花似錦明吩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宗兼,卻和暖如春躏鱼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背殷绍。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工染苛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人主到。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓茶行,卻偏偏與公主長得像,于是被迫代替她去往敵國和親登钥。 傳聞我的和親對象是個殘疾皇子畔师,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359