Kotlin 知識梳理(1) - Kotlin 基礎

Kotlin 知識梳理系列文章

Kotlin 知識梳理(1) - Kotlin 基礎
Kotlin 知識梳理(2) - 函數的定義與調用
Kotlin 知識梳理(3) - 類、對象和接口
Kotlin 知識梳理(4) - 數據類、類委托 及 object 關鍵字
Kotlin 知識梳理(5) - lambda 表達式和成員引用
Kotlin 知識梳理(6) - Kotlin 的可空性
Kotlin 知識梳理(7) - Kotlin 的類型系統
Kotlin 知識梳理(8) - 運算符重載及其他約定
Kotlin 知識梳理(9) - 委托屬性
Kotlin 知識梳理(10) - 高階函數:Lambda 作為形參或返回值
Kotlin 知識梳理(11) - 內聯函數
Kotlin 知識梳理(12) - 泛型類型參數


一、本文概要

本文是對<<Kotlin in Action>>的學習筆記,如果需要運行相應的代碼可以訪問在線環境 try.kotlinlang.org,這部分的思維導圖為:

kotlin 基礎

二、函數和變量

2.1 函數

2.1.1 函數的基本構成

Kotlin中,函數的基本結構由四個部分構成:

  • 函數名稱
  • 參數列表
  • 返回類型
  • 函數體

函數的聲明以關鍵字 fun 開始,函數名稱 緊隨其后,接下來是括號括起來的 參數列表,參數列表的后面跟著 返回類型,返回類型和參數列表之間用冒號隔開,最后是函數體。

下面是一個比較大小的函數例子,上面談到的四個部分構成如圖中標注所示:


2.1.2 表達式和語句

在上面的例子中,if是表達式,而不是語句,表達式和語句的區別在于:

  • 表達式 有值,并且能作為另一個表達式的一部分使用。
  • 語句 總是包含著它的代碼塊中的頂層元素,并且沒有自己的值。

Java中,所有的控制結構都是語句,而在Kotlin中,除了fordodo/while以外大多數控制結構都是表達式。

當函數體是由單個表達式構成時,可以用這個表達式作為完整的函數體,并且去掉花括號和return語句,上面的例子就是這種情況,因此可以改寫為:

  • 如果函數體寫在花括號中,我們說這個函數有 代碼塊體
  • 如果它直接返回了一個表達式,它就有 表達式體

2.1.3 省略返回類型

對于 表達式體函數,可以省略返回類型,因為編譯器會分析作為函數體的表達式,并把它的類型作為函數的返回類型,這種分析稱為 類型推導。但是對于有返回值的 代碼塊體函數,必須顯示地寫出返回類型和return語句。

上面的例子可以簡化為:


2.2 變量

Kotlin中,變量的聲明以關鍵字val/var開始,然后是變量名稱,最后可以加上類型(不加也可以),這里分為兩種情況:

  • 如果指定了初始化器,那么在不指定類型的情況下,編譯器會分析初始化器表達式的值,并把它的類型作為變量的類型,例如下面兩個就分別為IntDouble類型:
  • 如果沒有指定初始化器,需要顯示地指定它的類型,因為此時編譯器無法推斷出它的類型。


2.2.1 可變變量和不可變變量

聲明變量的關鍵字有兩個:

(1) 不可變引用 val

使用val聲明的變量不能在初始化之后再次賦值,它對應的是Javafinal變量。
默認情況下,應該盡可能地使用val關鍵字來聲明所有的Kotlin變量。在定義了val變量的代碼塊執行期間,val變量只能進行唯一一次初始化,但是,如果編譯器能確保唯一一條初始化語句會被執行,可以根據條件使用不同的值來初始化它。

(2) 可變引用 var

這種變量的值可以改變,但是它的類型卻是改變不了的。



如果需要在變量中存儲不匹配類型的值,必須手動把值轉換或強制轉換到正確的類型。

2.2.2 字符串模板

  • Kotlin可以在字符串字面值中引用局部變量,只需要在變量名稱前面加上字符$
  • 如果要在字符串中使用$,需要對它進行轉義。

    運行結果為:
  • 除了可以引用局部變量之外,還可以引用更加復雜的表達式,只需要把表達式用花括號擴起來。


