1. 程式人生 > >Kotlin開發一 kotlin程式設計基礎

Kotlin開發一 kotlin程式設計基礎

1 kotlin資料型別

1 數字型別
kotlin中數字的表示方式和java一樣
這裡寫圖片描述

kotlin中Float,Double,十六進位制,二進位制,10進位制的表示和java一樣,區別是kotlin中無八進位制表示
kotlin中數字型別沒有隱式轉換,必須顯示轉換
每個數字型別支援如下的轉換:

toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char

kotlin中位移運算用以下表示

shl(bits)
– 有符號左移 (Java 的 << ) shr(bits) – 有符號右移 (Java 的 >> ) ushr(bits) – 無符號右移 (Java 的 >>> ) and(bits) – 位與 or(bits) – 位或 xor(bits) – 位異或 inv() – 位非

數比較
相等性檢測: a == b 與 a != b
比較操作符: a < b 、 a > b 、 a <= b 、 a >= b
區間例項以及區間檢測: a..b 、 x in a..b 、 x !in a..b
kotlin中支援區間,a..b就是指[a,b]都是閉區間

2 字元
字元用 Char 型別表示。它們不能直接當作數字
字元字面值用單引號括起來: ‘1’ 。 特殊字元可以用反斜槓轉義。 支援這幾個轉義序列: \t 、 \b 、 \n 、 \r 、 \’ 、 \” 、 \ 與 $ 。 編碼其他字元要用 Unicode 轉義序列語法: ‘\uFF00’ 。
我們可以顯式把字元轉換為 Int 數字:

toInt()//轉換

當需要可空引用時,像數字、字元會被裝箱。裝箱操作不會保留同一性。

3 布林
布林用 Boolean 型別表示,它有兩個值: true 與 false 。若需要可空引用布林會被裝箱。
內建的布林運算有:

|| – 短路邏輯或
&& – 短路邏輯與
! - 邏輯非

4 陣列
陣列在 Kotlin 中使用 Array 類來表示,它定義了 get 與 set 函式(按照運算子過載約定這會轉變為 [] )以及 size 屬性,以及一些其他有用的成員函式:

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

fun main(args: Array<String>) {
    //sampleStart
    // 建立一個 Array<String> 初始化為 ["0", "1", "4", "9", "16"]
    val asc = Array(5, { i -> (i * i).toString() })
    asc.forEach { println(it) }
    //sampleEnd
}

如上所述, [] 運算子代表呼叫成員函式 get() 與 set() 。
注意: 與 Java 不同的是,Kotlin 中陣列是不型變的(invariant)。這意味著 Kotlin不讓我們把 Array 賦值給 Array ,以防止可能的執行時失敗(但是你可以使用 Array , 參見型別投影)。

Kotlin 也有無裝箱開銷的專門的類來表示原生型別陣列: ByteArray 、ShortArray 、 IntArray 等等。這些類與 Array 並沒有繼承關係,但是它們有同樣的方法屬性集。它們也都有相應的工廠方法:

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

5 字串
字串用 String 型別表示。字串是不可變的。 字串的元素——字元可以使用索引運算子訪問: s[i] 。 可以用 for 迴圈迭代字串:

fun main(args: Array<String>) {
    val str = "abcd"
    //sampleStart
    for (c in str) {
        println(c)
    }
    //sampleEnd
}

可以用 + 操作符連線字串。這也適用於連線字串與其他型別的值, 只要表示式中的第一個元素是字串:

Kotlin 有兩種型別的字串字面值: 轉義字串可以有轉義字元,以及原始字串可以包含換行以及任意文字。轉義字串很像 Java 字串:

val s = "Hello, world!\n"

轉義採用傳統的反斜槓方式。參見上面的 字元 檢視支援的轉義序列。
原始字串 使用三個引號( “”” )分界符括起來,內部沒有轉義並且可以包含換行以及任何其他字元:

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

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

fun main(args: Array<String>) {
    //sampleStart
    val i = 10
    println("i = $i") // 輸出“i = 10”
    //sampleEnd
}

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

fun main(args: Array<String>) {
    //sampleStart
    val s = "abc"
    println("$s.length is ${s.length}") // 輸出“abc.length is 3”
    //sampleEnd
}

6 引用型別
除以上基本型別之外,其他由類定義的資料型別都是引用型別。
當然String也是引用型別,基本型別的可空型別由於涉及到裝箱,也可以看做引用型別。這一點和java類似。

2 包

包的概念和命名和java一樣,只是kotlin中不要求檔案目錄和包一一匹配
與 Java 不同,Kotlin 沒有單獨的“import static”語法; 所有這些宣告都用 import關鍵字匯入

package com.qiyei.kotlin

3 控制流

控制流主要是if、when、for、while。相比java,kotlin用when替代了switch,但是when比switch更加強大

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 分支。

2 when 表示式
when 取代了類 C 語言的 switch 操作符。其最簡單的形式如下:

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

when 將它的引數與所有的分支條件順序比較,直到某個分支滿足條件。 when既可以被當做表示式使用也可以被當做語句使用。如果它被當做表示式, 符合條件的分支的值就是整個表示式的值,如果當做語句使用, 則忽略個別分支的值。(像if 一樣,每一個分支可以是一個程式碼塊,它的值是塊中最後的表示式的值。)如果其他分支都不滿足條件將會求值 else 分支。 如果 when 作為一個表示式使用,則必須有 else 分支, 除非編譯器能夠檢測出所有的可能情況都已經覆蓋了[例如,對於 列舉( enum )類條目與密封( sealed )類子型別]。

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

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 )一個特定型別的值。注意: 由於智慧轉換,你可以訪問該型別的方法與屬性而無需任何額外的檢測。

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

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

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

