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

tsejen129 7年前發布 | 30K 次閱讀 Kotlin Java

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

我想告訴你一個名為 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

}</code></pre>

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</code></pre>

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

<strong>val </strong>pixels: Int
    <strong>get</strong>() = width * height

}</code></pre>

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", "john@gmail.com", 112)</code></pre>

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)</code></pre>

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()</code></pre>

標準庫擴展了 Java 原來類型的功能,這是字符串對象所需要的:

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

15#  Null 安全

Java 是我們應該稱之為是一個幾乎靜態類型的編程語言。Java 的 String 變量類型無法保證它不會等于 null。盡管我們已經習慣了這樣的情況,但它否定了靜態類型檢查的安全性,導致 Java 程序員總是活在各種空指針異常的恐懼中。

Kotlin 通過區分非空類型和允許為空類型來解決這個問題。類型默認是不允許為空的,可以通過在后面加一個 ? 問號來表示允許為空,例如:

var a: String = "abc"
a = null                // 編譯錯誤

var b: String? = "xyz" b = null // 正確</code></pre>

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

優點體現在:

  1. 如果 lambda 是方法的最后一個參數或者是唯一參數的話,那么方法的括號可以移動或者省略.
  2. 如果我們選擇不去聲明單參數的 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 的開發:

 

來自:https://coyee.com/article/12274-why-you-should-totally-switch-to-kotlin

 

 本文由用戶 tsejen129 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!