Kotlin 101

Nekocode發表於2018-12-26

Kotlin 簡介

2011 年,作為全球最先進 IDE 開發商之一的 JetBrains 揭露了一項正處於開發中的程式語言 —— Kotlin。它是一門跑在 JVM 上,和 Java 間具有高互操作性的全新語言。JetBrains 通過多年來和各種程式語言打交道的經驗,為 Kotlin 整合了多項現代程式語言特性。

2017 年,Google 在 I/O 大會上宣佈將 Kotlin 作為 Android 開發的官方支援語言。彼時,Kotlin 的開發者社群開始了爆炸性的增長,而 Netflix、Pinterest、Trello、Kickstarter 等知名公司也早已開始使用 Kotlin。

2018 年,目前 Kotlin 1.3 正式版本已經發布,更多的語言特性得到了支援。而隨著官方提供了更多的編譯後端,也讓 Kotlin 擺脫了 JVM 的束縛,使用 Kotlin 編寫的程式碼可以編譯成機器碼甚至 JavaScript 而跑在不同的執行環境中。另外,根據 Google 官方的調查,目前已有 40% 的 Android 開發者選擇使用 Kotlin 進行程式設計工作,國內抖音、網易有道詞典、大眾點評、知乎等大量應用也開始引入 Kotlin。

使用 Kotlin 有什麼好處?

既然 Google 已經宣佈 Kotlin 成為 Android 開發的官方支援語言,也說明了至少在 Android 開發上使用 Kotlin 目前已經毫無障礙了。那麼作為 Android 開發者,對比 Java 而言,使用 Kotlin 語言能獲得什麼好處呢?

第一點,使用 Kotlin 能夠讓我們的程式碼變得更簡潔。我們都知道 Java 以它語法的嚴謹性而著名,它支撐起了世界上各種大型、複雜的計算機軟體。然而 ,它的語法是有歷史包袱而且略顯囉嗦的,對比更靈活的現代語言,使用 Java 來實現同樣的邏輯通常需要寫更多的程式碼。而沒有歷史包袱的 Kotlin 則吸取了現代語言各種靈活簡潔的語法,讓開發者在 JVM 上也能寫出簡潔的程式碼:

// Java
final ArrayList<String> a = new ArrayList<>();
// Kotlin
val a = ArrayList<String>()

// Java
public String b(String c) {
    return "Test: " + c.substring(2);
}
// Kotlin
fun b(c: String) = "Test: ${c.substring(2)}";
複製程式碼

除了語法上的各種簡便,Kotlin 的標準庫也提供了很多實用的方法來精簡你的程式碼,例如針對開發中最常用的「集合」,Kotlin 提供了封裝讓你可以輕鬆建立集合類、使用和 Java Stream 相似但更豐富的介面來操作集合:

// 建立包含元素 1、3、5、7 的 ArrayList
arrayListOf(1, 3, 5, 7)
        // 過濾出集合中大於 3 的元素
        .filter { it > 3 }
        // 轉換成字串
        .map { "$it, " }
        // 迴圈輸出
        .forEach { println(it) }
複製程式碼

更多 Kotlin 比 Java 語法更精簡的例子可以檢視 From Java to Kotlin

第二點,使用 Kotlin 能讓你的程式更安全。Java 工程師最常見陷阱之一就是訪問了空的引用而導致空指標異常,而 Java 在語法上無法描述某個引用是否可空,所以開發者要揹負起更多的心智負擔而不得不經常進行判空操作。雖然目前可以通過 Annotation + IDE 提示的方式來一定程度上減輕這個負擔,但這並不是一個強約束,在 IDE 上的提示是可被忽略的。

而 Kotlin 在語法上對此進行了強約束。在 Kotlin 中定義某個引用時必須描述其是否為可空型別,對於可空型別引用的不安全訪問會在編譯期報錯:

// 不可空型別,可以直接訪問
val a: String = ""
a.substring(2)

// 可空型別
val b: String? = null
b.substring(2) // 不安全訪問,編譯報錯
複製程式碼

這有利於在執行前察覺並處理可能的空指標異常。而且 Kotlin 還提供了 ?.?:、型別自動轉換等便捷的語法來輔助處理可空型別:

val b: String? = null
b?.substring(2) // 當 b 不為空時才呼叫 substring()
if (b is String) {
    b.substring(2) // 自動把 b 轉換成不可空型別
}
val c = b ?: "" // 如果 b 為空的話,則返回 ?: 操作符右邊的值
複製程式碼

以上兩點是 Kotlin 能給大多數 Java 開發者帶來的直接好處。但 Kotlin 能給開發者帶來的也不僅僅只有這些,它有著完美的 IDE 支援(這也正是 JetBrains 的強處),它與 Java 之間的高互操作性讓你可以輕鬆使用 Java 生態中豐富的庫,而它對各種現代語言新特性(例如協程、函數語言程式設計)的支援,能讓你在面對不同的計算機問題時有更多不同的思考和解決方式。

必須知道的一些缺點

我們要知道,任何程式語言在設計時都需要做各種取捨。Kotlin 在提供高靈活性的背後也需要開發者付出一定的代價:

  • 語法糖過多,加重開發者心智負擔;
  • 部分語法糖,例如 Extensions,會破壞程式碼的可閱讀性;
  • 靈活性過高,不同的開發者容易產生不同的表達偏好;
  • 過度依賴 IDE,脫離 IDE 可能讓程式碼難以閱讀和維護。

