當前位置: 首頁>>編程語言>>正文


為什麽要從Java切換到Kotlin

為什麽您應該從Java完全切換到Kotlin

是時候開始使用現代編程語言了!

 

我想介紹一種新的編程語言Kotlin以及為什麽要在下一個項目中考慮它。我曾經更喜歡Java,但是慢慢發現自己會盡可能地編寫Kotlin代碼。

Kotlin是由JetBrains開發和維護,它的務實簡潔使編碼令人有滿意且高效的體驗。出於以下一些原因,您可以考慮切換到Kotlin:

#0 與Java的互操作性

Kotlin是100%與Java兼容的,也就是可以用Kotlin和Java混合編程。您實際上可以使用Kotlin繼續舊的Java項目上的工作。所有你喜歡的Java框架仍然可用,且無論您是用Kotlin編寫的任何框架,都容易被您的Java朋友所采用。

#1 熟悉的語法

Kotlin不是學術界出生的怪異語言。它的語法對於來自麵向對象領域的程序員來說都會比較熟悉。當然有一些與Java的差異,例如重新構造的構造函數或val/var變量聲明。下麵的代碼段介紹了大多數基礎知識:

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()更智能、更易讀的字符串處理:

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 = ArrayList()     // type declared explicitly

#4智能Cast

Kotlin編譯器會跟蹤您的邏輯並自動cast類型(如果可能),這意味著不再需要用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默認參數

無需使用不同的參數定義幾種類似的方法:

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

#7命名參數

與默認參數結合使用時,命名參數消除了對Builder的需要:

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

#8when表達式

switch被更具可讀性和靈活性的when表達式取代:

 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屬性

自定義set & get可以將行為添加到公共字段中,這意味著我們可以停止漫不經心的getters & setters代碼膨脹。

#10Data Class

這是一個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)

#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範圍

出於可讀性考慮:

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()。後來當你需要將一個String轉大寫時,您最終編寫了自己的輔助函數,因為您不知道StringUtils.capitalize()

如果隻有一種方法可以向舊類添加新功能;這樣,您的IDE可以幫助您在代碼補全中找到正確的函數/方法。在Kotlin中,您可以執行以下操作:

fun String.replaceSpaces(): String {
    return this.replace(' ', '_')
}

val formatted = str.replaceSpaces()

標準庫擴展了Java原始類型的功能,這對於String非常有必要:

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

#15Null安全

Java是我們應該稱之為的幾乎靜態類型的語言。JAVA中,一個String類型變量是不保證的一定指向一個String-它可能是指null。即使我們已經習慣了它,但它否定了靜態類型檢查的安全性,因此Java開發人員不得不時刻小心NPE(Null Pointer Exception)。

Kotlin通過區分非空類型可為空的類型解決這個問題。類型默認情況下為非null,並且可以通過添加一個?來允許空值,像這樣:

var a: String = "abc"
a = null                // compile error

var b: String? = "xyz"
b = null                // no problem

每當您訪問可為空的類型時,Kotlin在編譯時會強製報錯防止NPE:

val x = b.length        // compile error: b might be null

盡管這看起來很麻煩,但由於Kotlin的一些智能功能,可以輕易搞定——因為有智能的類型轉換,它會盡可能將可空類型轉換為非空類型:

if (b == null) return
val x = b.length        // no problem

我們也可以使用安全的調用?.,其結果可為null而不拋出NPE:

val x = b.length        // compile error: b might be null

可以將安全調用鏈接在一起,以避免我們在其他語言有時會遇到的編寫嵌套if-not-null檢查的問題。另外如果我們需要默認值而不是null,我們可以使用三目運算符?:

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

如果這些都不適合您,並且您確實需要NPE,則必須明確要求:

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

#16更好的Lambda

Kotlin有一個很好的lambda係統-由於一些聰明的設計選擇,在可讀性和簡潔性之間達到了完美的平衡。首先語法是一目了然的:

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

這裏有一些聰明的地方:

  1. 如果lambda是方法的最後一個或唯一的參數,則可以移動或省略方法的圓括號。
  2. 如果我們選擇不聲明單參數lambda的參數,則會隱式聲明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 以旨在增強Android開發的DSL為例:

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

#17IDE支持

如果您打算開始使用Kotlin,可以有很多選擇,但是我強烈建議您使用IntelliJ, 這個IDE直接與Kotlin捆綁在一起-其功能展示了由同一個人設計語言和IDE的優勢。

僅舉一個小巧而巧妙的例子,當我第一次嘗試從Stack Overflow複製粘貼一些Java代碼時,便會彈出此內容:

IntelliJ將通知您是否將Java代碼粘貼到Kotlin文件中

到此為止。感謝您的閱讀!

參考資料

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/4538.html,未經允許,請勿轉載。