本書面向程序員、開發(fā)主管、架構師和技術經理。假定讀者熟悉編程的基礎知識,同時也假定讀者對Java和JDK有一定的了解。
第I部分主要介紹使用Kotlin編寫腳本。
第II部分是關于面向對象的編程。
第III部分,你將學習如何使用該語言的函數風格的功能。
第IV部分將把目前為止所學的知識結合起來,使你的代碼更加流暢,并教會你如何創(chuàng)建內部領域特定語言(DSL)。
在第V部分中,你將了解新的協程和異步編程。
第VI部分涉及Java的互操作、測試、使用帶有Spring的Kotlin,以及使用Kotlin編寫Android應用程序。
適讀人群 :程序員、開發(fā)主管、架構師和技術經理以及其他對Kotlin感興趣的讀者 Kotlin是一種高度簡潔、優(yōu)雅、流暢和富有表現力的﹑靜態(tài)類型的多范式語言。它是為數不多的可同時編譯成Java字節(jié)碼和JavaScript的語言之一。谷歌也將其作為Android開發(fā)的一流語言。使用Kotlin,你可以混合使用命令式、函數式和面向對象的編程風格,并從適合當前問題的方法中獲益。你可以用它來構建服務器端、前端以及Android應用程序。而且完成任務所需的代碼更少,同時又可以保證代碼類型安全且更不容易出錯。
【為什么要選擇本書】
閱讀本書,不僅可以通過易于理解的示例學習使用Kotlin語言的許多特性,還可以學習編寫易于維護、高性能的JVM和Android應用程序,創(chuàng)建DSL和異步編程等。
本書會帶你使用你喜歡的IDE并利用大量示例和練習來提高你的Kotlin技能。你將學習創(chuàng)建獨立的小程序并以腳本的形式運行,創(chuàng)建類型安全的代碼,然后將這些知識進一步拓展,以創(chuàng)建易于擴展的﹑完全面向對象的﹑函數式風格的代碼。還將學習如何在不影響效率或性能的情況下優(yōu)雅地編程,以及如何使用元編程來創(chuàng)建高度富有表現力的代碼,并創(chuàng)建利用語言流暢性優(yōu)勢的內部DSL。與此同時,你也會學習協程、異步編程、自動化測試的相關知識,并學習在企業(yè)級應用中混合使用Kotlin與Java。
本書將幫助你掌握少數幾種可用于全棧編程(從服務器到移動設備)的語言之一,從而創(chuàng)建高性能、簡潔、易于維護的應用程序。如果你想學習Kotlin的精髓,包括從基礎知識到更高級的概念,那么這本書你選對了。
本書的目標讀者
本書面向程序員、開發(fā)主管、架構師和技術經理。本書假定讀者熟悉編程的基礎知識,同時也假定讀者對Java和JDK有一定的了解,但并沒有假定讀者對Kotlin有任何了解。如果你是一名Android程序員,本書會為你將來用Kotlin來為這些設備編程打下良好的基礎,盡管本書并不是專門針對Android平臺的。
如果你是Kotlin新手,本書將幫助你入門并快速地將該語言應用到你的項目中。如果你已經在使用Kotlin,可以使用本書來加深對該語言的一些高級特性的理解。
你還可以使用本書來培訓你的開發(fā)人員,讓他們精通Kotlin,用它來編寫高度流暢和富于表現力的代碼,并解決復雜的問題。
本書內容
Kotlin是一種多范式編程語言。你可以用Kotlin編寫簡單的腳本、面向對象的代碼、函數式代碼,以及異步編程等。為了合理地涵蓋這一廣泛的主題,本書分為多個部分。
第一部分主要介紹使用Kotlin編寫腳本。第二部分是關于面向對象編程的。在第三部分中,你將學習如何使用該語言的函數式風格的功能。第四部分將把目前為止所學的知識結合起來,使代碼更加流暢,并教會你如何創(chuàng)建內部領域特定語言(DSL)。在第五部分中,你將了解協程和異步編程。最后,第六部分涉及Java的互操作、測試、在Spring中使用Kotlin,以及使用Kotlin編寫Android應用程序。
以下是每章所涵蓋的內容。
在第1章中,我們將了解使用Kotlin的原因,下載必要的工具,并開始編寫代碼。
從Java轉為Kotlin的程序員在開始學習Kotlin的新特性和不同之處之前,需要先忘卻一些實踐和語法。我們將在第2章介紹這些內容。
在Kotlin中,函數是“一等公民”,該語言提供了很多內容,比如默認參數、命名參數和可變參數。
第3章將探索這些與函數相關的功能。
在命令式編程中,我們經常使用外部迭代器。
第4章介紹Kotlin的迭代器如何使任務變得可以忍受,以及參數匹配語法如何從條件語句中消除大量的干擾。
我們在編程時廣泛使用集合。
第5章將向你展示如何使用視圖接口來處理Kotlin的JDK集合。
Kotlin有一個健全的類型系統(tǒng),它的編譯時類型檢查超出了我們對靜態(tài)類型語言的期望。
第6章將介紹Kotlin的基本類型、可空和不可空引用、智能類型轉換等。
盡管在語義上是等價的,但在Kotlin中創(chuàng)建類與在Java中創(chuàng)建類是完全不同的。
第7章將學習創(chuàng)建單例、類、伴生對象,以及使用數據類的原因。
Kotlin處理繼承的方式與Java中使用繼承的方式有很大不同。默認情況下類是final的,并且該語言設置了一些規(guī)則來改進類型的安全性和編譯時的檢查。我們將在第8章中深入探討這個主題。
作為直接支持委托的語言之一,Kotlin提供了一些內置的委托,并且使創(chuàng)建自定義委托變得更加容易。
第9章將首先討論何時以及為何使用委托,然后深入討論如何使用委托。
第10章將學習如何創(chuàng)建lambda表達式和編寫高階函數。我們還將介紹Kotlin提供的用來消除函數調用開銷并提高性能的工具。
內部迭代器提供了流暢性,而序列給了我們效率。我們將在第11章中介紹對迭代和處理對象集合應用函數風格。
第12章將展示Kotlin用于創(chuàng)建簡潔、流暢、優(yōu)雅和富于表現力的代碼的許多能力。
第13章介紹如何創(chuàng)建內部DSL,為你的專用語言定義你自己的語法。
Kotlin是JVM上為數不多的提供尾調用優(yōu)化的語言之一。
我們將在第14章中看到它的實際應用,以及使用記憶來降低計算的復雜性。
協程是Kotlin 1.3中的一個穩(wěn)定特性,它與延續(xù)一起為異步編程提供了基礎架構。協程和延續(xù)的基礎知識在第15章中進行介紹。
第16章介紹應用協程來創(chuàng)建實際的應用程序,這些應用程序可以從異步程序執(zhí)行中獲益。
Kotlin可以運行在不同的平臺上,包括Java虛擬機。
在第17章中,你將學習如何將Kotlin與Java混合使用,如何在Java的現代版本中使用Kotlin—即使用Java模塊,如何將其與Maven和Gradle一起使用,以及如何在同一個應用程序中順利地使用Java和Kotlin。
盡管Kotlin編譯器會捕獲到一些錯誤,自動化測試對于可持續(xù)敏捷開發(fā)來說還是一個必不可少的實踐。第18章介紹如何創(chuàng)建單元測試以及度量代碼覆蓋率。
第19章將探索面向Kotlin程序員的Spring庫以及這些庫所提供的獨特功能。
最后,在第20章中,我們將使用Kotlin創(chuàng)建一個與后端服務對話的Android應用程序。
本書所使用的Kotlin和Java版本
要運行本書中的示例,需要Kotlin 1.3和Java 1.6或更高版本。盡管大多數示例也適用于早期版本的Kotlin,但有些示例需要使用Kotlin 1.3。Java互操作章節(jié)中的示例需要Java 9或更高版本。第1章會提供所需工具的下載說明。
如何閱讀代碼示例
本書中的大多數示例都是用Kotlin腳本編寫的,因此你可以輕松地將它們作為單個文件運行,而無須顯式編譯。如果需要編譯和其他步驟,會在代碼旁邊提供說明。
為了節(jié)省篇幅,我們會在println()命令的同一行或下一行上,將一段代碼的輸出顯示為注釋行。只有少量注釋是用于說明代碼的某些內容,而不是顯示預期的輸出。
Venkat Subramaniam博士是一位獲獎作家,Agile Developer公司的創(chuàng)始人,休斯敦大學的教學型教授。他在北美洲、歐洲和亞洲培訓和指導了數千名軟件開發(fā)人員,并定期應邀在國際會議上發(fā)言。他是多本書的作者(合著者),包括2007年獲得Jolt Productivity獎的Practices of an Agile Developer一書。
第1章 你好Kotlin1
1.1 愛上Kotlin的理由2
1.1.1 多范式編程3
1.1.2 具有類型推斷的靜態(tài)類型4
1.2 為什么選擇Kotlin5
1.3 帶Kotlin去兜兜風5
1.3.1 安裝Kotlin SDK6
1.3.2 驗證安裝6
1.4 編譯成字節(jié)碼并運行7
1.4.1 在命令行上運行7
1.4.2 在IDE中運行8
1.4.3 使用REPL進行實驗8
1.4.4 作為腳本運行9
1.5 編譯成其他目標11
1.6 選擇哪個選項11
1.7 本章小結12
【第一部分 使用Kotlin編寫腳本】
第2章 從Java角度了解Kotlin的基本知識14
2.1 減少輸入15
2.1.1 分號是可選的15
2.1.2 變量類型規(guī)范是可選的15
2.1.3 類和函數是可選的17
2.1.4 try-catch是可選的18
2.2 合理的警告19
2.3 選擇val而不是var20
2.4 改進的相等性檢查21
2.5 字符串模板23
2.6 原始字符串24
2.6.1 沒有轉義24
2.6.2 多行字符串24
2.7 更多的表達式,更少的語句26
2.8 本章小結28
第3章 使用函數29
3.1 創(chuàng)建函數30
3.1.1 KISS函數30
3.1.2 返回類型和類型推斷30
3.1.3 所有的函數都是表達式31
3.1.4 定義參數32
3.1.5 帶有塊體的函數33
3.2 默認參數和命名參數34
3.2.1 演化帶有默認參數的函數34
3.2.2 使用命名參數提高可讀性35
3.3 vararg和spread37
3.3.1 可變數量的實參37
3.3.2 spread運算符38
3.4 解構39
3.5 本章小結40
第4章 外部迭代和參數匹配42
4.1 范圍與迭代43
4.1.1 范圍類43
4.1.2 正向迭代43
4.1.3 反向迭代44
4.1.4 跳過范圍內的值44
4.2 遍歷數組和列表45
4.3 何時應該使用when47
4.3.1 when用作表達式47
4.3.2 when用作語句49
4.3.3 when和變量的作用域49
4.4 本章小結50
第5章 使用集合51
5.1 集合的類型51
5.1.1 Kotlin所添加的便利方法52
5.1.2 視圖53
5.2 使用Pair和Triple53
5.3 對象和基元數組55
5.4 使用列表56
5.5 使用集合59
5.6 使用映射59
5.7 本章小結61
第6章 使用類型安全性解決問題63
6.1 Any和Nothing類64
6.1.1 Any是基類64
6.1.2 Nothing比void更深入65
6.2 可空的引用65
6.2.1 null是件不好的事66
6.2.2 使用可空類型67
6.2.3 安全調用運算符69
6.2.4 Elvis運算符69
6.2.5 不要使用不安全的斷言運算符70
6.2.6 使用when71
6.3 類型檢查和轉換72
6.3.1 類型檢查72
6.3.2 使用is72
6.3.3 智能轉換73
6.3.4 使用帶有when的類型檢查和智能轉換75
6.4 顯式類型轉換75
6.5 泛型:參數類型的變化和約束77
6.5.1 類型不變性77
6.5.2 使用協變79
6.5.3 使用逆變81
6.5.4 使用where的參數類型約束82
6.5.5 星投影83
6.6 具體化的類型參數84
6.7 本章小結86
【第二部分 面向對象的Kotlin】
第7章 對象和類88
7.1 對象和單例88
7.1.1 帶有對象表達式的匿名對象89
7.1.2 帶有對象聲明的單例91
7.1.3 頂級函數與單例92
7.2 創(chuàng)建類93
7.2.1 最小的類94
7.2.2 只讀屬性94
7.2.3 創(chuàng)建實例94
7.2.4 讀寫屬性95
7.2.5 底層探秘—字段和屬性95
7.3 伴生對象和類成員102
7.3.1 類級別成員102
7.3.2 訪問同伴103
7.3.3 Companion作為Factory103
7.3.4 不是非常靜態(tài)的104
7.4 創(chuàng)建泛型類105
7.5 數據類106
7.6 本章小結108
第8章 類層次結構和繼承110
8.1 創(chuàng)建接口和抽象類110
8.1.1 創(chuàng)建接口111
8.1.2 創(chuàng)建抽象類113
8.1.3 是接口還是抽象類113
8.2 嵌套類和內部類114
8.3 繼承116
8.4 Sealed類119
8.5 創(chuàng)建和使用枚舉120
8.6 本章小結122
第9章 通過委托進行擴展124
9.1 何時選擇委托而不是繼承125
9.2 使用委托進行設計126
9.2.1 一個設計問題126
9.2.2 繼承的錯誤指向127
9.2.3 委托—艱難的方式128
9.2.4 使用Kotlin的by來進行委托129
9.3 委托給一個參數130
9.4 處理方法沖突131
9.5 Kotlin委托的注意事項133
9.6 委托變量和屬性135
9.6.1 委托變量135
9.6.2 委托屬性137
9.7 內置的標準委托139
9.7.1 有點兒懶惰也沒關系140
9.7.2 Observable委托141
9.7.3 行使你的可否決權利142
9.8 本章小結143
【第三部分 函數式Kotlin】
第10章 使用lambda進行函數式編程146
10.1 函數式風格146
10.1.1 什么是函數式風格147
10.1.2 為什么以及何時使用函數式風格148
10.2 lambda表達式149
10.2.1 lambda的結構149
10.2.2 傳遞lambda150
10.2.3 使用隱式參數151
10.2.4 接收lambda151
10.2.5 用lambda作為最后一個參數151
10.2.6 使用函數引用152
10.2.7 函數返回函數154
10.3 lambda和匿名函數155
10.4 閉包和詞法作用域157
10.5 非局部和帶標簽的return158
10.5.1 默認情況下不允許使用return 158
10.5.2 帶標簽的return159
10.5.3 非局部return161
10.6 帶有l(wèi)ambda的內聯函數163
10.6.1 默認情況下沒有內聯優(yōu)化163
10.6.2 內聯優(yōu)化164
10.6.3 對參數精心選擇noinline 165
10.6.4 內聯lambda中允許非局部return166
10.6.5 crossinline參數167
10.6.6 inline和return的良好實踐168
10.7 本章小結169
第11章 內部迭代和延遲計算170
11.1 外部迭代器與內部迭代器171
11.2 內部迭代器172
11.2.1 filter、map和reduce172
11.2.2 得到第一個和最后一個174
11.2.3 flatten和flatMap175
11.2.4 排序177
11.2.5 將對象進行分組177
11.3 延遲計算序列178
11.3.1 使用序列提高性能179
11.3.2 無限序列181
11.4 本章小結183
【第四部分 優(yōu)雅且高效的Kotlin】
第12章 Kotlin的流暢性186
12.1 重載運算符187
12.2 使用擴展函數和屬性進行注入190
12.2.1 使用擴展函數注入方法190
12.2.2 使用擴展函數注入運算符191
12.2.3 使用擴展屬性注入屬性192
12.2.4 注入第三方類192
12.2.5 注入靜態(tài)方法195
12.2.6 從類內注入195
12.3 擴展函數197
12.4 帶中綴的函數流暢性198
12.5 帶Any對象的流暢性199
12.5.1 四種方法的行為200
12.5.2 來自冗長和混亂的代碼201
12.5.3 使用apply刪除重復的引用202
12.5.4 使用run獲得結果203
12.5.5 使用let將對象作為參數傳遞203
12.5.6 使用also將void函數鏈接起來205
12.6 隱式接收方206
12.6.1 傳遞一個接收方206
12.6.2 帶接收方的多個作用域207
12.7 本章小結209
第13章 創(chuàng)建內部DSL210
13.1 DSL的類型和特征211
13.1.1 外部DSL與內部DSL211
13.1.2 語境驅動和流暢211
13.2 用于內部DSL的Kotlin211
13.2.1 分號可選212
13.2.2 點和圓括號不與中綴在一起212
13.2.3 使用擴展函數獲得特定的域212
13.2.4 傳遞lambda不需要圓括號213
13.2.5 隱式接收方影響DSL的創(chuàng)建213
13.2.6 還有一些特性可以幫助DSL214
13.3 構建流暢性方面的挑戰(zhàn)214
13.3.1 使用擴展函數215
13.3.2 使用接收方和中綴216
13.4 類型安全構建器220
13.4.1 HTML構建器220
13.4.2 XML構建器222
13.5 使用作用域控制來縮小訪問范圍225
13.6 本章小結227
第14章 編寫遞歸和記憶228
14.1 遞歸的威力和危險228
14.2 尾調用優(yōu)化230
14.3 記憶232
14.3.1 重復計算233
14.3.2 記憶—Kotlin中的Groovy方法234
14.3.3 記憶作為委托235
14.4 將記憶應用于動態(tài)規(guī)劃237
14.5 本章小結238
【第五部分 編寫異步應用程序】
第15章 探索協程242
15.1 協程和并發(fā)242
15.1.1 并行與并發(fā)243
15.1.2 協程作為協作函數243
15.2 使用協程并發(fā)運行244
15.2.1 從順序執(zhí)行開始244
15.2.2 創(chuàng)建一個協程245
15.2.3 啟動一個任務246
15.2.4 與掛起點交錯調用247
15.3 協程上下文和線程249
15.3.1 顯式設置上下文249
15.3.2 在自定義池中運行250
15.3.3 在掛起點后切換線程251
15.3.4 修改CoroutineContext253
15.4 調試協程254
15.4.1 async 和await255
15.4.2 看一眼延續(xù)256
15.5 創(chuàng)建無限序列258
15.5.1 使用序列258
15.5.2 使用iterator函數259
15.6 本章小結261
第16章 異步編程262
16.1 非阻塞異步編程262
16.1.1 按順序開始262
16.1.2 進行異步264
16.2 異常處理266
16.2.1 啟動和異常266
16.2.2 異步和異常268
16.3 取消和超時270
16.3.1 取消協程270
16.3.2 請勿打擾273
16.3.3 雙向取消274
16.3.4 監(jiān)督作業(yè)275
16.3.5 編程時使用超時276
16.4 本章小結277
【第六部分 互操作和測試】
第17章 將Java與Kotlin混合使用280
17.1 聯合編譯280
17.2 從Kotlin調用Java283
17.3 從Java調用Kotlin286
17.3.1 使用Java中的重載運算符287
17.3.2 創(chuàng)建靜態(tài)方法288
17.3.3 傳遞lambda289
17.3.4 添加throws子句290
17.3.5 使用帶默認參數的函數292
17.3.6 訪問頂級函數293
17.3.7 更多注釋294
17.4 本章小結294
第18章 使用Kotlin進行單元測試296
18.1 被測試的代碼296
18.2 獲取項目文件297
18.2.1 設置Gradle298
18.2.2 設置Maven300
18.3 從Canary測試開始300
18.4 編寫經驗測試301
18.5 編寫數據驅動的測試304
18.6 模擬依賴項305
18.6.1 創(chuàng)建交互測試306
18.6.2 測試解析數據308
18.7 測試頂級函數310
18.8 測試協程和異步調用313
18.9 與服務集成316
18.10 查看代碼覆蓋率317
18.11 將應用程序用于驅動318
18.12 本章小結319
第19章 使用Kotlin編寫Spring應用程序320
19.1 創(chuàng)建一個Starter項目320
19.2 創(chuàng)建一個控制器322
19.3 創(chuàng)建一個實體類324
19.4 創(chuàng)建一個存儲庫接口325
19.5 創(chuàng)建一個服務326
19.6 將服務與控制器集成327
19.7 繼續(xù)實踐329
19.8 本章小結330
第20章 使用Kotlin編寫Android應用程序331
20.1 創(chuàng)建一個項目331
20.2 定義域對象333
20.3 創(chuàng)建布局335
20.4 實施活動337
20.5 更新RecyclerView341
20.6 查看應用程序的運行情況343
20.7 本章小結344
附錄1 轉換為JavaScript346
附錄2 Kotlin/Native350
附錄3 Kotlin到WebAssembly353
參考文獻357