Kotlin中的基本資料類型
作為Google【官方指定的幹兒子】,Kotlin語言今年受到了越來越多的重視。無論是開發Android還是背景程式,這門語言以後一定是大有可為。由于相關的文章很多,那我們不多介紹這門語言是怎麼來的。就讓我們慢慢來,一點一點的去品味Kotlin。
第一章,一起來看看這門語言的基本資料類型吧。
開始之前,我們需要明确一點:
kotlin是一門【強類型】、【靜态類型】、【支援隐式類型】的【顯式】類型語言。
PS:
1、強類型:強類型語言的編譯器引入了較多的類型檢查限制,是以在運作時不會發生未經明确(顯示轉換)類型轉換的類型轉換。常見的語言中,Java就是強類型語言,而JavaScript則是弱類型語言。
2、靜态類型:根據類型檢查在編譯時期還是運作時期,我們把語言分為靜态類型以及動态類型。靜态語言是基于編譯器來確定語言類型的安全。
3、顯式類型:根據變量名是否需要顯式的給出聲明,我們可以将語言分為顯式類型以及隐式類型。kotlin是顯式類型的語言,與此同時又因為有【類型推斷】的作用是以可以看做是支援隐式類型。
一、簡述
1、var 與 val
kotlin中,var符号表示的事變量,可以多次重複指派。
而val表示的是“常量”,但這并不是通俗意義上的常量。本質上val也是變量,但一次指派之後,不能再次修改,隻能作為【隻讀變量】。
2、kotlin中的根類型:Any
kotlin中萬物皆對象,所有類型都是引用類型。所有的類都有一個超類:Any。
官方文檔是這麼說的:
這個類隻有三個方法:
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
如果類聲明中,沒有指明超類,則預設為Any。
kotlin中的Any映射為java中的java.lang.Object.
特别注意的一點:java中Object隻是所有引用類型的超類,而基本類型int、long等不包含在内。而kotlin中,Any是一切的超類。
3、kotlin中的數字類型
3.1、常識介紹
kotlin中常見的數字類型分為以下6種:
方法名 | 轉換類型 | 補充 |
---|---|---|
Byte | 8位 | 1位元組 |
Short | 16位 | 2位元組 |
Int | 32位 | 4位元組 |
Long | 64位 | 8位元組 |
Float | 32位 | 4位元組 |
Double | 64位 | 8位元組 |
根據名稱可以看出基本和java中的相關定義相近。
kotlin支援二進制、十進制、十六進制;
但【不】支援八進制
與此同時,kotlin在數值類型的表示方式上也支援下劃線,如:
val Million = 1000_000_000
val tmp = 123_456_789L
val demo = 0xDD_FF_EE
kotlin中的數字類型與java很是相近,但有一點不同:
kotlin沒有java語言的隐式變換(如byte->short->int->long 等)。
是以,java中的如下代碼,在kotlin中是無法編譯的:
short a = 1;
int b = a;
當然,在kotlin中應該這樣描述:
val a : Int = 1
val b : Long = a
上述代碼同樣是無法通過編譯的!
是以,遇到類型轉換我們就應該考慮一下【顯式轉換】:
java中,我們一般會這樣進行數值類型的顯式轉換:
int a = 1;
...
Long tmp = (long)a;
而kotlin中,我們可以這樣:
val a : Int = 1
val b : a.toLong()
相關的方法彙總如下:
方法名 | 轉換類型 |
---|---|
toByte() | Byte |
toShort() | Short |
toInt() | Int |
toLong() | Long |
toFloat() | Float |
toDouble() | Double |
toChar() | Char |
這裡需要注意一點的是:
與java不同,kotlin中Char類型僅僅表示字元,不能再被直接當做數字。 是以,Char類型的變量必須在單引号之間表示:’變量’。(CSDN部落格這裡顯示有誤。。。)
一段簡單的java代碼如下:
char a = 'c';
System.out.println(a+1);
此時列印的結果為【數字】100。
而作為對比,在kotlin中:
val a : Char = 'c'
println(a+1)
上述代碼的列印結果為【字元】d
是以我們要明确:Kotlin中 Char類型由于不是直接當數值用,是以最後傳回依舊是Char型。
3.2、一些需要注意的點
3.2.1、== 與 ===
kotlin中并沒有單純的數值,在我們定義每一個數值的時候,kotlin編譯器都在默默的為我們将定義的數值封裝成一個對象,以最大限度的解決空指針異常的問題。是以kotlin中數值的比較除了我們常見的 == 号之外還多了 === 。
當然,根據面向對象的定義也可以快速的了解:
符号名 | 作用 | 否定形式 |
---|---|---|
== | 【結構相等】比較兩個具體的【數值的大小】是否相同 | != |
=== | 【引用相等】比較兩個對象【在記憶體的存儲位址】是否相同 | !== |
ps:
編譯器中,== 等同于equal()方法。
舉個栗子來看:
fun main(args: Array<String>){
val a : Int = 10
println(a === a) //此處傳回的值為true
val b : Int = a
println(a === b) //此處傳回的值為true,因為指派操作是記憶體位址指派,而記憶體位址相同,其中的數字值自然相同
println(a == b) //此處傳回的值為true,原因同上
}
【☆☆☆】考慮到裝箱問題:數字裝箱不保留【同一性】,但保留數值的【相等性】。
val a: Int = 200
println(a === a) //此處傳回的值為true
val b :Int ? = a
println(a === b) //此處傳回的值為false,因為這是兩個對象,記憶體位址不相同
println(a == b) //此處傳回的值為true,數值相同
當然還有一個特殊情況,考慮到JVM虛拟機的常量池特性:
val a: Int = 20
println(a === a) //此處傳回的值為true
val b :Int ? = 20
println(a === b) //此處傳回的值為true
println(a == b) //此處傳回的值為true,數值相同
PS:
【1】JVM虛拟機中維護着有符号整形常量池(-128,127),在這個範圍裡的數值都會直接使用常量池的記憶體位址,是以這個範圍内的數值裝箱後比較記憶體位址依舊是相等的。(常量池主要用于存放兩大類常量:字面量(Literal)和符号引用量(Symbolic References))
【2】kotlin中,?表示這個對象可能為空。是以這一句“val b :Int ? = a”
表示的意思除了普通的數字指派外,還多了一層含義:如果被指派對象為空,則開辟記憶體建立新的對象。
3.2.2、移位操作
在java中,移位操作的表示非常簡潔,直接用符号即可表示:
符号名稱 | 作用 |
---|---|
<< | 左移位操作 |
*>> | 右移位操作(此處*為顯示效果) |
*>>> | 無符号右移位 |
而在kotlin中,則沒有這些簡單的符号表示,取而代之的是相應的移位操作方法:
符号名稱 | 作用 |
---|---|
shl(bits) | 左移位 |
shr(bits) | 右移位 |
ushr(bits) | 無符号右移位 |
and(bits) | 與操作 |
or(bits) | 或操作 |
xor(bits) | 異或操作 |
inv() | 反向操作 |
3.2.3、運算符 + 的重載
先來看一段代碼:
val a = 10L + 1
很明顯,上述代碼中,+ 左右兩個數分别為Long類型與Int類型。
那麼問題來了,我們前面說過,kotlin中并不支援數字類型的隐式轉換,而且上面表達式中的數字1并沒有顯示拓寬為Long類型,為何卻準确無誤呢???
答案很簡答,那就是kotlin中對于符号“+”的重載。
看一看到,源碼中有很多重載的方法。
當我們執行:val a = 10L + 1
實質上是:
val a = 10L.plus(1)
值得注意的一點是:XX.plus()方法中傳入的形參隻能為數值類型!
4、kotlin中的字元類型
kotlin中的基本字元為Char類型,相關的知識點我們已經在前文讨論過。
5、kotlin中的布爾類型
布爾用 Boolean 類型表示,它有兩個值:true 和 false。
若需要可空引用布爾會被裝箱。
6、kotlin中的字元串類型
kotlin中字元串是String類型。
與java類似,kotlin中的String同樣是由final修飾的,即不可被繼承。我們一起來看一些新的特性。
6.1、支援多行字元串
val string = """
line 1
line 2
lin3 4
"""
注意以上代碼的列印結果是存在前置的空格号的:
我們可以借助與 trimMargin() 發放做到去除掉每行的前置空格。
val string = """
|line 1
|line 2
|lin3 4
""".trimMargin("|")
這裡有一點需要注意:trimMargin()方法需要傳入一個String類型的參數作為删除前置空格并進行每行分割的标志Flag,我們在這裡選用了”|”。
6.2、支援字元串模闆
在kotlin中,字元串可以包含字元串模闆用來表示前面用的到的一段代碼。kotlin中規定,所有的字元串模闆必須以美元符号”$”開頭。
val a = "temp"
val q = "$a.length():"
println(q+a.length)
列印結果為:
原生字元串和轉義字元串内部都支援模闆。
6.3、索引運算符s[i]
當我們需要對一個字元串的某一位取值時,java中會用到:
"abc".charAt(i);
而在kotlin中,我們可以簡單的用索引運算符即可:
val s = "abc"
s[0]//結果為a
6.4、for循環疊代字元串
for (s in "12345"){println(s)}
列印結果:
7、kotlin中的數組類型
7.1、生成數組
kotlin中的數組不是new出來的而是用了别的表示方法:
【1】fun_1
val a = arrayOf(1,2,3) //1,2,3
【2】fun_2 工廠函數
val b = Array(3, { i -> (i * 2) })//0,2,4
7.2、數組的多類型表示
kotlin中的數組支援多類型:
val arr = arrayOf(1,2,true,"abc")
for(c in arr){println(c)}
上述代碼的列印結果為:
注意:在這裡kotlin編譯器自動将數組更新為java.lang.Object類型了。
7.3、建立空數組
除此之外在建立空數組時,我們必須顯示地知名數組元素的類型:
val b = arrayOfNulls(10)//錯誤
val b = arrayOfNulls<Int>(10)//正确
7.4、數組轉換
注意:kotlin中數組不是形變的,即我們不能将Array指派給Array。