Kotlin系列一:基礎知識快速入門

目錄

一 概述

二 基本類型

2.1 數字

2.2 字符類型

2.3 布爾型

2.4 數組類型

2.5 字符串

三 類型轉換和變量定義

3.1 類型轉換

3.2 變量

四 函數

五 控制流:if、when、for、while

5.1 if條件語句

5.2 when條件語句

5.3 For循環

學習參考


一 概述

Android 1.5系統中Google 引入了NDK功能,支持使用C和C++語言來進行一些本地化開發。

17年官宣kotlin爲安卓一級開發語言;所以對於安卓開發者,學習kotlin是必須的,這是java最好的第三方庫(富語法糖java)。

kotlin將代碼編譯成同樣規格的class文件讓Java虛擬機識別,它繼承了Java的全部財富,和Java100%兼容的,可以直接調用使用Java編寫的代碼,也可以無縫使用Java第三方的開源庫;Kotlin的類型推斷也在Java 8 中被推出,Lambda作爲函數式編程的基礎也在Java 8版本中加入,兩者會越來越像。

Kotlin是函數式編程語言(注1:),Kotlin的語法非常像Scala,python,借鑑了很多語言,學了很多語言發現他們越來越像,就像C#之父Anders Hejlsberg說的:未來的編程語言將逐漸融合各自的特性,而不會只存在單純的聲明式語言或者函數編程語言。

對比Java的一些優勢:

與作爲命令式語言時代的產物:Java相比,Kotlin對內聯函數的支持,使它運行Lambda表達式更快;

提前到編譯期的空指針安全檢測;

Kotlin有很多現代靜態編程語言的特點:類型推斷、多範式支持、可空性表達、擴展函數、DSL支持等。這些功能Java也陸續在加入。


二 基本類型

Kotlin完全拋棄了Java中的基本數據類型,全部使用了對象數據類型,在 Kotlin 中,所有東西都是對象;

2.1 數字

基本Kotlin數值類型包括:Byte、Short、Int、Long、Float、Double等。與Java不同的是,Kotlin中的Charactor不屬於數值類型。

Kotlin 提供了一組表示數字的內置類型。 對於整數,有四種不同大小的類型,因此值的範圍也不同。

類型 大小(比特數) 最小值 最大值
Byte 8 -128 127
Short 16 -32768 32767
Int 32 -2,147,483,648 (-231) 2,147,483,647 (231 - 1)
Long 64 -9,223,372,036,854,775,808 (-263) 9,223,372,036,854,775,807 (263 - 1)

所有以未超出 Int 最大值的整型值初始化的變量都會推斷爲 Int 類型。如果初始值超過了其最大值,那麼推斷爲 Long 類型。 如需顯式指定 Long 型值,請在該值後追加 L 後綴。

val one = 1 // Int
val threeBillion = 3000000000 // Long
val oneLong = 1L // Long
val oneByte: Byte = 1

對於浮點數,Kotlin 提供了 Float 與 Double 類型。 

類型 大小(比特數) 有效數字比特數 指數比特數 十進制位數
Float 32 24 8 6-7
Double 64 53 11 15-16

對於以小數初始化的變量,編譯器會推斷爲 Double 類型。 如需將一個值顯式指定爲 Float 類型,請添加 f 或 F 後綴。 如果這樣的值包含多於 6~7 位十進制數,那麼會將其舍入。

val pi = 3.14 // Double
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float,實際值爲 2.7182817

請注意,與一些其他語言不同,Kotlin 中的數字沒有隱式拓寬轉換。 例如,具有 Double 參數的函數只能對 Double 值調用,而不能對 Float、 Int 或者其他數字值調用。

注:=== 表示比較對象地址,== 表示比較兩個值大小。

2.2 字符類型

Kotlin中字符類型用Charactor表示,與Java不同的是,它們不能直接當作數字,它無法直接使用Char類型的ASCII進行算數運算。如果需要用,得用toInt函數轉爲相應ASCII。

2.3 布爾型

一些語言比如OC或python中,false、true可以用0、1代替,在Kotlin/Java中不允許。

2.4 數組類型

Kotlin中數組用Array類表示,可以使用庫函數 arrayOf() 來創建一個數組並傳遞元素值給它。Kotlin 也有無裝箱開銷的專門的類來表示原生類型數組: ByteArray、 ShortArrayIntArray 等等。這些類與 Array 並沒有繼承關係,但是它們有同樣的方法屬性集。

// 大小爲 5、值爲 [0, 0, 0, 0, 0] 的整型數組
val arr = IntArray(5)

// 例如:用常量初始化數組中的值
// 大小爲 5、值爲 [42, 42, 42, 42, 42] 的整型數組
val arr = IntArray(5) { 42 }

// 例如:使用 lambda 表達式初始化數組中的值
// 大小爲 5、值爲 [0, 1, 2, 3, 4] 的整型數組(值初始化爲其索引值)
var arr = IntArray(5) { it * 1 }

