Android開(kāi)發(fā)者自述:為什么我要改用Kotlin?
寫(xiě)在前面的話(huà),作為一個(gè)不熬夜的人,一覺(jué)醒來(lái)發(fā)現(xiàn) Kotlin 成為了 Android 的官方語(yǔ)言,可謂是大喜過(guò)望。為了趁熱打鐵,我決定提前三天放出原定本周日 Release 的文章。希望能及時(shí)讓大家了解一下 Kotlin。
相信很多開(kāi)發(fā)人員,尤其是 Android 開(kāi)發(fā)者都會(huì)或多或少聽(tīng)說(shuō)過(guò) Kotlin,當(dāng)然如果沒(méi)有聽(tīng)過(guò)或者不熟悉也沒(méi)有關(guān)系。因?yàn)楸酒恼乱约安┛秃笃诘膬?nèi)容會(huì)涉及到很多關(guān)于 Kotlin 的知識(shí)分享。
在寫(xiě)這篇文章前的一個(gè)多月,F(xiàn)lipboard 中國(guó)的 Android 項(xiàng)目確定了正式將 Kotlin 作為項(xiàng)目開(kāi)發(fā)語(yǔ)言,這就意味著新增的代碼文件將以 Kotlin 代碼格式出現(xiàn),而且同時(shí)舊的 Java 代碼也將會(huì)陸陸續(xù)續(xù)翻譯成 Kotlin 代碼。在使用 Kotlin 的這段時(shí)間,被它的簡(jiǎn)潔,高效,快捷等等特點(diǎn)震撼,所以有必要寫(xiě)一篇文章來(lái)談一談 Kotlin 的特性,如若能取得推廣 Kotlin 的效果則倍感欣慰。
Kotlin的「簡(jiǎn)歷」
- 來(lái)自于著名的 IDE IntelliJ IDEA(Android Studio 基于此開(kāi)發(fā)) 軟件開(kāi)發(fā)公司 JetBrains(位于東歐捷克)
- 起源來(lái)自 JetBrains 的圣彼得堡團(tuán)隊(duì),名稱(chēng)取自圣彼得堡附近的一個(gè)小島 (Kotlin Island)
- 一種基于 JVM 的靜態(tài)類(lèi)型編程語(yǔ)言
來(lái)自知名的工具開(kāi)發(fā)商 JetBrains,也就決定了 Kotlin 的基因中必然包含實(shí)用與高效等特征。那我們接下來(lái)看一看 Kotlin 的特點(diǎn),當(dāng)然這也是我改用 Kotlin 的重要原因。
語(yǔ)法簡(jiǎn)單,不啰嗦
- Kotlin 支持類(lèi)型推斷,沒(méi)有 Java 那樣的啰嗦。
- 另外用 var 表示變量,val 表示常量更加的簡(jiǎn)潔
- 方法也很簡(jiǎn)單,連 function 都縮寫(xiě)成了 fun,平添了幾分雙關(guān)之意。
- 類(lèi)的繼承和實(shí)現(xiàn)很簡(jiǎn)單,使用:即可
- Kotlin 每個(gè)句子都不需要加分號(hào) (;)
空指針安全
空指針(NullPointerException 或 NPE)是我們使用 Java 開(kāi)發(fā)程序中最常見(jiàn)的崩潰了。因?yàn)樵?Java 中我們不得不寫(xiě)很多防御性的代碼,比如這樣:
在 Kotlin 中空指針異常得到了很好的解決。
- 在類(lèi)型上的處理,即在類(lèi)型后面加上?,即表示這個(gè)變量或參數(shù)以及返回值可以為 null,否則不允許為變量參數(shù)賦值為 null 或者返回 null
- 對(duì)于一個(gè)可能是 null 的變量或者參數(shù),在調(diào)用對(duì)象方法或者屬性之前,需要加上?,否則編譯無(wú)法通過(guò)。
如下面的代碼就是 Kotlin 實(shí)現(xiàn)空指針安全的一個(gè)例子,而且相對(duì) Java 實(shí)現(xiàn)而言,簡(jiǎn)直是一行代碼搞定的。
關(guān)于空指針安全的原理,可以參考這篇文章研究學(xué)習(xí)Kotlin的一些方法。
支持方法擴(kuò)展
很多時(shí)候,F(xiàn)ramework 提供給我們的 API 往往都時(shí)比較原子的,調(diào)用時(shí)需要我們進(jìn)行組合處理,因?yàn)榫蜁?huì)產(chǎn)生了一些 Util 類(lèi),一個(gè)簡(jiǎn)單的例子,我們想要更快捷的展示 Toast 信息,在 Java 中我們可以這樣做。
但是 Kotlin 的實(shí)現(xiàn)卻讓人驚奇,我們只需要重寫(xiě)擴(kuò)展方法就可以了,比如這個(gè) longToast 方法擴(kuò)展到所有的 Context 對(duì)象中,如果不去追根溯源,可能無(wú)法區(qū)分是 Framework 提供的還是自行擴(kuò)展的。
注意:Kotlin 的方法擴(kuò)展并不是真正修改了對(duì)應(yīng)的類(lèi)文件,而是在編譯器和 IDE 方面做得處理。使我們看起來(lái)像是擴(kuò)展了方法。
Lambda, 高階函數(shù),Streams API, 函數(shù)式編程支持
所謂的 Lambda 表達(dá)式是匿名函數(shù),這使得我們的代碼會(huì)更加的簡(jiǎn)單。比如下面的代碼就是 lambda 的應(yīng)用。
所謂的高階函數(shù)就是:
- 可以接受函數(shù)作為參數(shù)
- 也可以返回函數(shù)作為結(jié)果
舉一個(gè)接受函數(shù)作為參數(shù)的例子。在 Android 開(kāi)發(fā)中,我們經(jīng)常使用 SharedPreference 來(lái)存儲(chǔ)數(shù)據(jù),如果忘記調(diào)用 apply 或者 commit 則數(shù)據(jù)修改不能應(yīng)用。利用 Kotlin 中的高階函數(shù)的功能,我們能更好的解決這個(gè)問(wèn)題:
當(dāng)然這上面的例子中我們也同時(shí)使用了方法擴(kuò)展這個(gè)特性。
Kotlin 支持了 Streams API 和方法引用,這樣函數(shù)式編程更加方便。比如下面的代碼就是我們結(jié)合 Jsoup,來(lái)抓取某個(gè) proxy 網(wǎng)站的數(shù)據(jù),代碼更加簡(jiǎn)單,實(shí)現(xiàn)起來(lái)也快速。
字符串模板
無(wú)論是 Java 還是 Android 開(kāi)發(fā),我們都會(huì)用到字符串拼接,比如進(jìn)行日志輸出等等。在 Kotlin 中,字符串模板是支持的,我們可以很輕松的完成一個(gè)字符串?dāng)?shù)組的組成:
與 Java 交互性好
Kotlin 和 Java 都屬于基于 JVM 的編程語(yǔ)言。Kotlin 和 Java 的交互性很好,可以說(shuō)是無(wú)縫連接。這表現(xiàn)在:
- Kotlin 可以自由的引用 Java 的代碼,反之亦然。
- Kotlin 可以現(xiàn)有的全部的 Java 框架和庫(kù)
- Java 文件可以很輕松的借助 IntelliJ 的插件轉(zhuǎn)成 kotlin
Kotlin 應(yīng)用廣泛
Kotlin 對(duì) Android 應(yīng)用開(kāi)發(fā)支持廣泛,諸多工具,比如 kotterknife(ButterKnife Kotlin 版),RxKotlin,Anko 等等,當(dāng)然還有已經(jīng)存在的很多 Java 的庫(kù)都是可以使用的。
除此之外,Kotlin 也可以編譯成 Javascript。最近使用 Kotlin 寫(xiě)了一段抓取 proxy 的代碼,實(shí)現(xiàn)起來(lái)非??旖?。甚至比純 JavaScript 實(shí)現(xiàn)起來(lái)要快很多。
關(guān)于性能
Kotlin 的執(zhí)行效率和 Java 代碼的執(zhí)行效率理論上一致的。有時(shí)候 Kotlin 可能會(huì)顯得高一些,比如 Kotlin 提供了方法的 inline 設(shè)置,可以設(shè)置某些高頻方法進(jìn)行 inline 操作,減少了運(yùn)行時(shí)的進(jìn)棧出棧和保存狀態(tài)的開(kāi)銷(xiāo)。
讀到這里,是不是想要嘗試一下 Kotlin 呢,它簡(jiǎn)潔的語(yǔ)法,匯集諸多特性,高效率實(shí)現(xiàn)等等,已經(jīng)在國(guó)外風(fēng)生水起,國(guó)外的 Pintereset, Square, Flipboard 等公司已經(jīng)開(kāi)始應(yīng)用到生產(chǎn)中。
關(guān)于轉(zhuǎn)向 Kotlin
其實(shí),我在做決定之前(當(dāng)時(shí) Kotlin 還沒(méi)有被欽定)也曾有過(guò)考慮,是不是選擇了 Kotlin 就意味著放棄 Java 呢,冷靜下來(lái)想一想,其實(shí)并不是那么回事,因?yàn)?Kotlin 與 Java 語(yǔ)法太相近,以及在 Kotlin 中無(wú)時(shí)無(wú)刻不在和 Java 相關(guān)的東西打交道,所以這點(diǎn)顧慮不是問(wèn)題的。
對(duì)于個(gè)人的項(xiàng)目來(lái)轉(zhuǎn)向 Kotlin,通常不是很難的選擇,畢竟 Kotlin 是那么優(yōu)秀的語(yǔ)言,相信很多人還是愿意嘗試并使用這個(gè)事半功倍的語(yǔ)言的。
而比較難抉擇的情況是如果如何讓團(tuán)隊(duì)轉(zhuǎn)用 Kotlin,個(gè)人認(rèn)為團(tuán)隊(duì)難以轉(zhuǎn)用的原因有很多,比如學(xué)習(xí)成本,歷史包袱等等。但其實(shí)根本原因還是思維方式的問(wèn)題,歪果仁喜歡用工具來(lái)提升開(kāi)發(fā)效率,因?yàn)槿肆Τ杀竞芨?。而?guó)內(nèi)團(tuán)隊(duì)提高效率的辦法通常是增加成員。好在 Flipboard 美國(guó)團(tuán)隊(duì)自 2015 年(可能更早)就引入了 Kotlin,因此中國(guó)團(tuán)隊(duì)這邊選用 Kotlin 也更加順?biāo)浦邸.?dāng)然更主要的是目前團(tuán)隊(duì)規(guī)模不大,成員一致認(rèn)可 Kotlin 的優(yōu)點(diǎn)。
關(guān)于團(tuán)隊(duì)轉(zhuǎn)用 Kotlin 的方法,一般比較行得通的辦法是自上而下的推行。這就意味著要么直接的技術(shù)負(fù)責(zé)人比較開(kāi)明要么就是需要有人來(lái)不斷推介來(lái)影響團(tuán)隊(duì)。
做個(gè)比較現(xiàn)實(shí)的比擬,Java 就像是一趟從我的家鄉(xiāng)保定開(kāi)往北京西的耗時(shí)將近 2 個(gè)小時(shí)甚至更長(zhǎng)的普通列車(chē),而 Kotlin 則是那趟僅需 40 分鐘就能到達(dá)的高鐵。通常的人都會(huì)選擇高鐵,因?yàn)樗?jié)省了時(shí)間和提高了體驗(yàn)。這個(gè)時(shí)間和體驗(yàn)對(duì)應(yīng)編程中的,我想應(yīng)該是高效率和高可讀性,可維護(hù)性的代碼。
現(xiàn)在好了,有了 Google 的支持,Kotlin 轉(zhuǎn) Android 相信在不久的將來(lái)就會(huì)全面展開(kāi)。篡改 Python 的一句名言「人生苦短,我用 Kotlin」,這樣一個(gè)高效實(shí)用的語(yǔ)言應(yīng)該會(huì)被越來(lái)越多的團(tuán)隊(duì)所接受,并應(yīng)用到開(kāi)發(fā)生產(chǎn)中。當(dāng)然也希望在國(guó)內(nèi)環(huán)境下大放異彩。
本文作者為 Flipboard 中國(guó) Android 研發(fā)工程師段建華。