1. 程式人生 > >快速上手kotlin

快速上手kotlin

首先我們先了解一下什麼是kotiln?

Kotlin 是一個基於 JVM 的新的程式語言,由 JetBrains 開發。
Kotlin可以編譯成Java位元組碼,也可以編譯成JavaScript,方便在沒有JVM的裝置上執行。
JetBrains,作為目前廣受歡迎的Java IDE IntelliJ 的提供商,在 Apache 許可下已經開源其Kotlin 程式語言。
Kotlin已正式成為Android官方支援開發語言。

那麼kotiln與Java相比有什麼優勢呢?

Kotlin編譯為JVM位元組碼或JavaScript ,像Java一樣,Bytecode也是Kotlin程式的編譯格式。 位元組碼錶示程式設計程式碼,一旦編譯,就通過虛擬機器而不是計算機的處理器執行。 通過使用這種方法,一旦編譯並執行虛擬機器,原始碼就可以在任何平臺上執行。 一旦kotlin程式被轉換為位元組碼,它可以通過網路傳輸並由JVM(Java虛擬機器)執行。

Kotlin程式可以使用所有現有的Java框架和庫 ,是的,Kotlin程式可以使用所有現有的Java框架和庫,甚至依賴於註釋處理的高階框架也是如此。關於kotlin語言的主要重點是它可以輕鬆地與Maven和其他構建系統整合。Kotlin可以輕鬆學習,平易近人。通過簡單的閱讀語言參考可以輕鬆學習。語言乾淨直觀(易於使用和理解)。Kotlin看起來很像Scala,但更簡單。Kotlin是開放原始碼,沒有收費。

將Java自動轉換為Kotlin - JetBrains將IntelliJ集成了一個新功能,將Java轉換為Kotlin,節省了大量的時間。而且它也節省了我們重新編寫世代程式碼。
Kotlin的空安全性很好 - 現在擺脫NullPointerExceptions。這種型別的系統幫助我們避免空指標異常。在Kotlin系統中,系統只拒絕編譯嘗試分配或返回null的程式碼考慮以下示例 -
程式碼審查不是問題 - 科特林更注重可讀性的語法,所以程式碼審查不是一個問題,它們仍然可以由那些不熟悉語言的團隊成員完成。

最後讓我們來看看Kotlin 基本語法

先說個學習Kotlin語法的小竅門,將程式碼用Java寫好,然後Code/Conver Java File to Kotlin File轉換成Kotlin程式碼,或者將Java程式碼複製到Kotlin檔案會提示轉換也是挺方便的,比較差異很容易就能理解了,一開始難免不適應習慣後相信你一定會喜歡上Kotlin

Kotlin定義

忘掉Java的那一套寫法不然會很不適應的,Kotlin有自己的特性不該被Java的思維所束縛。在Kotlin中常量用val宣告,變數用var宣告,關鍵字在前面,型別以冒號:隔開在後面,也可以省略直接賦值,型別後帶問號?表示可為空型別(預設空安全)。常量val延遲載入by lazy{},預設執行緒安全關閉執行緒安全lazy(LazyThreadSafetyMode.NONE){},變數var延遲載入late init。

//常量陣列int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
//空安全變數
var str: String = "hello"
var str1 = "word"
//可為空字串變數
var str2: String? = null

條件

if…else 正常使用,不過移除了switch用更強大的when替代,when子式可以是常量、變數、返回數值的表示式、返回Boolean值的表示式,強大到用來替換if…else if

// 測試值 x = 0, -1, 1, 2, 3, 6, 10
var x = 10
when (x) {
    //常量
    2 -> println("等於2")
    //數值表示式
    if (x > 0) 
    1
     else
      -1 -> println("大於0並等於1,或小於0並等於-1")
  
    //Boolean型別表示式
    in 1..5 -> println("範圍匹配1-5")
    !in 6..9 -> println("不是6-9")
    is Int -> println("型別判斷")
    else -> println("else")
}
// 代替if...else if
when{
    x > 6 && x <= 10  ->  println("大於6小於等於10")
    x < 6 -> println("小於6")
    else -> println("else")
}

迴圈

while 和 do…while 同Java並無區別,for則有很大改變並多出了幾個變種

val list = arrayListOf("aa", "bb", "cc")
//遞增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
   print(list[i])
}
//遞增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
   print(list[i])
}
//遞減for (int i = list.size() - 1; i >= 0; i--)
for (i in list.size - 1 downTo 0) {
    print(list[i])
}

//操作列表內的物件
for (item in list) {
    print(item)
}
//加強版
for((i, item) in list.witnIndex()) {
    print(list[i])
    print(item)
}
//變種版
list.forEach {
    print(it)
}

list.forEach {
    print(it)
}

