1. 程式人生 > >Kotlin快速入門(一)基礎

Kotlin快速入門(一)基礎

一個表 range fix font 有一個 get() nta 兼容 des

Kotlin快速入門(一)基礎

Kotlin學習筆記,主要記錄與Java不同的地方。

1 基本類型

1.1 數字

1)數字沒有隱式擴寬轉換

val b: Byte = 1 // OK, 字面值是靜態檢測的
val i: Int = b // 錯誤

但我們可以顯示轉換

val i: Int = b.toInt()

上下文推斷轉換類型是可以的

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

2)Kotlin中字符不是數字,但字符可以顯示轉換為數字

fun check(c: Char) {
if (c == 1) { // 錯誤:類型不兼容
// ……
}
}
fun decimalDigitValue(c: Char): Int {
if (c !in ‘0‘..‘9‘) throw IllegalArgumentException("Out of range") return c.toInt() - ‘0‘.toInt() // 顯式轉換為數字 }

3)可以使用下劃線使數字常量更易讀

val a=1_000_000

4)數字的封箱

val a: Int = 10000
print(a === a) // 輸出“true”
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!輸出“false”!!!
val a: Int = 10000
print(a 
== a) // 輸出“true” val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA == anotherBoxedA) // 輸出“true”
// 假想的代碼,實際上並不能編譯:
val a: Int? = 1 // 一個裝箱的 Int (java.lang.Integer)
val b: Long? = a // 隱式轉換產生一個裝箱的 Long (java.lang.Long)
print(a == b) // 驚!這將打印 "false" 鑒於 Long 的 equals() 檢測其他部分也是 Long

1.2 運算

位運算列表(只用於 Int Long ) :
shl(bits) 有符號左移 (Java << )
shr(bits) 有符號右移 (Java >> )
ushr(bits) 無符號右移 (Java >>> )
and(bits) 位與
or(bits) 位或
xor(bits) 位異或

inv() 位非

1.3 數組

數組在 Kotlin 中使用 Array 類來表示,它定義了 get set 函數(按照運算符重載約定
這會轉變為 [] ) 和 size 屬性,以及一些其他有用的成員函數:

class Array<T> private constructor() {
val size: Int
operator fun get(index: Int): T
operator fun set(index: Int, value: T): Unit
operator fun iterator(): Iterator<T>
// ……
}

我們可以使用庫函數 arrayOf() 來創建一個數組並傳遞元素值給它,這樣 arrayOf(1, 2, 3)
創建了 array [1, 2, 3]。 或者,庫函數 arrayOfNulls() 可以用於創建一個指定大小、元素都
為空的數組。
另一個選項是用接受數組大小和一個函數參數的工廠函數,用作參數的函數能夠返回 給定索
引的每個元素初始值:

// 創建一個 Array<String> 初始化為 ["0", "1", "4", "9", "16"]
val asc = Array(5, { i -> (i * i).toString() })

如上所述, [] 運算符代表調用成員函數 get() set()
註意: Java 不同的是,Kotlin 中數組是不型變的(invariant) 。這意味著 Kotlin 不讓我們把
Array<String> 賦值給 Array<Any> ,以防止可能的運行時失敗(但是你可以使用 Array<out
Any> , 參見類型投影) 。
Kotlin 也有無裝箱開銷的專門的類來表示原生類型數組: ByteArray
ShortArray IntArray 等等。這些類和 Array 並沒有繼承關系,但是 它們有同樣的方法
屬性集。它們也都有相應的工廠方法:

val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2] 

1.4 字符串

1)可以使用索引運算符訪問

如:s[i]

2)可以用 for 循環叠代字符串

for (c in str) {
println(c)
}

3)Kotlin 有兩種類型的字符串字面值: 轉義字符串可以有轉義字符,以及原生字符串可以包含換
行和任意文本。

轉移字符串(與Java類似)

val s = "Hello, world!\n"

