原文地址
Basic Types
在Kotlin中,在通過變量調(diào)用成員函數(shù)和屬性的意義上來講,任何東西都是對象。一些類型是嵌入的,由于他們的實(shí)現(xiàn)被優(yōu)化了,但是對于用戶他們看起來像普通的類。在本章中我們描述多數(shù)這種類型:如數(shù)字、字符、布爾和數(shù)組。
數(shù)字:
Kotlin處理數(shù)字的方式接近java,但不完全相同。例如,這兒沒有對數(shù)字隱性擴(kuò)展轉(zhuǎn)換,并且字面值在某些情況下也不一樣。
Kotlin提供如下嵌入類型代表數(shù)字(很像java)
| Type | Bit width |
|---|---|
| Double | 64 |
| Float | 32 |
| Long | 64 |
| Int | 32 |
| Short | 16 |
| Byte | 8 |
注意在Kotlin中字符不是數(shù)字
Literal Constants(字面常量)
下面是幾種字面常量對于整數(shù):
- 十進(jìn)制:123
- 被大寫字母L標(biāo)記的長整形:123L
- 16進(jìn)制:0x0F
- 二進(jìn)制:0b00001011
注意:8進(jìn)制字面值是不支持的。
Kotlin也支持常規(guī)的符號對于浮點(diǎn)型:
- Doubles by default(默認(rèn)Double型): 123.5, 123.5e10
- Floats 被標(biāo)記為f或者F:123.5f
Underscores in numeric literals (since 1.1)(數(shù)字中的下劃線)
為了讓數(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
Representation
在Java平臺中,數(shù)字被存為JVM原始類型,除非我們需要一個(gè)可空的數(shù)字引用(也就是Int?)或者涉及到泛型時(shí)。下面的情況當(dāng)中數(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'
Explicit Conversions(顯示轉(zhuǎn)換)
由于不同表示,較小的類型不是較大類型的子類型。如果他們是,我們將在一些情況下有一些問題:
//假定代碼,并不實(shí)際編譯:
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
所以不僅一致性,甚至相等性也將會消失。
結(jié)果是,較小的類型不會隱式轉(zhuǎn)換為較大的類型。我們不能把一個(gè)Byte的值賦給一個(gè)Int變量在沒有明確的轉(zhuǎn)換的情況下。
val b: Byte = 1 // 成功,字面值被靜態(tài)的檢查
val i: Int = b // ERROR
我們可以使用顯示轉(zhuǎn)換去擴(kuò)大的數(shù)字
val i: Int = b.toInt() // OK: explicitly widened
每個(gè)數(shù)字類型支持如下轉(zhuǎn)換:
? oByte(): Byte
? toShort(): Short
? toInt(): Int
? toLong(): Long
? toFloat(): Float
? toDouble(): Double
? toChar(): Char
隱式轉(zhuǎn)換的缺失很少被注意到因?yàn)樯舷挛闹械念愋屯茢?,和算術(shù)操作符被重載為合適的轉(zhuǎn)換,例如:
val l = 1L + 3 // Long + Int => Long
Operations
Kotlin支持被聲明為類成員的數(shù)字運(yùn)算的標(biāo)準(zhǔn)集。(但是編譯器優(yōu)化了相關(guān)的調(diào)用指令),參看操作符重載
作為位運(yùn)算,這里沒有特殊的字符,但是只有能夠以前綴方式調(diào)用的命名函數(shù),例如:
val x = (1 shl 2) and 0x000FF000
這兒有完整的未操作符(僅僅適用于整型和長整型)
? 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
字符
字符被Char類型表示,他們不能直接被當(dāng)做數(shù)字
fun check(c: Char) {
if (c == 1) { // ERROR: incompatible types
// ...
}
}
字符文字在單引號中’1’.特殊字符能夠被轉(zhuǎn)義用反斜杠。如下轉(zhuǎn)義結(jié)果被支持:\t, \b, \n, \r, ', ", \ and $.為了編碼其他任何字符,適用Unicode轉(zhuǎn)義語法:'\uFF00'
我們可以明確的把一個(gè)字符轉(zhuǎn)為一個(gè)整型:
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ù)字那樣,字符被裝箱當(dāng)可空引用類型需要的時(shí)候。通過裝箱操作,一致性將不被保留。
布爾類型
Boolean類型代表布爾類型,并且有兩個(gè)值:true和false。
布爾類型被裝箱當(dāng)一個(gè)可空的引用被需要的時(shí)候。
嵌入操作當(dāng)布爾類型包括
? || – lazy disjunction
? && – lazy conjunction
? ! - negation
數(shù)組
Arrays 在Kotlin中代表有g(shù)et和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)建一個(gè)數(shù)組,我們可以使用一個(gè)庫函數(shù)arrayof()并且傳進(jìn)一些值進(jìn)去。所以arrayof(1,2,3)創(chuàng)建一個(gè)數(shù)組array[1,2,3].相反的,arrayofNulls()庫函數(shù)可以用于創(chuàng)建一個(gè)空數(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中的arrays是不變的。也就意味kotlin不允許我們分配一個(gè)Array<String>到Array<Any>,這阻止了一個(gè)運(yùn)行時(shí)異常(但是你可以使用Array<out Any>,參看Type Projections)
Kotlin也有一些特殊的類代表沒有裝箱損耗的原始類型的數(shù)組:ByteArray,ShortArray,IntArray等等,這些類沒有Array類的相關(guān)繼承類,但是他們有相同的屬性和函數(shù)集合。他們中每一個(gè)也含有一個(gè)相應(yīng)的工廠函數(shù):
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
字符串
字符串代表類型String。字符串是不可變的。String中的元素是可以被索引操作訪問的字符:s[i]。一個(gè)字符串可以通過for循環(huán)遍歷
for (c in str) {
println(c)
}
String 字面值
Kotlin有兩種類型的字符串字面值:轉(zhuǎn)義字符串可能含有轉(zhuǎn)義字符,原始字符串可以包含換行和任意文本。一個(gè)轉(zhuǎn)義字符串非常像java字符串。
Val s= “Hello,World!\n”
轉(zhuǎn)義是像傳統(tǒng)方式那樣完成的,通過反斜杠。參看之上的Characters,支持的轉(zhuǎn)義序列列表
一個(gè)原始字符串被一個(gè)引用(“””)限定,包含非轉(zhuǎn)義和能夠包含換行和其他任意字符串。
val text = """
for (c in "foo")
print(c)
"""
你可以移除開頭空格通過trimMargin()函數(shù):
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
默認(rèn)情況下| 用于頁邊前綴,但是你能夠選擇另一個(gè)字符串并且把它當(dāng)做參數(shù)傳入,例如trimMargin(">").
字符串模板
字符串可能包含模板表達(dá)式,也就是被評估的代碼碎片和結(jié)果被嵌入到字符串中。一個(gè)模板表達(dá)式可以以美元符號開始并且包含一個(gè)簡單的名稱:
val i = 10
val s = "i = $i" // evaluates to "i = 10"
或者一個(gè)在花括號中的任意表達(dá)式:
val s = "abc"
val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
模板同時(shí)被原始字符串和轉(zhuǎn)義字符串支持。如果你需要表示一個(gè)字面值$字符在原始字符串中(不支持反斜杠轉(zhuǎn)義),你可以使用如下語法:
val price = """
${'$'}9.99
"""