1. 程式人生 > >為什麼你必須摒棄 Java ,全面轉向 Kotlin 語言?

為什麼你必須摒棄 Java ,全面轉向 Kotlin 語言?

是時候開始玩一門現代的程式語言了!

為什麼你必須摒棄 Java ,全面轉向 Kotlin 語言?

我想告訴你一個名為 Kotlin 的新的程式語言,以及為什麼你要開始考慮使用它來開發你的下一個專案。我以前喜歡 Java ,但是去年我發現了 Kotlin ,只要有可能我就會用 Kotlin 來寫程式碼。現在我實在無法想象有什麼地方只有 Java 能做,而 Kotlin 不能的。

Kotlin 是 JetBrains 開發的,這是一家開發了一整套 IDEs 的公司,諸如 IntelliJ 和 ReSharper, 還有正在閃耀光芒的 Kotlin。這是一個務實而且簡潔的程式語言,真正讓人感覺身心愉悅的程式語言,而且效率非常高。

儘管 Kotlin 最終編譯成 JavaScript ,很快也將編譯成 機器碼,但我們仍將聚焦於其主要的環境 —— JVM。

這裡有一堆你應該完全轉向 Kotlin 語言的理由:

0# Java 互操作性

Kotlin 是 100% 與 Java 具備互操作性的。你可以使用 Kotlin 繼續你老的 Java 專案開發。所有你熟悉的 Java 框架仍然可用,任何框架,不管是 Kotlin 寫的,還是你固執 Java 小夥伴寫的都可以。

1# 熟悉的語法

Kotlin 不是誕生於學術界的怪異語言。其語法是 OOP 領域的任何開發者都熟悉的,可以或多或少的有一些瞭解。當然和 Java 還是有些不同的,例如重構後的建構函式以及使用 val 的變數宣告等等。下面是一個基本的 Kotlin 示例程式碼:

class Foo { val b: String = "b" // val means unmodifiable
var i: Int = 0 // var means modifiable
fun hello() { val str = "Hello"
print("$str World")
} fun sum(x: Int, y: Int): Int { return x + y
} fun maxOf(a: Float, b: Float) = if (a > b) a else b
}

2# 字串插值

這相當於是更智慧,更具備可讀性的 Java 的 String.format() 方法的 Kotlin 實現:

val x = 4
val y = 7
print("sum of $x and $y is ${x + y}") // sum of 4 and 7 is 11

3# 型別推斷

Kotlin 會自動的對變數的型別進行推斷:

val a = "abc" // type inferred to String
val b = 4 // type inferred to Int
val c: Double = 0.7 // type declared explicitly
val d: List<String> = ArrayList() // type declared explicitly


4# 智慧型別轉換

Kotlin 編譯器會跟蹤你的邏輯程式碼並在需要的時候進行自動的型別轉換,這意味著我們不需要在顯示轉換時做更多的 instanceof 檢查:

if (obj is String) {
print(obj.toUpperCase()) // obj is now known to be a String
}

5# 更直觀的相等性比較

你不再需要呼叫 equals() ,因為 == 操作符也可以用來比較結構的相等性:

val john1 = Person("John")
val john2 = Person("John")
john1 == john2 // true (structural equality)
john1 === john2 // false (referential equality)
6# 預設引數值

不需要像 Java 那樣定義很多包含不同引數的相似方法:

fun build(title: String, width: Int = 800, height: Int = 600) {
Frame(title, width, height)
}

7# 命名引數

結合預設引數值,命名引數可以消除 builders 的使用:

build("PacMan", 400, 300) // equivalent
build(title = "PacMan", width = 400, height = 300) // equivalent
build(width = 400, height = 300, title = "PacMan") // equivalent

8# When 表示式

switch 替換成 when ,程式碼更具可讀性:

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")
}

支援表示式或者是語句,可以是有引數或者無引數:

val res: Boolean = when {
obj == null -> false
obj is String -> true
else -> throw IllegalStateException()
}

9# Properties

可以給公共欄位自定義 set 和 get 行為,這意味著不再會因為那些沒用的 getters & setters 導致程式碼瘋狂膨脹。

class Frame { var width: Int = 800
var height: Int = 600
val pixels: Int
get() = width * height
}

10# Data 類

這是一個 POJO 類,包含 toString(), equals(), hashCode(), 和 copy() 方法,和 Java 不同的是,它不會超過 100 行程式碼:

data class Person(val name: String,
var email: String,
var age: Int)
val john = Person("John", "[email protected]", 112)

11# 操作符過載

可以過載預定義的一組操作符來提升程式碼的可讀性:

data class Vec(val x: Float, val y: Float) {
operator fun plus(v: Vec) = Vec(x + v.x, y + v.y)
}
val v = Vec(2f, 3f) + Vec(4f, 1f)

