1. 程式人生 > >Kotlin-04.基本型別/資料型別(Basic Types)

Kotlin-04.基本型別/資料型別(Basic Types)

1.介紹

與java不同,Kotlin所有資料型別都是物件,因此可在任何變數上呼叫成員函式和屬性(欄位)!

2.數字

Kotlin 處理數字在某種程度上接近 Java,但是並不完全相同。
例如,對於數字沒有隱式把範圍變寬轉換(如在 Java 中 int 可以隱式轉換為long),
另外有些情況的字面值略有不同。

Kotlin 內建數字型別:
    型別    位數
    Double  64
    Float   32
    Long    64
    Int     32
    Short   16
    Byte    8
注意在 Kotlin 中字元Char不能轉化為數字

3.數值字面常量

數值常量字面值表示:
    十進位制:   123        
    十六進位制: 0x0F
    二進位制:   0b00001011
    注意: 不支援八進位制(而java以0開頭表示八進位制 07)

    Long 用大寫 L 標記:    123L  
    Float 用 f 或 F 標記:  123.5f
    double:              123.5、123.5e10

自 Kotlin 1.1 起,用下劃線使數字更易讀:   
    val oneMillion = 1_000_000
    val creditCardNumber = 1234_5678_9012_3456L
    val socialSecurityNumber = 999_99_9999L
    val hexBytes = 0xFF_EC_DE_5E
    val bytes = 0b11010010_01101001_10010100_10010010

4.數字自動裝箱-表示方式

Kotlin數字在虛擬機器中是物理儲存為JVM原生型別,但如果是可null引用(有問號?)或者泛型物件,
那麼kotlin數字就會自動裝箱(類似java包裝類,如int自動裝箱轉為Integer)

kotlin數字自動裝箱的例項:
    val a: Int = 10000       
    val boxA: Int? = a //有問號? 會自動裝箱
    val boxB: Int? = a //有問號? 會自動裝箱

kotlin三個等號===比較的是物件地址(引用),自動裝箱會生成新物件,兩個物件不同,輸出false
但是數值在-128和127之間時,自動裝箱會重用同一個物件(java快取機制),輸出true
    print(boxA === boxB) //輸出false,如果數值在-128和127之間,輸出true

kotlin兩個等號==比較的是物件數值,兩個物件數值相同,輸出true
    print(boxA == boxB) //輸出true

5.顯式轉換

範圍較小數字型別不能隱式轉換為範圍較大型別。
    val b: Byte = 1 // 正確, 字面值是靜態檢測的
    val i: Int = b // 錯誤: 隱式擴寬
    val i: Int = b.toInt() // 正確: 顯式擴寬

每個數字型別支援如下型別轉換:
    toByte(): Byte
    toShort(): Short
    toInt(): Int
    toLong(): Long
    toFloat(): Float
    toDouble(): Double
    toChar(): Char

缺少隱式擴寬轉換是很少引人注意的,因為型別是從上下文推斷出來的,而算術運算會有過載做適當擴寬轉換,例如:
    val l = 1L + 3 // Long + Int => Long

6.位運算

Kotlin支援數字運算的標準集,運算被定義為相應的類成員(但編譯器會將函式呼叫優化為相應的指令)
對於按位運算,沒有特殊字元來表示,而只可用中綴方式呼叫函式,例如:
    val x = (1 shl 2) and 0x000FF000
以下是完整位運算列表(只用於 Int 和 Long):
    shl(bits) – 有符號左移 (Java 的 <<)
    shr(bits) – 有符號右移 (Java 的 >>)
    ushr(bits) – 無符號右移 (Java 的 >>>)
    and(bits) – 位與
    or(bits) – 位或
    xor(bits) – 位異或
    inv() – 位非

7.字元

字元用 Char 型別表示,不能直接當作數字
    fun check(c: Char) {
        if (c == 1) { // 錯誤:型別不相容
            // ……
        }
    }
字元字面值用單引號括起來: '1' 
特殊字元可以用反斜槓轉義: \t、 \b、\n、\r、\'、\"、\\ 和 \$。 
編碼其他字元用 Unicode 轉義序列語法:'\uFF00'。

我們可以顯式把字元轉換為 Int 數字
fun decimalDigitValue(c: Char): Int {
    if (c !in '0'..'9')
        throw IllegalArgumentException("Out of range")
    return c.toInt() - '0'.toInt() // 顯式轉換為數字
}
當需要可null引用時,像數字一樣,字元也會被裝箱。
裝箱操作不會保留同一性(同一物件)。

8.布林

布林用 Boolean 型別表示,它有兩個值:true 和 false。
若需要可空引用布林會被裝箱。

9.陣列

陣列在 Kotlin 中使用 Array 類來表示,它定義了 get 和 set 函式(按照運算子過載約定轉變為 [])和 size 屬性

使用庫函式 arrayOf() 來建立一個數組並傳遞元素值
    arrayOf(1, 2, 3) 建立了 array [1, 2, 3]
或  arrayOfNulls() 建立一個指定大小的null陣列

使用接受陣列大小和一個函式引數的工廠函式,用作引數的函式能夠返回每個元素初始值:
    // 建立一個 Array<String> 初始化為 ["0", "1", "4", "9", "16"]
    val asc = Array(5, { i -> (i * i).toString() })

注意: 與 Java 不同的是,Kotlin 中陣列是不型變的(invariant)。
這意味著 Kotlin 不讓 Array<String> 賦值給 Array<Any>,以防止可能的執行時失敗(但是可用 Array<out Any>)

還有無裝箱開銷的類表示原生型別陣列: ByteArray、 ShortArray、IntArray 等等,這些類和 Array 並沒有繼承關係,但是有同樣方法屬性,相應的工廠方法
    val x: IntArray = intArrayOf(1, 2, 3)
    x[0] = x[1] + x[2]

10.字串

字串用 String 型別表示,字串是不可變的;
字串元素可通過索引操作 s[i]
可用 for 迴圈迭代字串:
    for (c in str) {
        println(c)
    }

1.字串字面值

Kotlin 有兩種型別的字串字面值: 
一是轉義字串 可以有轉義字元,二是原始字串 可以包含換行和任意文字

轉義字串 很像 Java 字串:
    val s = "Hello, world!\n"
    轉義採用傳統的反斜槓方式

原始字串 使用三個引號 """ 括起來,
內部沒有轉義並且可以包含換行和任何其他字元:
    val text = """
        for (c in "foo")
            print(c)
    """

你可以通過 trimMargin() 函式去除前導空格:
val text = """
    |Tell me and I forget.
    |Teach me and I remember.
    |Involve me and I learn.
    |(Benjamin Franklin)
    """.trimMargin()
預設 | 用作邊界字首,可用其他字元作為引數傳入 trimMargin(">")

2.字串模板

字串可以包含模板表示式 ,即一些小段程式碼,會求值並把結果合併到字串中。 
模板表示式以美元符 $ 開頭

由一個簡單變數構成:
    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
                """