在Kotlin中,一切都是一個對象,可以在任何變量上調(diào)用成員函數(shù)和屬性。 一些類型是內(nèi)置的,因為它們的實現(xiàn)被優(yōu)化,但是它們看起來像普通類。 在本節(jié)中,我們將介紹描述Kotlin中的大多數(shù)類型:數(shù)字,字符,布爾和數(shù)組等等。
Kotlin以接近Java的方式來處理數(shù)字,但不完全相同。 例如,數(shù)字沒有隱含的擴展轉(zhuǎn)換,在某些情況下,字面量略有不同。
Kotlin提供以下代表數(shù)字的內(nèi)置類型(這接近Java):
| 類型 | 位寬度 |
|---|---|
| Double | 64 |
| Float | 32 |
| Long | 64 |
| Int | 32 |
| Short | 16 |
| Byte | 8 |
注意,字符不是Kotlin中的數(shù)字。
對于整數(shù)值,有以下幾種字面常量:
123123L0x0F0b00001011注意:不支持八進制字面常量。
Kotlin還支持一個常規(guī)的浮點數(shù)符號:
Double:123.5, 123.5e10f或F:123.5f可以使用下劃線使數(shù)字常量更易讀:
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
在Java平臺上,數(shù)字被物理存儲為JVM原始類型,除非需要一個可空的數(shù)字引用(例如Int?)或涉及泛型。 在后一種情況下,數(shù)字是裝箱的。
請注意,裝箱數(shù)字不一定保持身份:
val a: Int = 10000
print(a === a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!Prints 'false'!!!
另一方面,它保持相等:
val a: Int = 10000
print(a == a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA == anotherBoxedA) // Prints 'true'
由于不同的表示,較小的類型不是較大的類型的子類型,就會有以下類型的麻煩:
// Hypothetical code, does not actually compile:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // implicit conversion yields a boxed Long (java.lang.Long)
print(a == b) // Surprise! This prints "false" as Long's equals() check for other part to be Long as well
因此,較小的類型不會被隱式轉(zhuǎn)換為更大的類型。 這意味著不能在沒有顯式轉(zhuǎn)換的情況下將Byte類型的值賦給Int類型的變量。
val b: Byte = 1 // OK, literals are checked statically
val i: Int = b // ERROR
可以使用顯式轉(zhuǎn)換來擴寬數(shù)字 -
val i: Int = b.toInt() // OK: explicitly widened
每個數(shù)字類型都支持以下轉(zhuǎn)換:
toByte(): BytetoShort(): ShorttoInt(): InttoLong(): LongtoFloat(): FloattoDouble(): DoubletoChar(): Char缺少隱式轉(zhuǎn)換是很少引人注意的,因為類型是從上下文推斷出來的,而算術(shù)運算則被重載為適當?shù)霓D(zhuǎn)換,例如 -
val l = 1L + 3 // Long + Int => Long
Kotlin支持對數(shù)字進行的算術(shù)運算的標準集合,它們被聲明為適當類的成員(但編譯器將調(diào)用優(yōu)化為相應(yīng)的指令)。請參閱操作符重載。
對于按位操作,它們沒有特殊的字符,但是只能命名為可以以中綴形式調(diào)用的函數(shù),例如:
val x = (1 shl 2) and 0x000FF000
以下是按位操作的完整列表(僅適用于Int和Long):
shl(bits) – 有符號向左移 (Java的<<)shr(bits) – 有符號向右移 (Java’s >>)ushr(bits) – 無符號向右移 (Java’s >>>)and(bits) – 位運算符andor(bits) – 位運算符orxor(bits) – 位運算符xorinv() – 位運算符”取反”字符由Char類型表示,它們不能直接被視為數(shù)字
fun check(c: Char) {
if (c == 1) { // ERROR: incompatible types
// ...
}
}
字符文字用單引號表示:'1'。 可以使用反斜杠轉(zhuǎn)義特殊字符。 支持以下轉(zhuǎn)義序列: \t, \b, \n, \r,\', \", \\ 和 \$; 要編碼任何其他字符,請使用Unicode轉(zhuǎn)義序列語法:'\uFF00'。
可以將一個字符顯式轉(zhuǎn)換為一個Int類型數(shù)字:
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // Explicit conversions to numbers
}
像數(shù)字一樣,當需要可空引用時,字符將被包裝。標識不能被裝箱操作所保留。
Boolean類型表示布爾值,并具有兩個值:true和false。
如果需要可空引用,布爾值將可被裝箱。
內(nèi)置的布爾操作包括:
|| – 懶分離&& – 懶結(jié)合! - 否定Kotlin中的數(shù)組由Array類表示,它有get()和set()函數(shù)(通過運算符重載約定轉(zhuǎn)換為[]),以及size屬性以及其他一些有用的成員函數(shù):
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>
// ...
}
要創(chuàng)建一個數(shù)組,我們可以使用一個庫函數(shù)arrayOf(),并將數(shù)組的元素值傳遞給它,如:arrayOf(1,2,3)創(chuàng)建一個數(shù)組[1,2,3]。 或者arrayOfNulls()庫函數(shù)可用于創(chuàng)建一個填充空(null)元素的給定大小的數(shù)組。
另一個選擇是使用一個工廠函數(shù),它使用數(shù)組大小和返回給定其索引的每個數(shù)組元素的初始值的函數(shù):
// Creates an Array<String> with values ["0", "1", "4", "9", "16"]
val asc = Array(5, { i -> (i * i).toString() })
如上所述,[]操作代表調(diào)用成員函數(shù)get()和set()。
注意:與Java不同,Kotlin中的數(shù)組是不變的。 這意味著Kotlin不允許將Array <String>分配給Array <Any>,這樣可以防止可能的運行時故障(但可以使用Array <out Any>),詳細的可參考類型投影。
Kotlin還有專門的類來表示原始類型的數(shù)組,沒有裝箱開銷,它們分別是:ByteArray, ShortArray, IntArray等等。
這些類與Array類沒有繼承關(guān)系,但它們具有相同的方法和屬性集。它們也有相應(yīng)的工廠函數(shù):
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
字符串由String類型表示。字符串是不可變的。 字符串的元素可以通過索引操作的字符:s[i]來訪問。可以使用for循環(huán)迭代字符串:
for (c in str) {
println(c)
}
Kotlin有兩種類型的字符串字面值:可以在其中轉(zhuǎn)義字符的轉(zhuǎn)義字符串,以及可以包含換行符和任意文本的原始字符串。 轉(zhuǎn)義的字符串非常像Java字符串:
val s = "Hello, world!\n"
使用反斜杠以常規(guī)方式完成轉(zhuǎn)義。 有關(guān)支持的轉(zhuǎn)義序列的列表,請參閱上述字符。
原始字符串由三重引號(""")分隔,不包含轉(zhuǎn)義,并且可以包含換行符和任何其他字符:
val text = """
for (c in "foo")
print(c)
"""
可以使用trimMargin()函數(shù)刪除前導(dǎo)空格:
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
默認使用|作邊距前綴,但您可以選擇另一個字符,并將其作為參數(shù)傳遞:trimMargin(">")。
字符串可以包含模板表達式,即被評估的代碼片段,并且其結(jié)果被連接到字符串中。 模板表達式以美元符號($)開頭以及簡單名稱組成:
val i = 10
val s = "i = $i" // evaluates to "i = 10"
或大括號中的任意表達式:
val s = "abc"
val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
原始字符串和轉(zhuǎn)義字符串內(nèi)部都支持模板。如果您需要在原始字符串(不支持反斜杠轉(zhuǎn)義)中表示一個文字$字符,則可以使用以下語法:
val price = """
${'$'}9.99
"""