Kotlin學習之基礎篇—基本數據類型


寫在前面:Kotlin的起始篇其實還有一篇講Kotlin的編碼規範,實在太長我就不翻譯了,其實規範大多和Java編碼規範類似,當然也有不一樣的地方。如果想了解不妨看 Kotlin編碼規範-官方文檔 。或者看中文版 Kotlin編碼規範-kotlin中文站文檔

Kotlin中,一切皆對象,從這個意義上來說,可以調用任何成員變量的方法和屬性。有些數據類型具有特殊的內部表示,例如:數字字符布爾值能表示爲運行時的原始值,雖然對於用戶來說它們看起來沒什麼特殊。這一節我們將講述Kotlin中的這些基本的數據類型:數字字符布爾值數組字符串


1. 數字

Kotlin處理數字的方式和Java類似,但並不完全相同。例如,數字之間不能像Java那樣隱式轉換。
Kotlin提供了以下內建類型來表示數字(和Java類似)

類型 位數
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

注意:char類型在Kotlin中不是數字

1.1 字面常量

數字有以下幾種字面值
- 十進制
– 比如Long類型通常以L爲標記:123L
- 十六進制:0x0F
- 二進制: 0b00001011
注意:Kotlin不支持八進制

Kotlin也支持浮點數的簡便寫法:
- Double默認寫法: 123.5,1.235e2
- FloatfF標記:123.5f

1.2 數字文字中的下劃線

可以使用下劃線來使數字更易讀,而不會改變數字大小:

val oneMillion = 1_000_000
val creditCardNumber = 123_5678_2344_1233L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

如果把上面的下劃線都去掉,數值的大小不會有任何改變,加下劃線只是爲了格式更清楚更易讀而已。

1.3 表現方式

在Java平臺上,數字被物理存儲爲JVM的原始類型,除非我們需要一個可空的數字引用或者泛型。在後一種情況下,數字將被封裝。

注意:數字封裝後不一定會保持相等性。

val a: Int = 10000
print(a === a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!Prints 'false'!!!

先有必要說下運算符===,在Java裏面,並沒有這個運算符,只有==。在Kotlin裏===表示引用相等,即當ab都指向同一個對象時,a === b才爲true。如果用===來比較原始類型數據,比如Int,那麼其作用相當於==

上面代碼中boxedA === anotherBoxedA爲什麼會返回false呢? 首先,我們已經知道,可空引用數字將會使數字被封裝,因此這個比較並不是原始類型數據的比較,而是封裝後的數字對象的比較,即引用相等性比較。

在Java中,對數字封裝時,值大小在 -128127 之間的數字封裝會被緩存起來,如下:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

可以看到,調用valueOf方法對數字封裝時,如果值大小在-128IntegerCache.high 之間,會返回緩存中的對象,否則返回一個新的對象。這個IntegerCache.high是由系統來決定的,也可以自己設置。所以如果一個數字的數值在-128IntegerCache.high之間,不管對它封裝多少次,其引用地址都是同一個。而數值在此之外的數字,每次對其進行封裝都會產生一個新的對象,其引用地址當然也不相同。

因此,如果把上面代碼中的常量a的大小改爲-128127之間的數字boxedA === anotherBoxedA將返回true

val a: Int = 10000
print(a == a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA == anotherBoxedA) // Prints 'true'

封裝後的數字將保持結構相等,上述代碼中boxedA == anotherBoxedA將返回true。在Kotlin中==可以稱之爲結構相等,其作用類似於方法equals,可以用以下代碼表示:

a?.equals(b) ?: (b === null)

如果a不爲null,則調用equals方法比較ab,如果anull,則檢查b是否也爲null

1.4 顯示轉換

在Java中,小的數字類型可以隱式轉換爲大的數字類型,比如:

byte b = 10;
int i = b;
double d = i;

byte可以隱式轉intint可以隱式轉double

但Kotlin中不支持這種轉換,如果要轉換隻能顯示地調用相關的方法,目前各種數字類型都有以下轉換方法:
- toByte(): Byte
- toShort(): Short
- toInt(): Int
- toLong(): Long
- toFloat(): Float
- toDouble(): Double
- toChar(): Char

缺少隱式轉換並沒有多大影響,因爲數值的類型可以根據上下文自動推斷,而算術運算符已經被重載以在運算時作適當的轉換,例如:

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

上面這句代碼是ok的,因爲算術運算符在運算過程中對數字的類型做了相應的轉換。

1.5 運算

Kotlin支持標準的算術運算。但是對於位運算,Kotlin中並沒有定義相應的操作符,只能通過調用相關的方法。比如:

val x = (1 shl 2) and 0x000FF000

以下是一些位運算相應的操作方法(只支持Int和Long類型):
- shl(bits) – 左移:signed shift left (Java’s <<)
- shr(bits) – 右移:signed shift right (Java’s >>)
- ushr(bits) – 無符號右移:unsigned shift right (Java’s >>>)
- and(bits) – 按位與:bitwise and
- or(bits) – 按位或:bitwise or
- xor(bits) – 按位異或:bitwise xor
- inv() – 按位取反:bitwise inversion

1.6 浮點數比較
  • 相等性檢查: a == ba != b
  • 比較操作符:a < b,a > b, a <= b, a >= b
  • 範圍及範圍檢查: a..b, x in a..b, x !in a..b


2. 字符

字符類型由Char來表示,字符不能直接作爲數字使用。

字符字面量要加單引號表示:'1'。特殊字符可以使用反斜槓轉義,Kotlin支持以下轉義序列:
\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() // Explicit conversions to numbers
}