實際上這也是大多數語法靈活、語法糖多的語言的共同問題。但我們不必過於擔心,通過使用強大的 IDE 和建立程式碼規範這些問題都能被解決。作為開發者,我們應該把精力放在用更少的程式碼、更快、更方便地描述出我們想要的「邏輯」上,其他的負擔都交給編譯器或 IDE 吧,這也正是高階程式語言誕生的初衷。

作為 Android 開發者是否應該學習 Kotlin

總所周知,由於 Google 和 Oracle 之間的各種政治鬥爭,導致 Android 開發者一直以來只能用上閹割版的 Java。大部分開發者甚至是最近幾年才開始用上、甚至開始知道 Lambda 表示式,而像 Stream 之類的工具更是無人知曉。雖然期間有傳聞過要支援 Go 和 Dart 語言,但很快也都音訊全無了。

而 Kotlin 的出現正好彌補了 Android 開發生態中一塊巨大的短板 —— 落後的開發語言。而且,Kotlin 和 Java 十分相似(甚至很多人把它認為是 Java 的增強版),所以從 Java 過渡到 Kotlin 的門檻比起其他語言來說相對更低。而基於 JVM 又讓 Kotlin 的程式碼可以很輕鬆地執行在 Android 平臺上。這麼看來,Kotlin 確實比起 Google 自己的 Go 和 Dart 來說更適合作為 Android 平臺的開發語言,也難怪 Google 最終敲定 Kotlin。

縱觀未來,隨著 Google 和 JetBrains 深度的合作,Kotlin 也肯定會成為 Android 開發生態中最先進的工具之一。目前通過 Kotlin Android Extensions 已經可以很方便地在 Activity 中直接通過 Id 名來直接訪問對應的 View:

import kotlinx.android.synthetic.main.activity_main.*

// 設定 id 為 helloTextView 的 TextView 的文字
helloTextView.text = "Hello World!"
複製程式碼

而 Google 官方推出的 KTX 庫 更是讓開發者能夠更方便地使用 Kotlin 來開發 Android 應用:

// 使用 KTX 前
view.viewTreeObserver.addOnPreDrawListener(
    object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            viewTreeObserver.removeOnPreDrawListener(this)
            actionToBeTriggered()
            return true
        }
    }
)

// 使用 KTX 後
view.doOnPreDraw {
     actionToBeTriggered()
}
複製程式碼

另外一個好訊息是,今年 11 月剛釋出的 Gradle 5.0 也宣佈支援了 Kotlin DSL,這意味著我們甚至可以用 Kotlin 來寫我們的構建指令碼了:

android {
    compileSdkVersion(27)
    defaultConfig {
        applicationId = "com.test.app"
        minSdkVersion(15)
        targetSdkVersion(27)
        versionCode = 1
        versionName = "1.0"
    }
}
複製程式碼

所以從各種跡象來看,答案其實已經很明顯了。Kotlin 的誕生以及被 Google 的欽點,對一直以來被語言限制生產力的 Android 開發者們而言意義非凡。而就 Google 和 JetBrains 的影響力來看,未來幾年 Kotlin Android 開發者的數量將呈爆炸式增長,市場對於 Kotlin 工程師的需求也將會不斷增加。所以,學習 Kotlin 不但能讓你接觸到更先進的工具、思想,也肯定能讓你在人才市場上更具競爭力。

事實上,根據 Github 今年發表的 Octoverse 報告 ,Kotlin 已經成為增長速度最快的語言。

先嚐試一下吧

如果你已經對 Kotlin 產生興趣,可以先通過官方的 Playground 來線上嘗試下 Kotlin 的語法。它還包括一些列用於演示各種語法的例項,以及一個完整的語法課程。

如果你想在本地建立一個全新的使用 Kotlin 編寫的 Android 應用專案,參照官方文件中的 Getting started with Android and Kotlin 來進行即可,目前 Android Studio 已經完全支援 Kotlin 語言。

而如果你想在一個使用 Java 的 Android 應用專案中同時使用 Kotlin,也是完全沒問題的。通過上一個連結的教程引入 Kotlin Gradle Plugin,即可在你的原始碼目錄下通過 Android Studio 選單直接建立 Kt 原始碼檔案。

有人可能會擔心使用過程中遇到各種坑 。實際上,筆者在 2015 年就開始使用 Kotlin 了,期間在語法、IDE 支援、Kotlin 註解處理器上都遇到官方不少的坑,但由於官方的迭代速度足夠快,很多問題很快就被修復了。另外,Kotlin 的社群也十分活躍,如果遇到坑或者問題也基本都能在上面找到回答。

而自從 16 年 Kotlin 1.0 釋出之後的版本就更加穩定了,工具鏈、IDE 支援也都十分完善。所以大可不必擔心會遇到無法解決的坑。

最後說點什麼

有科學家表明,使用不同的自然語言會影響人的思考方式。而程式設計,亦是如此。激進的 Kotlin 和保守的 Java 之間的差異,肯定會給我們帶來不一樣的思考問題的方式。而這些不一樣,也肯定會影響未來 Android 開發的新風向。

在筆者看來,Android 開發界隨著 Kotlin 的出現實際上已經到了一個新的紀元,浪潮已來,為了不被浪潮所擊退,請用力擁抱 Kotlin 吧!

相關文章