2.3 類

2.3.1 屬性

類的概念就是把數據和處理數據的代碼封裝成一個單一的實體,在Java中,數據存儲在字段中,并且通常是私有的。如果想讓類的使用者訪問到數據得提供訪問方法,即getter/setter

Java中,字段和其訪問器的組合常常被叫作屬性。在Kotlin中,屬性是頭等的語言特性,完全 替代了字段和訪問器方法。在類中聲明一個屬性和聲明一個變量一樣:使用val/var關鍵字,前者是只讀的,而后者是可變的。

當聲明屬性的時候,就聲明了對應的訪問器(只讀屬性有一個gettter,而可變屬性則有getter/setter),例如下面的例子,聲明了只讀的name屬性,可變的isMarried屬性,其賦值和讀取的方法如下所示:


運行結果為:

2.3.2 自定義訪問器

假設聲明一個矩形,它能判斷自己是否是正方形,那么就不需要一個單獨的字段來存儲這個信息,此時我們可以寫一個自定義的訪問器:用val開頭作為聲明,緊跟著的是屬性的名稱和類型,接下來是get()關鍵字,最后是一個函數體。


運行結果為:

2.3.3 目錄和包

  • Kotlin中包的概念和Java類似,每個kotlin文件都能以一個package語句開頭,而文件中定義的所有聲明(類、函數及屬性)都會被放到這個包中。
  • 如果其他文件定義的聲明也有相同的包,這個文件可以直接使用它們;如果包不同,則需要導入它們,導入語句放在文件的最前面并使用import關鍵字。
  • kotlin不區分導入的是類還是函數,而且,它允許使用import關鍵字導入任何種類的聲明,可以直接導入頂層函數的名稱,也可以在包名稱后加上.*來導入特定包中定義的所有聲明。
  • Java中,要把類放到和包結構相匹配的文件與目錄結構中,而在kotlin中,可以把多個package聲明不相同的類放在同一個文件夾中。

2.4 表示和處理選擇:枚舉和 when

2.4.1 聲明枚舉類

簡單枚舉類

聲明枚舉類時,enum是一個所謂的軟關鍵字,只有當它出現在class前面時才有特殊的意義,在其他地方可以當做普通名稱使用。而class仍然是一個關鍵字,下面是一個枚舉類的聲明:

帶屬性的枚舉類

以下是一個帶屬性的枚舉類:



運行結果為:



當聲明一個帶屬性的枚舉類時,有幾點需要注意:
  • 當聲明每個枚舉常量的時候,必須提供該常量的屬性值。
  • 如果要在枚舉類中定義任何方法,就要使用分號把枚舉常量列表和方法分開。

2.4.2 使用 "when” 處理枚舉類

when是一個有返回值的表達式,因此,作為表達式函數體,它可以去掉花括號和return語句,并省略返回類型的聲明。

下面是一個通過when處理枚舉類的例子,它和Java中的switch語句類似,根據whenColor的值走到對應的分支,除此之外,我們可以把多個值用逗號間隔,合并到同一個分支:


運行的結果為:

2.4.3 在 “when”結構中使用任意對象

Java中,和when類似的switch語句要求必須使用常量(枚舉常量、字符串或者數字字面值)作為 分支條件,而when允許使用任何對象,我們使用一個函數來混合兩種顏色。下面例子中用到的setOf是由Kotlin標準函數庫提供的,它可以創建出一個Set,并且會包含所有指定為函數實參的對象,只要兩個set中包含一樣的條目,它們就是相等的,集合的條目順序并不重要。


運行結果為:

除此之外,我們還可以不給when表達式提供參數,這樣分支條件就是任意的布爾表達時,這種寫法的優點是不會創建額外的對象,但代價是它更難理解。

2.4.4 智能轉換:合并類型檢查和轉換

kotlin中,判斷一個變量是否是某種類型需要使用is關鍵字,它和Java當中的instanceOf相似。

  • Java中,在檢查完后還需要顯示地加上類型轉換。
  • kotlin中,如果你檢查過一個變量是某種類型,后面就不需要再轉換它,可以把它當做你檢查過的類型來使用。

