內容提要
《Kotlin 實戰》將從語言的基本特性開始,逐漸覆蓋其更多的高級特性,尤其注重講解如何將 Koltin 集成到已有 Java 工程實踐及其背後的原理。本書分為兩個部分。第一部分講解如何開始使用 Kotlin 現有的庫和API,包括基本語法、擴展函式和擴展屬性、數據類和伴生對象、lambda 表達式,以及數據類型系統(著重講解了可空性和集合的概念)。第二部分教你如何使用 Kotlin 構建自己的 API,以及一些深層次特性——約定和委託屬性、高階函式、泛型、註解和反射,以及領域特定語言的構建。《Kotlin 實戰》適合廣大移動開發者及入門學習者,尤其是緊跟主流趨勢的前沿探索者。
目錄
第 1 部分 Kotlin 簡介 1
1 Kotlin :定義和目的 3
1.1 Kotlin 初體驗 3
1.2 Kotlin 的主要特徵4
1.2.1 目標平台 :伺服器端、Android 及任何 Java 運行的地方 4
1.2.2 靜態類型5
1.2.3 函式式和面向對象 6
1.2.4 免費並開源 7
1.3 Kotlin 套用8
1.3.1 伺服器端的 Kotlin8
1.3.2 Android 上的 Kotlin 9
1.4 Kotlin 的設計哲學 10
1.4.1 務實10
1.4.2 簡潔 11
1.4.3 安全12
1.4.4 互操作性 13
1.5 使用 Kotlin 工具 14
1.5.1 編譯 Kotlin 代碼 14
1.5.2 IntelliJ IDEA 和 Android Studio 外掛程式 15
1.5.3 互動式 shell15
1.5.4 Eclipse 外掛程式 15
1.5.5 線上 playground 15
1.5.6 Java 到 Kotlin 的轉換器 16
1.6 小結16
2 Kotlin 基礎 17
2.1 基本要素 :函式和變數 17
2.1.1 Hello,world!18
2.1.2 函式18
2.1.3 變數20
2.1.4 更簡單的字元串格式化 :字元串模板 22
2.2 類和屬性 23
2.2.1 屬性24
2.2.2 自定義訪問器 25
2.2.3 Kotlin 源碼布局 :目錄和包26
2.3 表示和處理選擇 :枚舉和“when” 28
2.3.1 聲明枚舉類28
2.3.2 使用“when”處理枚舉類 29
2.3.3 在“when”結構中使用任意對象 30
2.3.4 使用不帶參數的“when” 31
2.3.5 智慧型轉換 :合併類型檢查和轉換32
2.3.6 重構 :用“when”代替“if” 34
2.3.7 代碼塊作為“if”和“when”的分支 35
2.4 疊代事物 :“while”循環和“for”循環 36
2.4.1 “while”循環36
2.4.2 疊代數字 :區間和數列 37
2.4.3 疊代 map 38
2.4.4 使用“in”檢查集合和區間的成員39
2.5 Kotlin 中的異常 41
2.5.1 “try”“catch”和“finally” 41
2.5.2 “try”作為表達式 42
2.6 小結44
3 函式的定義與調用 45
3.1 在 Kotlin 中創建集合 45
3.2 讓函式更好調用 47
3.2.1 命名參數 48
3.2.2 默認參數值49
3.2.3 消除靜態工具類 :頂層函式和屬性 50
3.3 給別人的類添加方法 :擴展函式和屬性53
3.3.1 導入和擴展函式 54
3.3.2 從 Java 中調用擴展函式54
3.3.3 作為擴展函式的工具函式55
3.3.4 不可重寫的擴展函式 56
3.3.5 擴展屬性 58
3.4 處理集合 :可變參數、中綴調用和庫的支持 59
3.4.1 擴展 Java 集合的 API 59
3.4.2 可變參數 :讓函式支持任意數量的參數60
3.4.3 鍵值對的處理 :中綴調用和解構聲明 60
3.5 字元串和正則表達式的處理 62
3.5.1 分割字元串62
3.5.2 正則表達式和三重引號的字元串63
3.5.3 多行三重引號的字元串 64
3.6 讓你的代碼更整潔 :局部函式和擴展 66
3.7 小結68
4 類、對象和接口 69
4.1 定義類繼承結構 70
4.1.1 Kotlin 中的接口 70
4.1.2 open、final 和 abstract 修飾符 :默認為 final72
4.1.3 可見性修飾符 :默認為 public 75
4.1.4 內部類和嵌套類 :默認是嵌套類76
4.1.5 密封類 :定義受限的類繼承結構79
4.2 聲明一個帶非默認構造方法或屬性的類80
4.2.1 初始化類 :主構造方法和初始化語句塊80
4.2.2 構造方法 :用不同的方式來初始化父類83
4.2.3 實現在接口中聲明的屬性85
4.2.4 通過 getter 或 setter 訪問支持欄位 87
4.2.5 修改訪問器的可見性 88
4.3 編譯器生成的方法 :數據類和類委託 89
4.3.1 通用對象方法 89
4.3.2 數據類 :自動生成通用方法的實現 92
4.3.3 類委託 :使用“by”關鍵字 93
4.4 “object”關鍵字 :將聲明一個類與創建一個實例結合起來95
4.4.1 對象聲明 :創建單例易如反掌 95
4.4.2 伴生對象 :工廠方法和靜態成員的地盤98
4.4.3 作為普通對象使用的伴生對象 100
4.4.4 對象表達式 :改變寫法的匿名內部類 102
4.5 小結 104
5 Lambda 編程 105
5.1 Lambda 表達式和成員引用 105
5.1.1 Lambda 簡介 :作為函式參數的代碼塊106
5.1.2 Lambda 和集合 107
5.1.3 Lambda 表達式的語法 108
5.1.4 在作用域中訪問變數 111
5.1.5 成員引用 114
5.2 集合的函式式 API 116
5.2.1 基礎 :filter 和 map 116
5.2.2 “all”“any”“count”和“find”: 對集合套用判斷式 118
5.2.3 groupBy :把列錶轉換成分組的 map 119
5.2.4 flatMap 和 flatten :處理嵌套集合中的元素120
5.3 惰性集合操作 :序列121
5.3.1 執行序列操作 :中間和末端操作 123
5.3.2 創建序列 125
5.4 使用 Java 函式式接口 126
5.4.1 把 lambda 當作參數傳遞給 Java 方法127
5.4.2 SAM 構造方法 :顯式地把 lambda 轉換成函式式接口 129
5.5 帶接收者的 lambda :“with”與“apply”131
5.5.1 “with”函式131
5.5.2 “apply”函式 133
5.6 小結 135
6 Kotlin 的類型系統137
6.1 可空性137
6.1.1 可空類型 138
6.1.2 類型的含義 140
6.1.3 安全調用運算符 :“?:”141
6.1.4 Elvis 運算符 :“?:” 143
6.1.5 安全轉換 :“as?” 145
6.1.6 非空斷言 :“!!”146
6.1.7 “let”函式148
6.1.8 延遲初始化的屬性 149
6.1.9 可空類性的擴展 151
6.1.10 類型參數的可空性 153
6.1.11 可空性和 Java 153
6.2 基本數據類型和其他基本類型 157
6.2.1 基本數據類型 :Int、Boolean 及其他158
6.2.2 可空的基本數據類型 :Int?、Boolean? 及其他159
6.2.3 數字轉換 160
6.2.4 “Any”和“Any?”:根類型 162
6.2.5 Unit 類型 :Kotlin 的“void”163
6.2.6 Nothing 類型 :“這個函式永不返回” 164
6.3 集合與數組 164
6.3.1 可空性和集合165
6.3.2 唯讀集合與可變集合167
6.3.3 Kotlin 集合和 Java 168
6.3.4 作為平台類型的集合171
6.3.5 對象和基本數據類型的數組173
6.4 小結 175
第 2 部分 擁抱 Kotlin 177
7 運算符重載及其他約定179
7.1 重載算術運算符 180
7.1.1 重載二元算術運算 180
7.1.2 重載複合賦值運算符183
7.1.3 重載一元運算符 184
7.2 重載比較運算符 186
7.2.1 等號運算符 :“equals" 186
7.2.2 排序運算符 :compareTo187
7.3 集合與區間的約定 188
7.3.1 通過下標來訪問元素 :“get”和“set” 188
7.3.2 “in”的約定190
7.3.3 rangeTo 的約定 191
7.3.4 在“for”循環中使用“iterator”的約定 192
7.4 解構聲明和組件函式193
7.4.1 解構聲明和循環 194
7.5 重用屬性訪問的邏輯 :委託屬性 195
7.5.1 委託屬性的基本操作196
7.5.2 使用委託屬性 :惰性初始化和“by lazy()”197
7.5.3 實現委託屬性198
7.5.4 委託屬性的變換規則202
7.5.5 在 map 中保存屬性值 203
7.5.6 框架中的委託屬性 204
7.6 小結 205
8 高階函式 :Lambda 作為形參和返回值 207
8.1 聲明高階函式207
8.1.1 函式類型 208
8.1.2 調用作為參數的函式209
8.1.3 在 Java 中使用函式類 211
8.1.4 函式類型的參數默認值和 null 值 212
8.1.5 返回函式的函式 214
8.1.6 通過 lambda 去除重複代碼 216
8.2 內聯函式 :消除 lambda 帶來的運行時開銷218
8.2.1 內聯函式如何運作 219
8.2.2 內聯函式的限制 221
8.2.3 內聯集合操作222
8.2.4 決定何時將函式聲明成內聯223
8.2.5 使用內聯 lambda 管理資源 223
8.3 高階函式中的控制流225
8.3.1 lambda 中的返回語句 :從一個封閉的函式返回225
8.3.2 從 lambda 返回 :使用標籤返回226
8.3.3 匿名函式 :默認使用局部返回 228
8.4 小結 229
9 泛型 231
9.1 泛型類型參數232
9.1.1 泛型函式和屬性 232
9.1.2 聲明泛型類 234
9.1.3 類型參數約束235
9.1.4 讓類型形參非空 237
9.2 運行時的泛型 :擦除和實化類型參數 238
9.2.1 運行時的泛型 :類型檢查和轉換 238
9.2.2 聲明帶實化類型參數的函式241
9.2.3 使用實化類型參數代替類引用 243
9.2.4 實化類型參數的限制244
9.3 變型 :泛型和子類型化 245
9.3.1 為什麼存在變型 :給函式傳遞實參245
9.3.2 類、類型和子類型 246
9.3.3 協變 :保留子類型化關係 248
9.3.4 逆變 :反轉子類型化關係 252
9.3.5 使用點變型 :在類型出現的地方指定變型254
9.3.6 星號投影 :使用 * 代替類型參數 257
9.4 小結 261
10 註解與反射 263
10.1 聲明並套用註解264
10.1.1 套用註解264
10.1.2 註解目標265
10.1.3 使用註解定製 JSON 序列化 267
10.1.4 聲明註解269
10.1.5 元註解 :控制如何處理一個註解 270
10.1.6 使用類做註解參數 271
10.1.7 使用泛型類做註解參數272
10.2 反射 :在運行時對 Kotlin 對象進行自省 273
10.2.1 Kotlin 反射 API :KClass、KCallable、KFunction 和KProperty 274
10.2.2 用反射實現對象序列化278
10.2.3 用註解定製序列化 279
10.2.4 JSON 解析和對象反序列化283
10.2.5 反序列化的最後一步 :callBy() 和使用反射創建對象 287
10.3 小結 291
11 DSL 構建 293
11.1 從 API 到 DSL 293
11.1.1 領域特定語言的概念 295
11.1.2 內部 DSL296
11.1.3 DSL 的結構 297
11.1.4 使用內部 DSL 構建 HTML298
11.2 構建結構化的 API:DSL 中帶接收者的 lambda 299
11.2.1 帶接收者的 lambda 和擴展函式類型 299
11.2.2 在 HTML 構建器中使用帶接收者的 lambda 303
11.2.3 Kotlin 構建器 :促成抽象和重用307
11.3 使用“invoke”約定構建更靈活的代碼塊嵌套 310
11.3.1 “invoke”約定 :像函式一樣可以調用的對象 310
11.3.2 “invoke”約定和函式式類型 311
11.3.3 DSL 中的“invoke”約定 :在 Gradle 中聲明依賴 312
11.4 實踐中的 Kotlin DSL 314
11.4.1 把中綴調用連結起來 :測試框架中的“should” 314
11.4.2 在基本數據類型上定義擴展 :處理日期 316
11.4.3 成員擴展函式 :為 SQL 設計的內部 DSL317
11.4.4 Anko :動態創建 Android UI 320
11.5 小結 322
A 構建 Kotlin 項目 323
B Kotlin 代碼的文檔化 327
C Kotlin 生態系統 331