Dive Into Kotlin(一):初探 Kotlin

ScalaCool發表於2017-11-06

本文由 Prefert 發表在 ScalaCool 團隊部落格。

在今年的 Google I/O 大會上,Google 宣佈在 Android 上為 Kotlin 提供一等支援(轉為正房)。

在 Andorid 開發的圈子中,這無疑掀起了軒然大浪。對部分人來說,也許這是第一次聽到 Kotlin 。事實上,在 2011 年 7 月,JetBrains 就推出 Kotlin 專案,直到去年 2 月 Kotlin v1.0 才正式釋出。

本系列文章「Dive Into Kotlin」將會對 Kotlin 進行較為系統的介紹,大致分為四個章節:

1. 熱身 —— Kotlin 基本特性
2. 下水 —— Kotlin 與函式式
3. 潛入 —— Kotlin 核心
4. 遨遊 —— kotlin 與 Android 實戰

本文將簡單介紹 Kotlin 的生態和部分語言功能,目錄如下:

  • Kotlin 是一門怎麼樣的語言
  • 強大的生態圈
  • 基本特徵

Kotlin 是一門怎麼樣的語言?

Kotlin 是一種在 JVM 上執行的靜態型別程式語言,可以編譯成 Java 位元組碼,也可以編譯成 JavaScript,方便在沒有 JVM 的裝置上執行。

Kotlin 核心的目標

  • 簡約:幫你減少實現同一個功能的程式碼量。

  • 易懂:讓你的程式碼更容易閱讀,同時易於理解。

  • 安全:移除了你可能會犯錯誤的功能。

  • 通用:基於 JVM 和 JavaScript,你可以在很多地方執行。

  • 互操作性: Kotlin 和 Java 可以相互呼叫,同時 Jetbrains 的目標是讓他們 100% 相容。
    對比 Java,Kotlin 或許顯得有點年輕,但這並不代表它的生態圈不夠穩定。

強大的生態圈

Kotlin 編譯為 JVM 位元組碼或 JavaScript
它可以吸引所有使用垃圾回收機制語言的程式設計師,包括 Java,Scala,Go,Python, Ruby 和 JavaScript。

kotlin 產自工業,而不是學術界。
它解決了程式設計師目前所面臨的一些問題。舉個例子:型別系統可以幫助你避免空指標異常。當我們在使用一些 API 或者大型庫時判斷是否為 null,往往沒有什麼實際作用。

Kotlin 完美相容 Java
在 Idea 中,你可以一鍵實現 Java 與 Kotlin 的轉換。也就是說, Kotlin 寫的專案中可以使用所有現有的 Java 框架和庫,甚至是依賴於註解的高階框架,並且它整合了 Maven,Gradle 和其他構建工具——幫助我們實現無縫的互操作。

Kotlin 相對入門簡單
所以正如大家所說的那樣,Kotlin 是一門十分友好的語言,你甚至可以花幾個小時閱讀下相關書籍就能入門。它的語法簡潔直觀,也許大多時候看起來比較像 Scala,實際上簡單了很多。這種語言很好地平衡了簡潔和可讀性。

不施加執行時間的開銷
標準庫是比較小的:主要是對 Java 標準庫的重點擴充套件。大量使用編譯時內聯(compile-time inlining)就意味著像 mapfilterreduce 這樣的語法編譯起來與命令式的相似。

Android擴充套件庫
Ankokovenant 讓 Kotlin 在 Android 的開發中更加方便,如果你看過這兩個庫,一定也為之青睞。

除 Android 外,其實企業級別的 Java 專案也可以考慮使用 Kotlin:

  1. 它有一個成熟的公司強大的商業支援,JetBrains 致力於該專案的發展,擁有一支高效的團隊和穩定的商業模式。在較長的時間內,你都不用擔心 Kotlin 被拋棄。

  2. Kotlin 的風險很低:可以由一兩個成員嘗試在某個功能塊使用,但並不會影響其他模組:Kotlin 類可以匯出一個與常規 Java 程式碼看起來相同的 Java API。

  3. Java 6 廢土中的一線希望:如果升級 JVM 對於你們的成本很高,你可以使用 Kotlin,它是「加強版的 Java 6」。

看完生態圈,來看看最吸引我們的語言功能部分。

特徵

kotlin&&Android

屬性前置

Java Bean 中總是出現一些重複工作量的程式碼:

public class Customer{
  String name;
  int age;

  public Customer(String name, int age){
    this.name=name;
    this.age=age;
  }
  
  public String getName(){
    return name;
  }
  
  public int getAge(){
    return age;
  }
  
