天天看點

Kotlin 文法

為什麼使用Kotlin

項目一期在收尾了終于有時間折騰了,一個多月以來Kotlin從入門到現在,堅持用來開發的切身感受。因為文法與Java的差別挺大的一開始很想放棄,如果不是因為項目在使用,想必很少人會嘗試這樣一門小衆語言,但是習慣後會發現這些年究竟浪費多少時間在寫無用的Java代碼了,Kotlin在相容Java的基礎上還能大大提升開發效率。Kotlin有許多特性但對于開發來說,快速适應和學習更為重要,很多時候我們都是在不明白其原因就開始使用的,正如我們不可能把Retrofit原理研究透才使用它。隻要它足夠穩定成熟,并能有效的提升開發效率都是值得嘗試的。鄙人不才,目前使用Kotlin的原因主要是因為它文法簡潔,支援lambda表達式,強大的when文法,不用寫分号結尾,光是這些就足以讓我喜歡Kotlin。至于空安全之類的特性,畢竟服務端資料類型太多null了并沒多大感觸,這些特性在實際應用中潛移默化的就吸收了,以至于現在遇到幾個Java編寫的代碼,都有些不适應了。

修改說明

突然火了一臉懵逼,Google IO的影響真是不容小觑。避免誤人子弟還是修改下比較好,也就把上一篇文章的基礎知識也搬遷過來,對條件判斷

when

還有空判斷處理進行了修改,添加了

lambda

說明,移除過期連結。

Kotlin 基本文法

先說個學習Kotlin文法的小竅門,将代碼用Java寫好,然後

Code/Conver Java File to Kotlin File

轉換成Kotlin代碼,或者将Java代碼複制到Kotlin檔案會提示轉換也是挺友善的,比較差異很容易就能了解了,一開始難免不适應習慣後相信你一定會喜歡上Kotlin

1). 定義

忘掉Java的那一套寫法不然會很不适應的,Kotlin有自己的特性不該被Java的思維所束縛。在Kotlin中常量用

val

聲明,變了用

var

聲明,關鍵字在前面,類型以冒号

:

隔開在後面,也可以省略直接指派,類型後帶問号

?

表示可為空類型(預設空安全)。

常量

val

延遲加載

by lazy{}

,預設線程安全關閉線程安全

lazy(LazyThreadSafetyMode.NONE){}

,變量

var

延遲加載

lateinit

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

2). 條件

if...else

 正常使用,不過移除了

switch

用更強大的

when

替代,when子式可以是常量、變量、傳回數值的表達式、傳回Boolean值的表達式,強大到用來替換

if...else if

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

3). 循環

while

 和 

do...while

 同Java并無差別,

for

則有很大改變并多出了幾個變種

val list = ArrayList<String>()
//遞增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 ..list.size-) {
   print(list[i])
}
//遞減for (int i = list.size(); i >= 0; i--)
for (i in list.size downTo ) {
    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 = "tutu" 
//省略類型說明
var age = "23"
//fun表示函數
fun getName(): String{
   return "tutu"
}
//類繼承
class UserList<E>(): ArrayList<E>() {
    //...
}
           

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

類名

::class.java

沒有為什麼就這麼寫記着就是

我是誰的@

除了冒号另一個重要符号

@

,想必用到内部類和匿名内部類的地方一定很多,再加上支援lambda文法,沒有它誰告訴你

this

return

指的是哪一個

class User {
    inner class State{
        fun getUser(): User{
            //傳回User
            return this@User
        }
        fun getState(): State{
            //傳回State
            return this@State
        }
    }
}
           

偷懶的方法

1). 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 = "tutu"
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

代替不會報錯但單例就沒效果了

2). 字元串模闆

在Java中拼接字元串的代碼可讀性都很差,在Kotlin字元串拼接變得非常簡潔,隻需用

$

後面加上參數名,複雜的參數要加上

{}

val user = User()
//指派
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age
var userInfo = "name:${user.name},  age:$age"
//輸出結果:name:tutu, age:23
           

3). lambda

一開始覺得lambda很進階完全看不懂,其實很簡單的就是把接口名、方法名和參數類型省掉不寫再加個

->

罷了,明白這點了很好了解。

// 無參數無傳回值
Thread(Runnable {
    sleep()
}).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)
        return@OnKeyListener true
    false
})
           

新面孔

1). 延遲加載

2). 流程控制

内容上一篇寫過參考 Android Kotlin 學習筆記,不重複介紹

空判斷

Kotlin的空安全設計對于聲明可為空的參數,在使用時要進行空判斷處理,有兩種處理方式,字段後加

!!

像Java一樣抛出空異常,另一種字段後加

?

可不做處理傳回值為 null或配合

?:

做空判斷處理

//類型後面加?表示可為空
var age: String? = "23" 
//抛出空指針異常
val ages = age!!.toInt()
//不做處理傳回 null
val ages1 = age?.toInt()
//age為空傳回-1
val ages2 = age?.toInt() ?: 
           

更多空處理NullPointException 利器 Kotlin 可選型

注意事項

内部類和參數預設為public,而在Java中為private

類預設為不可繼承(final),想要可被繼承要聲明為

open

abstract

取消了static關鍵字,靜态方法和參數統一寫在

companion object

internal子產品内可見,inner内部類

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

相關連結

線上學習

Kotlin 官方文檔

翻譯出處kotlin-web-site-cn

中文站(更新到 1.1):https://www.kotlincn.net/

網址(更新到 1.0.3):http://tanfujun.com/kotlin-web-site-cn/

Kotlin 中文論壇:https://www.kotliner.cn/

後記

為了友善收集優秀Kotlin文章建立了個專題,有興趣的歡迎投稿優秀内容

http://www.jianshu.com/c/3c442ef98c83