list.forEachIndexed { i, s ->
    print(list[i])
    print(s)
}

list.forEachIndexed(object :(Int,String) -> Unit{
    override fun invoke(i: Int, s: String) {
        print(list[i])
        print(s)
    }
})

萬能的冒號

在Kotlin中冒號:用萬能來稱呼絕不為過。常量變數的型別宣告,函式的返回值,類的繼承都需要它

//val表示常量var表示變數宣告
val name: String = "ljz" 
//省略型別說明
var age = "23"
//fun表示函式
fun getName(): String{
   return "ljz"
}
//類繼承
class UserList<E>(): ArrayList<E>() {
    //...
}

除此之外還有一個特別的地方也需要它,使用Java類的時候。Kotlin最終還是會編譯成Java位元組碼,使用到Java類是必然的,在Kotlin語法如下

val intent = Intent(this, MainActivity::class.java)

類名::class.java沒有為什麼就這麼寫記著就是

我是誰的@

除了冒號另一個重要符號@,想必用到內部類和匿名內部類的地方一定很多,再加上支援lambda語法,沒有它誰告訴你this和return指的是哪一個

class User {
    inner class State{
        fun getUser(): User{
            //返回User
            return [email protected]
        }
        fun getState(): State{
            //返回State
            return [email protected]
        }
    }
}

偷懶的方法

  • Kotlin特色

Java的getter/setter方法自動轉換成屬性,對應到Kotlin屬性的呼叫

public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

反之Kotlin的屬性自動生成Java的getter/setter方法,方便在Java中呼叫,同樣的定義在Kotlin中

class User {
    var name: String? = null
    var age: String? = null
}

這樣一個Java類在Kotlin中只需這樣呼叫

val user = User()
//賦值
user.name = "ljz"
user.age = "23"
//取值
val name = user.name
val age = user.age

我們的getter/setter方法有時不會這麼簡單,這就需要自定義getter/setter了,另起一行設定get()/set(value)方法,實現一個Java中常用的單例,這裡只為了展示,單例在Kotlin有更簡單的方法實現,只要在 package 級別建立一個 object 即可

class User {
    companion object {
        @Volatile
         var instance: User? = null
            get() {
                if (field == null) {
                    synchronized(User::class.java) {
                        if (field == null)
                            field = User()
                    }
                }
                return field
            }
    }

    var name: String? = null
    var age: String? = null
}

自定義getter/setter重點在field,跟我們熟悉Java的this指代當前類一樣,field指代當前引數,直接使用引數名instance代替不會報錯但單例就沒效果了

  • 字串模板

在Java中拼接字串的程式碼可讀性都很差,在Kotlin字串拼接變得非常簡潔,只需用$後面加上引數名,複雜的引數要加上{}

val user = User()
//賦值
user.name = "ljz"
user.age = "23"
//取值
val name = user.name
val age = user.age
var userInfo = "name:${user.name},  age:$age"
//輸出結果:name:ljz, age:23
  • lambda

一開始覺得lambda很高階完全看不懂,其實很簡單的就是把介面名、方法名和引數型別省掉不寫再加個->罷了,明白這點了很好理解。

// 無引數無返回值
Thread(Runnable {
    sleep(1000)
}).start()

// 單引數不帶返回值
view.setOnClickListener { v ->
    Log.e("tag", "${v.tag}")
}
// 多引數帶返回值
view.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
    Log.e("tag", "keyCode$keyCode, ${event.keyCode}")
    if (event.keyCode == KeyEvent.KEYCODE_BACK)
        [email protected] true
    false
})

新面孔

  • 延遲載入
  • 流程控制

空判斷

Kotlin的空安全設計對於宣告可為空的引數,在使用時要進行空判斷處理,有兩種處理方式,欄位後加!!像Java一樣丟擲空異常,另一種欄位後加?可不做處理返回值為 null或配合?:做空判斷處理

//型別後面加?表示可為空
var age: String? = "23" 
//丟擲空指標異常
val ages = age!!.toInt()
//不做處理返回 null
val ages1 = age?.toInt()
//age為空返回-1
val ages2 = age?.toInt() ?: -1

注意事項

內部類和引數預設為public,而在Java中為 default 即在同一個包中可見
類預設為不可繼承(final),想要可被繼承要宣告為open或abstract
取消了static關鍵字,靜態方法和引數統一寫在companion object塊
internal模組內可見,inner內部類

總結

以上僅是對使用頻率較高的語法總結,學會基本可以閱讀Kotlin程式碼,遇到點問題Google速查一下,至於智慧轉換、型別推導之類的不用說使用後喜歡自然就會了。當然這只是kotlin的基本語法,方便Java快速熟悉kotlin,深入學習還請閱讀相關資料。

相關連結