  public setName(String name){
    this.name=name;
  }
  public setAge(int age){
   this.age=age;
  }
}
複製程式碼

在 Java 物件中,建構函式和屬性的 GetterSetter 函式在每個Bean類中都會出現,看起來非常冗餘。

但是使用 Kotlin,程式碼是這樣的:

data class Customer(val name:String, val age:Int)
複製程式碼

Kotlin 將GetterSetter 等函式省略,讓我們更加關注屬性。

函數語言程式設計是變革的關鍵

如果你是一名 「FP」 (Functional Programming) 愛好者,你肯定知道 Scala 這門語言。而 Kotlin 的設計初衷就是提供 Scala 裡的很多特性,但不被編譯時間束縛。

FP

網上對函數語言程式設計的介紹,大多數對初學者都是不夠友好的,下面是一種比較簡潔的概括:

函式程式設計以基於數學的函式構成,實現一個功能時傾向於實現的目標,而不是實現目標的方式。

也就是說,函數語言程式設計處理的是不可變的資料,即不會改變變數的值。它所做的只是 Receive(接收)-> Compute(計算)-> Return(返回) ,而不改變它接收到的值,或者引起「副作用」

Kotlin 重新定義了函式的寫法

  • 簡化函式過載。
  • 命名引數不遵循順序:命名引數允許完全控制什麼值被傳遞給變數,並在與布林處理,舉個例子:
// Java
void check(boolean isAlpha, boolean isNum){
	// do something
}
check(true, false); // 函式呼叫

// Kotlin
fun check(isAlpha:Boolean, isNum:Boolean = false) {
   // do something
}
check(true)// 1
check(true,true)// 2
check(isAlpha = true, isNum = false) // 3
check(isNum = false, isAlpha = true) // 4
複製程式碼

其中1、3、4實際效果一致。

函式可讀性

  • 單行表示式是提高程式碼可讀性的第一步。
// Java
int sum (int x, int y){ // 必須宣告返回型別
  x = x + y; // x的值被改變,帶來副作用
  return x;
}

// kotlin
fun sum(x: Int, y: Int) = x + y // 完美
複製程式碼

在 Android 開發時,我們應該都會對檢視的 onClick 事件感到煩躁。

// Java
view.setOnClickListener(new View.OnClickKistener() {
  @ Override
  public void onClick(View v){
    System.out.println("sad");
  }
});
複製程式碼

在 kotlin 中,這也得到簡化:

view.onClick {
  println("nice !!")
}
複製程式碼

型別安全

在 Android 開發中,出現 NullPointerException 已經可以說是家常便飯了。但如果在執行的時候出現這個異常導致程式崩潰,對使用者體驗造成的損失是巨大的。

Kotlin 能很好的避免這個問題:

  • 指定 null
// Java
String text1 = null // NE  

// Kotlin
var text1: String = "Kotlin"// 正常
var text2: String = null // NE
var text3: String ?= null // 正常
複製程式碼

Kotlin 中只有加了 ? 才允許為 null。

  • 檢查 null Kotlin 可以通過 ?確保安全呼叫:
// Java
if(a != null){
  int x = a.length();
}
// Kotlin
val x = a?.length // 僅當 a 不為 null 時才能通過編譯
複製程式碼
  • 為 null 時預設值
val x = b?.length ?: 0 // 如果 b 為 null,那他的 length 就為0
val x = b?.length ?: throw NullPointerException()
val x = b!!.length    
複製程式碼

Lambda 優化

Lambda 表示式增加了 Kotlin 的簡潔功能,從而也讓程式碼更容易理解。(Java 6 不支援 lambda )

val sum = {x: Int, y: Int -> x + y} // 型別:(Int, Int) -> Int
val result = sum(2, 7// result == 9
複製程式碼

條件判斷更優雅

kotlin 中 when 同樣能帶給你驚喜,你可以用它簡化 if..elseswitch

// Java
if(x == 1) println("x is 1");
else if(x == 2) println("x is 2");
else if(x == 3 || x == 4) println("x is 3 or 4");
else if(x >= 5 || x <= 10) println("x is 5, 6, 7, 8, 9, or 10");
else println("x is out of range");

// Kotlin
when (x) {
  1 -> print("x is 1")
  2 -> print("x is 2")
  3, 4 -> print("x is 3 or 4")
  in 5..10 -> print("x is 5, 6, 7, 8, 9, or 10")
  else -> print("x is out of range")
}
複製程式碼

當然除了以上這些,Kotlin 還有許多令人驚喜的特性,將會在後續的文章中詳細介紹,敬請期待。

Dive Into Kotlin(一):初探 Kotlin

相關文章