2.5 字符串

Kotlin中字符串同Java,用String表示。

字符串用 String 類型表示。字符串是不可變的。 字符串的元素——字符可以使用索引運算符訪問: s[i]。 可以用 for 循環迭代字符串。

Kotlin提供了字符串的內嵌表達式,也被稱爲字符串模板。語法規則:

"hello, ${obj.name}. nice to meet you!"

字符串裏嵌入${}這種語法結構的表達式,並在運行時使用表達式執行的結果替代這一部分內容,當表達式中僅有一個變量的時候,還可以將兩邊的大括號省略:

"hello, $name. nice to meet you!"

三 類型轉換和變量定義

3.1 類型轉換

精度缺失的問題就不多說了,一般兩個不同類型數字在邏輯運算時並不需要特別注意,算術運算符會重載適應不同類型:

val a = 1L + 3  // Long + Int => Long

顯示轉換:

類型 顯示轉換
Byte toByte()
Short toShort()
Int toInt()
Long toLong()
Float toFloat()
Double toDouble()
Char toChar()
String toString()

3.2 變量

Kotlin中定義一個變量,只允許在變量前聲明兩種關鍵字:val和var。

  1. val(value的簡寫)用來聲明一個不可變的變量,這種變量在初始賦值之後就再也不能重新賦值,對應Java中的final變量。
  2. var(variable的簡寫)用來聲明一個可變的變量,這種變量在初始賦值之後仍然可以再被重新賦值,對應Java中的非final變量。

這樣設計,是爲了解決Java中final關鍵字沒有被合理使用的問題。

使用指導:永遠優先使用val來聲明一個變量,而當val沒有辦法滿足你的需求時再使用var。

Kotlin的類型推導機制:如下,val關鍵字定義了一個變量a賦值爲10,這裏a就會被自動推導成整型變量。

fun main() {
    val a = 10
    println("a = " + a)
}

但對一個變量延遲賦值的話,Kotlin就無法自動推導它的類型了。這時候就需要顯式地聲明變量類型才行:

val a: Int = 10

四 函數

Kotlin函數語法規則:

fun methodName(param1: Int, param2: Int): Int {
    return 0
}

參數括號後面的部分用於聲明該函數會返回什麼類型的數據,上例表示該函數會返回一個Int類型的數據。

如果一個函數不返回任何有用的值,它的返回類型是 Unit。如果函數不需要返回任何數據,這部分可以不寫。

當一個函數中只有一行代碼時,Kotlin允許我們不必編寫函數體,可以直接將唯一的一行代碼寫在函數定義的尾部,中間用等號連接即可:

fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2)

再結合Kotlin出色的類型推導機制,由於max()函數返回的是一個Int值,因此Kotlin可以推導出largerNumber()函數返回的必然也是一個Int值,代碼可以進一步簡化成如下形式:

fun largerNumber(num1: Int, num2: Int) = max(num1, num2)

默認參數:

函數參數可以有默認值,當省略相應的參數時使用默認值。與其他語言相比,這可以減少重載數量:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /*……*/ }

如果在默認參數之後的最後一個參數是 lambda表達式,那麼它既可以作爲具名參數在括號內傳入,也可以在括號外傳入:

fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*……*/ }

foo(1) { println("hello") }     // 使用默認值 baz = 1
foo(qux = { println("hello") }) // 使用兩個默認值 bar = 0 與 baz = 1
foo { println("hello") }        // 使用兩個默認值 bar = 0 與 baz = 1

Kotlin函數的可見性修飾符和Java相比變化較大。

Java和Kotlin中函數可見性修飾符之間的區別:

修飾符 Java Kotlin
public 所有類可見 (默認類型)所有類可見
private 當前類可見 當前類可見
protected 當前類、子類、同一包路徑下的類可見 當前類、子類可見
default (默認類型)同一包路徑下的類可見
internal 同一模塊中的類可見

五 控制流:if、when、for、while

5.1 if條件語句

fun largerNumber(num1: Int, num2: Int): Int {
    var value = 0
    if (num1 > num2) {
        value = num1
    } else {
        value = num2
    }
    return value
}

Kotlin中的if語句相比於Java有一個額外的功能,它是可以有返回值的,返回值就是if語句每一個條件中最後一行代碼的返回值。因此,上述代碼就可以簡化成如下形式:

fun largerNumber(num1: Int, num2: Int): Int {
    return if (num1 > num2) {
        num1
    } else {
        num2
    }
}

kotlin的語法糖裏,當一個函數只有一行代碼時,可以省略函數體部分,直接將這一行代碼使用等號串連在函數定義的尾部。雖然上述代碼中的largerNumber()函數不止只有一行代碼,但是它和只有一行代碼的作用是相同的,只是返回了一下if語句的返回值而已,符合該語法糖的使用條件。那麼我們就可以將代碼進一步精簡:

fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) {
    num1
} else {
    num2
}

再精練:

fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) num1 else num2

5.2 when條件語句