原生字符串 使用三個引號(""" ) 分界符括起來,內部沒有轉義並且可以包含換行和任何其
他字符:

val text = """
for (c in "foo")
print(c)
"""

4)字符串模板:

字符串可以包含模板表達式 ,即一些小段代碼,會求值並把結果合並到字符串中。 模板表達
式以美元符($ ) 開頭,由一個簡單的名字構成:

val i = 10
val s = "i = $i" // 求值結果為 "i = 10"

或者用花括號擴起來的任意表達式:

val s = "abc"
val str = "$s.length is ${s.length}" // 求值結果為 "abc.length is 3"

原生字符串和轉義字符串內部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符
(它不支持反斜杠轉義) ,你可以用下列語法:

val price = """
${‘$‘}9.99
"""

二、包

如果出現名字沖突,可以使用 as 關鍵字在本地重命名沖突項來消歧義:

import foo.Bar // Bar 可訪問
import bar.Bar as bBar // bBar 代表“bar.Bar”

關鍵字 import 並不僅限於導入類;也可用它來導入其他聲明:
頂層函數及屬性
對象聲明中聲明的函數和屬性;
枚舉常量
Java 不同,Kotlin 沒有單獨的 "import static" 語法; 所有這些聲明都用 import 關鍵字導
入 。

三、控制流

3.1 if表達式

Kotlin 中, if 是一個表達式,即它會返回一個值。 因此就不需要三元運算符(條件 ?
: 否則) ,因為普通的 if 就能勝任這個角色。

// 傳統用法
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
} 
// 作為表達式
val max = if (a > b) a else b

if 的分支可以是代碼塊,最後的表達式作為該塊的值:

val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}

如果你使用 if 作為表達式而不是語句(例如:返回它的值或者 把它賦給變量) ,該表達式
需要有 else 分支。

3.2 when表達式

when 取代了類 C 語言的 switch 操作符。

when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 註意這個塊
print("x is neither 1 nor 2")
}
}

when 既可以被當
做表達式使用也可以被當做語句使用。如果它被當做表達式, 符合條件的分支的值就是整個
表達式的值,如果當做語句使用, 則忽略個別分支的值。(像 if 一樣,每一個分支可以是
一個代碼塊,它的值 是塊中最後的表達式的值。)如果其他分支都不滿足條件將會求值 else 分支。 如果 when 作為一個表達式使用,則必須
else 分支, 除非編譯器能夠檢測出所有的可能情況都已經覆蓋了。

如果很多分支需要用相同的方式處理,則可以把多個分支條件放在一起,用逗號分隔:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

我們可以用任意表達式(而不只是常量) 作為分支條件 :

when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}

也可以檢測一個值在(in ) 或者不在(!in ) 一個區間或者集合中 :

when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

檢測一個值是(is ) 或者不是(!is ) 一個特定類型的值。註意: 由於
能轉換,你可以訪問該類型的方法和屬性而無需 任何額外的檢測 :

val hasPrefix = when(x) {
is String -> x.startsWith("prefix")
else -> false
}

when 也可以用來取代 if - else if 鏈。 如果不提供參數,所有的分支條件都是簡單的布
爾表達式,而當一個分支的條件為真時則執行該分支:

3.3 for循環

for 循環可以對任何提供叠代器(iterator) 的對象進行遍歷,語法如下:

for (item in collection) print(item)

循環體可以是一個代碼塊:

for (item: Int in ints) {
// ……
}

如上所述, for 可以循環遍歷任何提供了叠代器的對象。即:
有一個成員函數或者擴展函數 iterator() ,它的返回類型
有一個成員函數或者擴展函數 next() ,並且
有一個成員函數或者擴展函數 hasNext() 返回 Boolean
這三個函數都需要標記為 operator

對數組的 for 循環會被編譯為並不創建叠代器的基於索引的循環。
如果你想要通過索引遍歷一個數組或者一個 list,你可以這麽做:

for (i in array.indices) {
print(array[i])
}

註意這種在區間上遍歷會編譯成優化的實現而不會創建額外對象。
或者你可以用庫函數 withIndex

for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}


3.4 while循環

同Java

四、返回和跳轉

1)Kotlin 有三種結構化跳轉表達式
return 。默認從最直接包圍它的函數或者匿名函數返回。
break 。終止最直接包圍它的循環。
continue 。繼續下一次最直接包圍它的循環。
所有這些表達式都可以用作更大表達式的一部分

val s = person.name ?: return

這些表達式的類型是 Nothing 類型

2)我們可以用標簽限制 break 或者 continue

[email protected] for (i in 1..100) {
for (j in 1..100) {
if (……) break@loop
}
}

從lamada表達式返回

fun foo() {
ints.forEach [email protected] {
if (it == 0) return@lit
print(it)
}
} 

也可使用隱式標簽

fun foo() {
ints.forEach {
if (it == 0) return@forEach
print(it)
}
}

用一個匿名函數替代 lambda 表達式。 匿名函數內部的 return 語句將從該匿名
函數自身返回

fun foo() {
ints.forEach(fun(value: Int) {
if (value == 0) return
print(value)
})
}

當要返一個回值的時候,解析器優先選用標簽限制的 return,即

return@a 1 //意為“從標簽 @a 返回 1”,而不是“返回一個標簽標註的表達式 (@a 1) ”。

Kotlin快速入門(一)基礎