和數字一樣,當引用可空字符時,字符會被自動封裝。字符封裝後將不保持相等性。


3. 布爾值

Boolean類型代表布爾值,有truefalse兩種取值。
如果布爾值被可空引用,將被自動封裝。

內置的邏輯操作符包括:
- || -短路邏輯或
- && - 短路邏輯與
- ! - 邏輯非


4. 數組

Kotlin中數組用Array類表示,數組有getset方法(會通過操作符重載轉換爲[]),並且擁有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>
    // ...
}

要創建一個數組,可以使用 libraryarrayOf() 方法,比如arrayOf(1, 2, 3)會創建一個數組[1, 2, 3]。此外,librayarrayOfNulls() 方法能用來創建一個指定長度的元素全是null的數組。比如:arrayOfNulls<Int>(2)將創建一個size2Int數組,數組裏元素的值都是null

另一種創建數組的方法是使用Array的構造方法,如下:

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

注意:和Java不一樣,Kotlin中的數組是不可變的,這意味着Kotlin不允許我們將一個字符串數組Array<String>直接賦值給數組Array<Any>,這能防止可能出現的運行時錯誤。

Kotlin也有一些避免原始類型數組封裝消耗的類:ByteArray, ShortArray, IntArray等。這些類和Array類並沒有繼承關係,但是它們擁有同樣的方法和屬性。它們也都有相應的工廠方法:

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


5. 字符串

字符串類型用String來表示。字符串是不可變的。字符串的元素(字符)能夠通過索引的方式來訪問:s[i]。字符串可以使用for循環來迭代:

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

和Java一樣,Kotlin能使用加法操作符+來連接字符串,即使不是字符串類型的數值也可以連接,但和Java有所不同的是,連接表達式中的第一個元素必須是字符串類型。

val s = "abc" + 1
println(s + "def")

打印結果爲:

abc1def

注意:在大多數情況下,使用字符串模板或者原始字符串,優於使用字符串連接。

5.1 字符串字面量

Kotlin有兩種字符串字面量:包含轉義字符的轉義字符串 和 包含隨意字符或新行的原始字符串。轉義字符串和Java的字符串類似:

val s = "Hello, world!\n"

原始字符串由三引號"""來定義,如下:

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


5.2 字符串模板

字符串模板在 Kotlin學習之起始篇—基礎語法 已經介紹過了,這裏不再贅述。


以上內容參考了 Kotlin官方文檔Kotlin中文站文檔
新手入門,難免有理解錯誤的地方,請多指教。

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