Kotlin中的when語句類似於Java中的switch語句,但比Java中的switch語句要靈活很多。Java中的switch只能傳入整型或短於整型的變量作爲條件,JDK 1.7之後增加了對字符串變量的支持。

編寫一個查詢考試成績的功能,輸入一個學生的姓名,返回該學生考試的分數,if寫法:

fun getScore(name: String) = if (name == "Tom") {
    86
} else if (name == "Jim") {
    77
} else if (name == "Jack") {
    95
} else if (name == "Lily") {
    100
} else {
    0
}

when語句允許傳入一個任意類型的參數,然後可以在when的結構體中定義一系列的條件,格式是:

匹配值 -> { 執行邏輯 }

當你的執行邏輯只有一行代碼時,{ }可以省略。

當使用when語句的時候,現在我們將代碼改成如下寫法:

fun getScore(name: String) = when (name) {
    "Tom" -> 86
    "Jim" -> 77
    "Jack" -> 95
    "Lily" -> 100
    else -> 0
}

除了精確匹配之外,when語句還允許進行類型匹配。舉個例子。定義一個checkNumber()函數,如下所示:

fun checkNumber(num: Number) {
    when (num) {
        is Int -> println("number is Int")
        is Double -> println("number is Double")
        else -> println("number not support")
    }
}

上述代碼中,is關鍵字就是類型匹配的核心,它相當於Java中的instanceof關鍵字。

由於checkNumber()函數接收一個Number類型的參數,這是Kotlin內置的一個抽象類,像Int、Long、Float、Double等與數字相關的類都是它的子類,所以就裏就可以使用類型匹配來判斷傳入的參數到底屬於什麼類型,如果是Int型或Double型,就將該類型打印出來,否則就打印不支持該參數的類型。

when語句還有一種不帶參數的用法,雖然這種用法可能不太常用,但有的時候卻能發揮很強的擴展性。

拿剛纔的getScore()函數舉例,如果我們不在when語句中傳入參數的話,還可以這麼寫:

fun getScore(name: String) = when {
    name == "Tom" -> 86
    name == "Jim" -> 77
    name == "Jack" -> 95
    name == "Lily" -> 100
    else -> 0
}

可以看到,這種用法是將判斷的表達式完整地寫在when的結構體當中。注意,Kotlin中判斷字符串或對象是否相等可以直接使用==關鍵字,而不用像Java那樣調用equals()方法。可能你會覺得這種無參數的when語句寫起來比較冗餘,但有些場景必須使用這種寫法才能實現。舉個例子,假設所有名字以Tom開頭的人,他的分數都是86分,這種場景如果用帶參數的when語句來寫就無法實現,而使用不帶參數的when語句就可以這樣寫:

fun getScore(name: String) = when {
    name.startsWith("Tom") -> 86
    name == "Jim" -> 77
    name == "Jack" -> 95
    name == "Lily" -> 100
    else -> 0
}

現在不管你傳入的名字是Tom還是Tommy,只要是以Tom開頭的名字,他的分數就是86分。

5.3 For循環

Java中主要有兩種循環語句:while循環和for循環。Kotlin的while循環和Java中的while循環沒有任何區別。

Kotlin在for循環方面做了很大幅度的修改,Java中最常用的for-i循環在Kotlin中直接被捨棄了,而Java中另一種for-each循環則被Kotlin進行了大幅度的加強,變成了for-in循環,所以我們只需要學習for-in循環的用法就可以了。

區間的概念

閉區間:[0, 10]

val range = 0..10

左閉右開區間:[0,10):

val range = 0 until 10

有了區間之後,我們就可以通過for-in循環來遍歷這個區間,比如在main()函數中編寫如下代碼:

fun main() {
    for (i in 0..10) {
        println(i)
    }
}

默認情況下,for-in循環每次執行循環時會在區間範圍內遞增1,相當於Java for-i循環中i++的效果,而如果你想跳過其中的一些元素,可以使用step關鍵字:

fun main() {
    for (i in 0 until 10 step 2) {
        println(i)
    }
}

上述代碼表示在遍歷[0, 10)這個區間的時候,每次執行循環都會在區間範圍內遞增2,相當於for-i循環中i = i + 2的效果。

 .. 和until關鍵字都要求區間的左端必須小於等於區間的右端,也就是這兩種關鍵字創建的都是一個升序的區間。如果你想創建一個降序的區間,可以使用downTo關鍵字,用法如下:

fun main() {
    for (i in 10 downTo 1) {
        println(i)
    }
}

這裏我們創建了一個[10, 1]的降序區間。


標註1:

函數式編程是一種編程範式,我們常見的編程範式有命令式編程(Imperative programming)函數式編程邏輯式編程,常見的面向對象編程是也是一種命令式編程。更多瞭解推薦參考:https://www.zhihu.com/question/28292740

 

學習參考

1 官網文檔 https://www.kotlincn.net/docs/reference/basic-syntax.html

2 郭霖:《第一行代碼》

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章