寫在前面: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
- Float
用f
或F
標記: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裏===
表示引用相等,即當a
和b
都指向同一個對象時,a === b
才爲true
。如果用===
來比較原始類型數據
,比如Int
,那麼其作用相當於==
。
上面代碼中boxedA === anotherBoxedA
爲什麼會返回false呢? 首先,我們已經知道,可空引用數字將會使數字被封裝,因此這個比較並不是原始類型數據的比較,而是封裝後的數字對象的比較,即引用相等性比較。
在Java中,對數字封裝時,值大小在 -128
到127
之間的數字封裝會被緩存起來,如下:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
可以看到,調用valueOf
方法對數字封裝時,如果值大小在-128
到 IntegerCache.high
之間,會返回緩存中的對象,否則返回一個新的對象。這個IntegerCache.high
是由系統來決定的,也可以自己設置。所以如果一個數字的數值在-128
到 IntegerCache.high
之間,不管對它封裝多少次,其引用地址都是同一個。而數值在此之外的數字,每次對其進行封裝都會產生一個新的對象,其引用地址當然也不相同。
因此,如果把上面代碼中的常量a
的大小改爲-128
到127
之間的數字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
方法比較a
和b
,如果a
爲null
,則檢查b
是否也爲null
。
1.4 顯示轉換
在Java中,小的數字類型可以隱式轉換爲大的數字類型,比如:
byte b = 10;
int i = b;
double d = i;
byte
可以隱式轉int
,int
可以隱式轉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 == b
和a != 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
類型代表布爾值,有true
和false
兩種取值。
如果布爾值被可空引用,將被自動封裝。
內置的邏輯操作符包括:
- || -短路邏輯或
- && - 短路邏輯與
- ! - 邏輯非
4. 數組
Kotlin中數組用Array
類表示,數組有get
和set
方法(會通過操作符重載轉換爲[]
),並且擁有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>
// ...
}
要創建一個數組,可以使用 library
的 arrayOf()
方法,比如arrayOf(1, 2, 3)
會創建一個數組[1, 2, 3]
。此外,libray
的 arrayOfNulls()
方法能用來創建一個指定長度的元素全是null
的數組。比如:arrayOfNulls<Int>(2)
將創建一個size
爲2
的Int
數組,數組裏元素的值都是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中文站文檔 。
新手入門,難免有理解錯誤的地方,請多指教。