我們用下面這個例子,NumSum都實現了Expr接口,通過is判斷它的類型,完成遞歸求和。可以看到,在is判斷之后,不再需要轉換成NumSum,就可以直接訪問該類的成員變量。


運行結果為:

智能轉換 只在變量經過is檢查且之后不再發生變化 的情況下有效,當你對一個類的屬性進行智能轉換的時候,這個屬性必須是一個val屬性,而且不能有自定義的訪問器,否則,每次對屬性的訪問是否都能返回同樣的值將無從驗證。

2.4.5 代碼塊作為 "if" 和 "when" 的分支

ifwhen都可以使用代碼塊作為分支體,這種情況下,代碼塊中的最后一個表達式就是結果,這個規則在所有使用代碼塊并期望得到一個結果的地方成立。同樣的規則對try主體和catch子句也有效。


運行結果為:

2.5 迭代事物

2.5.1 while 循環

kotlinJava一樣,有while循環和do-while循環,它們的語法和Java中相應的循環完全一致。

2.5.2 迭代數字:區間和數列

Java當中,對于循環的處理方式為:先初始化變量,在循環的每一步更新它的值,并在值滿足某個限制條件時退出循環。

而在Kotlin中,為了替代常見的循環用法,使用了 區間 的概念,其本質上就是兩個值之間的間隔,這兩個值通常是數字:一個起始值,一個結束值。使用..運算符來表示區間,而結束值始終是區間的一部分。


運行結果為:

除此之外,還有downTostepuntil等用于區間的語法,用于進行循環操作,例如下面的例子downTo用于遞減到指定的值,而step則指定步長:

運行結果為:

使用until則可以使迭代不包含指定的結束值,例如下面這樣:

運行結果為:

2.5.3 迭代 map

更新 map

這里我們用到了TreeMap,在更新map時,我們可以像使用數組一樣,只不過下標變成了key值:

訪問 map

下面的例子展示了for允許允許展開迭代中的集合的元素,把展開的結果存儲到了兩個獨立的變量中:letter是鍵、binary是值:


運行結果為:

2.5.4 使用 "in" 檢查集合和區間的成員

使用in運算符來檢查一個值是否在區間中,或者它的逆運算!in來檢查這個值是否不在區間中,區間不僅限于字符,假如有一個支持實例比較操作的任意類(實現了java.lang.Comparable接口),就能創建這種類型的對象的區間。


運行結果為:

2.5 kotlin 中的異常

kotlin的異常處理和Java以及其他許多語言的處理方式類似:一個函數可以正常結束,也可以在出現錯誤的情況下拋出異常。方法的調用者能捕獲到這個異常并處理它;如果沒有處理,異常會沿著調用棧再次拋出。

  • 拋出異常時使用throw關鍵字,但是不必使用new關鍵字來創建異常實例。
  • throw結構是一個表達式,能作為另一個表達式的一部分使用。

2.5.1 “try” "catch" 和 "finally"

當使用帶有catchfinally子句的try結構來處理異常時,下面是一個典型的結構:

  • Java最大區別就是throws子句沒有出現在代碼中:如果使用Java來寫這個函數,你會顯示地在函數聲明上面寫上throws IOException。這是因為IOException是一個受檢異常,在Java中,這種異常必須顯示地處理,必須聲明你的函數能拋出所有的受檢異常。
    Java 處理方式
  • kotlin不區分受檢異常和未受檢異常,不必指定函數拋出的異常,而且可以處理也可以不處理異常。
  • 與此同時,BufferReader.close可能拋出需要處理的受檢異常,如果關閉失敗,大多數程序不會采取什么有意義的行動,所以捕獲來自close方法的異常所需的代碼是多余的。

2.5.2 “try”作為表達式

kotlin中的try關鍵字就像ifwhen一樣,引入了一個表達式,可以把它的值賦給一個變量,并且需要用花括號把語句主體括起來。如果主體包含多個表達式,那么整個try表達式的值就是最后一個表達式的值。


運行結果為:


更多文章,歡迎訪問我的 Android 知識梳理系列:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容