3 for 迴圈
for 迴圈可以對任何提供迭代器(iterator)的物件進行遍歷,這相當於像c# 這樣的語言中的 foreach 迴圈。語法如下:

for (item in collection) print(item)

迴圈體可以是一個程式碼塊。

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

如上所述, for 可以迴圈遍歷任何提供了迭代器的物件。即:

有一個成員函式或者擴充套件函式 iterator() ,它的返回型別有一個成員函式或者擴充套件函式 next() ,並且有一個成員函式或者擴充套件函式 hasNext() 返回 Boolean 。這三個函式都需要標記為 operator 。

如需在數字區間上迭代,請使用區間表示式:

fun main(args: Array<String>) {
    //sampleStart
    for (i in 1..3) {
        println(i)
    }
    for (i in 6 downTo 0 step 2) {
        println(i)
    }
    //sampleEnd
}

對區間或者陣列的 for 迴圈會被編譯為並不建立迭代器的基於索引的迴圈。
如果你想要通過索引遍歷一個數組或者一個 list,你可以這麼做:

fun main(args: Array<String>) {
    val array = arrayOf("a", "b", "c")
    //sampleStart
    for (i in array.indices) {
        println(array[i])
    }
    //sampleEnd
}

或者你可以用庫函式 withIndex :

4 while 迴圈

while迴圈,do while,break,continue這幾個與java中無區別

4 返回與跳轉

Kotlin 有三種結構化跳轉表示式:
return:預設從最直接包圍它的函式或者匿名函式返回。
break:終止最直接包圍它的迴圈。
continue:繼續下一次最直接包圍它的迴圈。
這些與java中並無什麼區別,所有這些表示式都可以用作更大表達式的一部分:

val s = person.name ?: return

當person.name如果為null時,將返回不會執行下面的程式碼

這些表示式的型別是 Nothing 型別。

break 與 continue 標籤
在 Kotlin 中任何表示式都可以用標籤( label )來標記。 標籤的格式為識別符號後跟 @ 符號,例如: [email protected][email protected] 都是有效的標籤(參見語法)。 要為一個表示式加標籤,我們只要在其前加標籤即可。

[email protected] for (i in 1..100) {
    // ……
}

現在,我們可以用標籤限制 break 或者 continue :

fun testBreakLabel(){
    loop@for(i in 1..100){
        for (j in 1..100){
            println(" i = $i j = $j")
            if (i== 2 && j == 2){
//                //預設退出的是內層迴圈,最直接包圍它的迴圈
//                break
                //退出到標籤迴圈
                break@loop
            }
        }
    }
}

標籤限制的 break 跳轉到剛好位於該標籤指定的迴圈後面的執行點。 continue繼續標籤指定的迴圈的下一次迭代。

return標籤
Kotlin 有函式字面量、區域性函式和物件表示式。因此 Kotlin 的函式可以被巢狀。 標籤限制的 return 允許我們從外層函式返回。 最重要的一個用途就是從 lambda表示式中返回。回想一下我們這麼寫的時候:

fun testReturnLabel(){

    listOf(1,2,3,4,5).forEach {
        if (it == 3){
            //直接return testReturnLabel的呼叫
            return
        }
        println("i = $it")
    }
    println("testReturnLabel end")
}

程式輸出

i = 1
i = 2

這個 return 表示式從最直接包圍它的函式即 foo 中返回。 (注意,這種非區域性的返回只支援傳給行內函數的 lambda 表示式。) 如果我們需要從 lambda 表示式中返回,我們必須給它加標籤並用以限制 return 。

fun testReturnLabel(){

    listOf(1,2,3,4,5).forEach it@{
        if (it == 3){
            //直接return testReturnLabel的呼叫
            return@it
        }
        println("i = $it")
    }
    println("testReturnLabel end")
}

一般比標籤與lambda 函式同名

fun testReturnLabel(){

    listOf(1,2,3,4,5).forEach {
        if (it == 3){
            //直接return testReturnLabel的呼叫
            //return
            return@forEach
        }
        println("i = $it")
    }
    println("testReturnLabel end")
}

輸出結果

i = 1
i = 2
i = 4
i = 5
testReturnLabel end

如果對於匿名函式,匿名函式內部的 return 語句將從該匿名函式自身返回

fun testReturnLabel2(){

    listOf(1,2,3,4,5).forEach (fun (value:Int){
        if (value == 3){
            //直接return testReturnLabel2的呼叫
            return
        }
        println("i = $value")
    })
    println("testReturnLabel2 end")
}

請注意,前文三個示例中使用的區域性返回類似於在常規迴圈中使用 continue 。並沒有 break 的直接等價形式,不過可以通過增加另一層巢狀 lambda 表示式並從其中非區域性返回來模擬

fun testReturnLabel3(){

    run lint@{ listOf(1,2,3,4,5).forEach {
        if (it == 3){
            //return lint 類似於在lint處continuereturn@lint
        }
        println("i = $it")
    }}
    println("testReturnLabel3 end")
}

輸出

i = 1
i = 2
testReturnLabel3 end

以上就是Kotlin程式設計的基礎,我們可以看到kotlin雖然也是一門JVM語言,但是在語法方面上與java還是有一些較大差異,特別是新增了很多kotlin獨有的特性,像if表示式,when,標籤,區間等。後續會繼續學習kotlin的其他語法