kotlin基礎——>基本數據類型、控制流、返回和跳轉
1.對于數字的定義,支持java 8的下劃線分割的方式
val a = 1_2_3 與 val a = 123 是相同的
2.如果要指定數字類型有兩種方式
val a : Float = 1 或者 val a = 1f
3.kotlin沒有隱式拓寬轉換
val i = 1 val d = 1.1 val f = 1.1f printDouble(d) printDouble(i) // 錯誤:類型不匹配 printDouble(f) // 錯誤:類型不匹配
4.kotlin數字定義不支持八進制
十進制: 123 -- Long類型 123L 十六進制: 0x0f 二進制: 0b001
5.當采用可空的引用(Int?)或泛型,后者情況會把數字裝箱,裝箱的數字保留相等性,但不一定保留同一性
val a: Int = 10000 println(a === a) // 輸出“true” val boxedA: Int? = a val anotherBoxedA: Int? = a println(boxedA === anotherBoxedA) // !!!輸出“false”!!! 但保留相等性 val a: Int = 10000 println(a == a) // 輸出“true” val boxedA: Int? = a val anotherBoxedA: Int? = a println(boxedA == anotherBoxedA) // 輸出“true”
6.顯示轉換,現在無法直接用long類型接收一個int類型的數字,在早起版本會把int類型裝箱變為Long類型,后續版本在編譯期就會報錯,無法通過默認方式的編譯成功
// 假想的代碼,實際上并不能編譯: val a: Int? = 1 // 一個裝箱的 Int (java.lang.Integer) val b: Long? = a // 隱式轉換產生一個裝箱的 Long (java.lang.Long) print(b == a) // 驚!這將輸出“false”鑒于 Long 的 equals() 會檢測另一個是否也為 Long //以下的方式也是錯的 val b: Byte = 1 // OK, 字面值是靜態檢測的 val i: Int = b // 錯誤 但是可以通過顯式轉換 val i: Int = b.toInt() // OK:顯式拓寬 可以使用以下的方式 — toByte(): Byte — toShort(): Short — toInt(): Int — toLong(): Long — toFloat(): Float — toDouble(): Double — toChar(): Char 注意: val l = 1L + 3 // Long + Int => Long
7.運算時,整數計算只會得到整數,如果需要返回浮點,需要其中一個進行顯式轉換
val x = 5 / 2.toDouble() println(x == 2.5)
8.位運算,對于位運算,沒有特殊字符來表示,而只可用中綴方式調用具名函數
val x = (1 shl 2) and 0x000FF000 這是完整的位運算列表(只用于 Int 與 Long): — shl(bits) ? 有符號左移 — shr(bits) ? 有符號右移 — ushr(bits) ? 無符號右移 — and(bits) ? 位與 — or(bits) ? 位或 — xor(bits) ? 位異或 — inv()?位非
9.區間比較
區間實例以及區間檢測:a..b、x in a..b、x !in a..b
10.字符Char,不能直接作為數字,可以顯式轉換
字符字面值用單引號括起來: '1' 。特殊字符可以用反斜杠轉義。支持這幾個轉義序列:\t 、 \b 、\n 、\r 、\' 、\" 、\\ 與 \$ 。編碼其他字符要用 Unicode 轉義序列語法:'\uFF00'
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // 顯式轉換為數字
}
11.數組,在kotlin中使用Array類來表示,在kotlin中是不型變的(invariant)。這意味著 Kotlin 不讓我們把 Array<String> 賦值給Array<Any>,以防止可能的運行時失敗(但是你可以使用 Array<out Any>,參?類型投影)。
// 創建一個 Array<String> 初始化為 ["0", "1", "4", "9", "16"]
val asc = Array(5) { i -> (i * i).toString() }
asc.forEach { println(it) }
12.原生類型數組
val x: IntArray = intArrayOf(1, 2, 3) x[0] = x[1] + x[2]
// 大小為 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 }
13.無符號整型(kotlin 1.3起才可用)
val a :UByte = 1u val b: Byte = a.toByte() 注意:將類型從無符號類型更改為對應的有符號類型(反之亦然)是二進制不兼容變更
無符號類型是使用另一個實驗性特性(即內聯類)實現的。
14.特化的類
與原生類型相同,每個無符號類型都有相應的為該類型特化的表示數組的類型: — kotlin.UByteArray : 無符號字節數組 — kotlin.UShortArray : 無符號短整型數組 — kotlin.UIntArray : 無符號整型數組 — kotlin.ULongArray : 無符號?整型數組 與有符號整型數組一樣,它們提供了類似于 Array 類的 API 而沒有裝箱開銷。 此外,區間與數列也支持 UInt 與 ULong(通過這些類 kotlin.ranges.UIntRange 、 kotlin.ranges.UIntProgression 、kotlin.ranges.ULongRange 、 kotlin.ranges.ULongProgression )
15.無符號是實驗性的,如果要使用需要加入聲明
— 如需傳播實驗性,請以 @ExperimentalUnsignedTypes 標注使用了無符號整型的聲明。 — 如需選擇加入而不傳播實驗性,要么使用 @OptIn(ExperimentalUnsignedTypes::class) 注解標注聲明,
要么將 -Xopt-in=kotlin.ExperimentalUnsignedTypes 傳給編譯器。
16.字符串關于"""(原始字符串)以及trimMargin()的使用
val text = """
|Tell me and I > forget.
|Teach me and I > remember.
|Involve me and > I learn.
|(Benjamin Franklin) """
println(text)
輸出結果(上下的換行,和前面的空格都是):
|Tell me and I > forget.
|Teach me and I > remember.
|Involve me and > I learn.
|(Benjamin Franklin)
val text = """
|Tell me and I > forget.
|Teach me and I > remember.
|Involve me and > I learn.
|(Benjamin Franklin) """.trimMargin()
println(text)
輸出結果:
Tell me and I > forget.
Teach me and I > remember.
Involve me and > I learn.
(Benjamin Franklin)
注意:trimMargin() 函數為去除前導空格,默認以 | 作為邊界前綴,所以等同于trimMargin("|") ,邊界前綴可以自己定義
17.字符串模版,可以直接使用 $ 符號
val i = 10
println("i = $i") // 輸出“i = 10”
val s = "abc"
println("$s.length is ${s.length}") // 輸出“abc.length is 3”
18.包導入,于java基本相同,對于出現名字沖突的可以使用as另外定義一個名字來取消沖突和歧義
import org.example.Message // Message 可訪問 import org.test.Message as testMessage // testMessage 代表“org.test.Message”
19.在kotilin中if為一個表達式,可以返回一個值,也就是說對于三元運算符的寫法,也可以用if替代,當然如果使用if作為表達式,那么必須要有else分支
1 //傳統用法 2 var max: Int 3 if (a > b) { 4 max = a 5 } else { 6 max = b 7 } 8 9 10 // 作為表達式 11 val max = if (a > b) a else b 12 13 //或者寫作 14 val max = if (a > b) { 15 print("Choose a") 16 a 17 } else { 18 print("Choose b") 19 b 20 }
20.when取代了之前的switch,同樣如果用于作為表達式,必須要有else分支,以下為when的幾種寫法
1 when (x) { 2 1 -> print("x == 1") 3 2 -> print("x == 2") 4 else -> { // 注意這個塊 5 print("x is neither 1 nor 2") 6 } 7 } 8 9 10 //多條件相同處理時,用 , 分割 11 when (x) { 12 0, 1 -> print("x == 0 or x == 1") 13 else -> print("otherwise") 14 } 15 16 //可以用任意表達式作為分支,而不僅僅是常量 17 when (x) { 18 parseInt(s) -> print("s encodes x") 19 else -> print("s does not encode x") 20 } 21 22 //也可以檢測一個值在(in)或者不在(!in)一個區間或者集合中 23 when (x) { 24 in 1..10 -> print("x is in the range") 25 in validNumbers -> print("x is valid") 26 !in 10..20 -> print("x is outside the range") 27 else -> print("none of the above") 28 } 29 30 //另一種可能性是檢測一個值是(is)或者不是(!is)一個特定類型的值。注意:由于智能轉換,你可以訪 問該類型的方法與屬性而無需任何額外的檢測。 31 32 fun hasPrefix(x: Any) = when(x) { 33 is String -> x.startsWith("prefix") 34 else -> false 35 } 36 37 //when 也可以用來取代 if-else if鏈 38 when { 39 x.isOdd() -> print("x is odd") 40 y.isEven() -> print("y is even") 41 else -> print("x+y is even.") 42 } 43 44 //自kotlin 1.3起,可以使用以下語法將 when 的主語(subject,譯注:指 when 所判斷的表達式)捕獲到 變量中: 45 46 fun Request.getBody() = 47 when (val response = executeRequest()) { 48 is Success -> response.body 49 is HttpError -> throw HttpException(response.status) 50 } 51 52 注意:在 when 主語中引入的變量的作用域僅限于 when 主體。
21.for循環,可以對任何提供迭代器(iterator)的對象進行遍歷,這相當于像 C# 這樣的語言中的 foreach 循環
1 // 1. 基本語法 2 for (item in collection) print(item) 3 4 //2.循環體是一個代碼塊 5 for (item: Int in ints) { 6 // ...... 7 } 8 9 //說明:for 可以循環遍歷任何提供了迭代器的對象。即: 10 // — 有一個成員函數或者擴展函數 iterator(),它的返回類型 11 // — 有一個成員函數或者擴展函數 next(),并且 12 // — 有一個成員函數或者擴展函數 hasNext() 返回 Boolean 。 13 // 這三個函數都需要標記為 operator 14 15 //3. 使用數字區間迭代 16 for (i in 1..3) { 17 println(i) 18 } 19 for (i in 6 downTo 0 step 2) { 20 println(i) 21 } 22 23 // 說明:對區間或者數組的 for 循環會被編譯為并不創建迭代器的基于索引的循環。 24 25 //4.如果想要通過索引遍歷一個數組或者list,你可以這么做: 26 for (i in array.indices) { 27 println(array[i]) 28 } 29 30 //4.1 或者使用庫函數 withIndex 31 for ((index, value) in array.withIndex()) { 32 println("the element at $index is $value") 33 }
22.while循環,這個沒什么變化,于java相同
while (x > 0) { x-- } do { val y = retrieveData() } while (y != null) // y 在此處可?
23.在kotlin中break和continue增加了指定標簽的方式,類似于C的寫法,標簽的格式為 標識符后跟@符號,例如 abc@
loop@ for (i in 1..100) { for (j in 1..100) { if (......) break@loop } }
24.return也可以采用標簽返回的方式,這種方式主要是為了更好的應用于lambda表達式中
fun foo() { listOf(1, 2, 3, 4, 5).forEach lit@{ if (it == 3) return@lit // 局部返回到該 lambda 表達式的調用者,即forEach 循環 print(it) } print(" done with explicit label") }
//當然也可以使用隱式標簽,該標簽于接受該lambda的函數同名
listOf(1, 2, 3, 4, 5).forEach {
print(" done with implicit label")
}
//或者用一個匿名函數替代lambda表達式,這樣return返回的是匿名函數自身
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
24.1 當要返回一個回值的時候,解析器優先選用標簽限制的return,例如:
return@a 1 //意為“返回 1 到 @a ”,而不是“返回一個標簽標注的表達式 (@a 1) ”

浙公網安備 33010602011771號