12# 解構宣告

一些物件是可以解構的,一個很有用的例子就是對 Map 進行迭代:

for ((key, value) in map) {
print("Key: $key")
print("Value: $value")
}

13# Ranges

完全為了可讀性:

for (i in 1..100) { ... }
for (i in 0 until 100) { ... }for (i in 2..10 step 2) { ... }
for (i in 10 downTo 1) { ... }
if (x in 1..10) { ... }

14# 擴充套件函式

還記得你第一次用 Java 實現一個 List 的排序嗎?你找不到一個 sort() 函式,然後你就四處求助,最終找到了 Collections.sort()。後來你需要將一個字串的首字元變成大寫,最終你還是自己寫了一個方法來實現,因為你當時還不知道有這麼個東西 StringUtils.capitalize().

如果只有一種方法可以向已有的類新增新的函式,這樣 IDE 就可以幫助你在程式碼完成時找到正確的函式。在 Kotlin 裡你可以這麼做:

fun String.replaceSpaces(): String {
return this.replace(' ', '_')
}
val formatted = str.replaceSpaces()

標準庫擴充套件了 Java 原來型別的功能,這是字串物件所需要的:

str.removeSuffix(".txt")
str.capitalize()
str.substringAfterLast("/")
str.replaceAfter(":", "classified")

15# Null 安全

Java 是我們應該稱之為是一個幾乎靜態型別的程式語言。Java 的 String 變數型別無法保證它不會等於 null。儘管我們已經習慣了這樣的情況,但它否定了靜態型別檢查的安全性,導致 Java 程式設計師總是活在各種空指標異常的恐懼中。

var a: String = "abc"
a = null // 編譯錯誤
var b: String? = "xyz"
b = null // 正確

Kotlin 強制你必須在訪問一個可為空的型別變數時候必須確保不會發生空指標:

val x = b.length // 編譯錯誤: b 允許為空

雖然看起來有點麻煩,但這的確是 Kotlin 一個微小卻又非常重要的特性。我們仍可以使用智慧的轉換,可以在需要的時候將允許為空的型別轉成不允許為空:

if (b == null) return
val x = b.length // 正確

我們也可以使用安全呼叫方法 ?. 該表示式在 b 為空時返回 null,而不是丟擲空指標異常:

val x = b?.length // type of x is nullable Int

安全呼叫可以連結在一起,以避免像其他語言一樣存在大量巢狀的 if-not-null 檢查,如果我們想要一個預設值而不是 null 時,可以用 ?: 操作符:

val name = ship?.captain?.name ?: "unknown"

如果沒有適合你的,那麼你應該是需要一個空指標了,你將不得不顯式的進行處理:

val x = b?.length ?: throw NullPointerException() // same as below
val x = b!!.length // same as above

16# 更好的 Lambdas

嘿,帥哥,這是一個很好的 Lambda 系統 —— 在完美的可讀性和簡潔之間取得非常好的平衡,這得益於非常聰明的設計選擇。其語法簡單直接:

val sum = { x: Int, y: Int -> x + y } // type: (Int, Int) -> Int
val res = sum(4,7) // res == 11

優點體現在:

如果 lambda 是方法的最後一個引數或者是唯一引數的話,那麼方法的括號可以移動或者省略.
如果我們選擇不去宣告單引數的 lambda 表示式的引數,那麼 Kotlin 會隱式的將之命名為 it.
結合上述優點,下面的三個不同的語句效果一樣:

numbers.filter({ x -> x.isPrime() })
numbers.filter { x -> x.isPrime() }
numbers.filter { it.isPrime() }

這個可以讓你編寫更加簡潔的函式式程式碼,就像下面這樣優雅:

persons
.filter { it.age >= 18 }
.sortedBy { it.name }
.map { it.email }
.forEach { print(it) }

Kotlin 的 lambda 系統和擴充套件函式結合,可以非常棒的用來開發各種 DSL。例如 Anko 這個 DSL 的例子可以增強 Android 的開發:

verticalLayout { padding = dip(30)
editText { hint = “Name”
textSize = 24f
}
editText { hint = “Password”
textSize = 24f
}
button(“Login”) { textSize = 26f
}
}

17# IDE 支援

如果你打算開始使用 Kotlin 開發專案,在工具上你會有很多的選擇。但我強烈推薦使用 IntelliJ ,因為它自帶 Kotlin 的支援 — 它的特點展示了同一組人設計的開發工具和語言時的優勢。

只是給你一個很小但有非常聰明的例子,當我從 Stackoverflow 貼上Java 程式碼執行後,會彈出視窗提醒你貼上了 Java 的程式碼到 Kotlin 檔案裡。

喜歡小編輕輕點個關注吧!