瘋狂kotlin講義連載之Kotlin的基礎類型--數值型之間的類型轉換

Kotlin是一門強類型的語言,Kotlin編譯器對類型檢查很是嚴格,這種嚴格保證了Kotlin程序的健壯,所以Kotlin不一樣類型的值常常須要進行相互轉換,數值型之間的變量和值也能夠相互轉換。html

整型之間的轉換

不一樣整型的變量能支持的表數範圍是不一樣的,好比Byte類型的變量或常量只能接受-128~127之間的整數,Short類型的變量或常量只能接受-32768~32767之間的整數。若是數值超出了變量或常量所支持的表數範圍,編譯器就會報錯。例如以下代碼:java

// Byte類型支持的表數範圍爲-32768~32767,因此下面代碼報錯編程

var negative: Short = 40000安全

// Byte類型支持的表數範圍爲-128~127,因此下面代碼報錯app

var big: Byte = 128dom

簡單來講,Kotlin與Java不一樣,Kot不支持取值範圍小的數據類型隱式轉換爲取值範圍大的類型。ide

因爲不一樣整型支持的表數範圍存在差別,所以進行類型轉換時必須注意選擇合適的類型。Kotlin爲全部數值類型都提供了以下方法進行轉換。post

  •  toByte():轉換爲Byte類型 。
  •  toShort():轉換爲Short類型。
  •  toInt():轉換爲Int類型。
  •  toLong():轉換爲Long類型。
  •  toFloat():轉換爲Float類型。
  •  toDouble():轉換爲Double類型。
  •  toChar():轉換爲Char類型。

Kotlin要求不一樣整型的變量或值之間必須進行顯式轉換。例如以下代碼。ui

程序清單:codes\02\2.6\IntConvert.kt編碼

fun main(args: Array<String>) {

var bookPrice : Byte = 79

var itemPrice : Short = 120

// bookPrice是Byte類型,但變量a是Short類型,所以下面代碼錯誤

// var a: Short = bookPrice

// 顯式將bookPrice強制轉換爲Int16類型

var a: Short = bookPrice.toShort() //

var b: Byte = itemPrice.toByte()

println("a: ${a}, b: ${b}")

val amount = 233

// 將Int型變量轉換爲Byte類型,發生溢出

val byteAmount: Byte = amount.toByte() //

println(byteAmount)

}

上面程序中第一行粗體字代碼試圖將bookPrice(Byte類型的變量)賦值給變量a,但因爲變量a是Short類型,雖然它們都是整型,但Kotlin依然不容許直接賦值,所以這行代碼沒法經過編譯。

程序中①號粗體字代碼先將bookPrice強制轉換爲Short類型,這樣便可將轉換後的結果賦值給Short類型的變量a了;接下來的代碼則調用itemPrice的toByte()方法將Short類型的變量轉換爲Byte類型。

與Java相似的是,把取值範圍大的變量或表達式強轉爲取值範圍小的類型時,可能發生溢出。例如上面程序中②號代碼所示。上面程序還把233強制類型轉換爲Byte型整數,從而變成了23,這就是典型的溢出。圖2.3示範了這個轉換過程。


圖2.3 int類型向byte類型強制類型轉換

從圖3.11能夠看出,32位Int類型的233在內存中如圖2.3上面所示,強制類型轉換爲8位的Byte類型,則須要截斷前面的24位,只保留右邊8位,最左邊的1是符號位,此處代表這是一個負數,負數在計算機裏是以補碼形式存在的,所以還須要換算成原碼。

將補碼減1獲得反碼形式,再將反碼取反就能夠獲得原碼。

最後的二進制原碼爲10010111,這個byte類型的值爲-(16 + 4 + 2 + 1),也就是-23。

從圖2.3很容易看出,當試圖強制把表數範圍大的類型轉換爲表數範圍小的類型時,必須格外當心,由於很是容易引發信息丟失。

雖然Kotlin缺少隱式轉換,但Kotlin在表達式中又可能夠自動轉換,這種轉換是基於上下文推斷出來,並且算術運算會有重載作適當轉換,例如以下代碼(程序清單同上)。

// 算術表達式中bookPrice、itemPrice會自動提高爲Int類型

var total = bookPrice + itemPrice //

println("total的值爲:${total}")

// 可看到total映射的Java類型爲int

println("total的類型爲:${total.javaClass}")

// 下面表達式中bookPrice強制轉換爲Logn類型,所以整個表達式類型爲Long

val tot = bookPrice.toLong() + itemPrice.toByte() //

println("total的值爲:${tot}")

// 可看到total映射的Java類型爲long

println("total的類型爲:${tot.javaClass}")

上面③號代碼將bookPrice(Byte類型)和itemPrice(Short類型)相加,Kotlin並不須要對它們進行強制轉換,Kotlin將會自動把它們提高到Int類型以後再進行計算(與Java表達式對全部整型的處理規則相同),所以整個表達式計算獲得的結果是Int類型。

上面④號代碼先將bookPrice的類型強轉換爲Long類型,這樣整個表達式中最高等級的操做數是Long類型,所以整個表達式計算獲得的結果也是Long類型。

提示:上面程序中使用了變量的javaClass屬性,該屬性來自Any類型(Any類型是Kotlin全部類型的根父類),javaClass屬性用於獲取指定變量對應的Java類型(大體至關於Java反射中的getClass()方法)。

Kotlin雖然不容許直接將Char當成整數值使用,也不容許將整數值直接當成Char使用,但Kotlin依然可調用數值型的toChar()方法將數值型變量或表達式轉換爲Char類型。例以下面程序示範瞭如何生成一個6位的隨機字符串,這個程序中用到了後面的循環控制,不理解循環的讀者能夠參考後面章節的介紹。

程序清單:codes\02\2.6\RandomStr.kt

fun main(args: Array<String>) {

// 定義一個空字符串

var result = "";

// 進行6次循環

for(i in 0..5) {

// 生成一個97~122之間的Int類型整數

val intVal = (Math.random() * 26 + 97).toInt();

// 將intValue強制轉換爲Char類型後鏈接到result後面

result = result + intVal.toChar();

}

// 輸出隨機字符串

println(result);

}

此外,Char型雖然不能被當成整數進行算術運算,但Kotlin爲Char類型提供了加、減運算支持,其計算規則以下:

q Char型的值加、減一個整型值:Kotlin會先將該Char值對應的字符編碼進行加、減該整數,而後將計算結果轉換爲Char值。

q 兩個Char值進行相減:Kotlin將用兩個Char值對應的字符編碼進行減法運算,最後返回Int類型的值。兩個Char型的值不能相加。

例如以下程序。

程序清單:codes\02\2.6\CharAdd.kt

fun main(args: Array<String>) {

var c1 = 'i'

var c2 = 'k'

println(c1 + 4); // 輸出m

println(c1 - 4); // 輸出e

println((c1 - c2)); // 輸出-2

}

浮點型與整型之間的轉換

Kotlin的Float、Double之間須要進行顯式轉換,浮點型與整型之間也須要進行顯式轉換—這些轉換過程與前面介紹的整型之間的轉換過程基本類似。例如以下程序。

程序清單:codes\02\2.6\FloatConvert.kt

fun main(args: Array<String>) {

var width: Float =

2.3f

var height: Double = 4.5

// width必須顯式強制轉換爲Double以後,才能賦值給變量a

var a: Double = width.toDouble()

println("a的值爲: ${a}")

// 將height強制轉換爲Float以後再進行計算,整個表達式的類型都是Float類型

// 所以area1的類型也被推斷爲Float類型

var area1 = width * height.toFloat()

// 表達式中height是Double類型,它是等級最高的運算數

// 所以整個表達式的類型都是Double類型,area2的類型也被推斷爲Double類型

var area2 = width * height

val multi: Int = 5

// 所以totalHeight1的類型也被推斷爲Double類型

var totalHeight1 = height * multi //

// 將height強制轉換爲Int後進行計算,整個表達式的類型都是Int類型

// 所以totalHeight2的類型也被推斷爲Int類型

var totalHeight2 = height.toInt() * multi //

}

上面程序中第一行粗體字代碼但願將Float類型的width變量賦值給Double類型的變量a,所以程序必須先進行類型轉換。接下來程序試圖將width和height相乘的積賦給area一、area2,若是咱們但願area1變量的類型是Float,這就須要將height強轉爲Float類型,這樣整個表達式中width、height都是Float類型,整個表達式的計算結果也是Float類型。area2則將被推斷爲Double類型。

上面程序中①號粗體字代碼計算multi、height的乘積,因爲height的類型是Double類型,所以整個表達式的類型是double類型,所以totalHeight1的類型也是Double類型。

程序中②號粗體字代碼先將height強制轉換爲Int類型,而後與multi(也是Int類型)變量相乘,這樣代碼也是正確的。

將Double類型或Float類型的值、變量或常量強制轉換爲整型時,浮點值的小數部分會被截斷,例如4.75將會變成四、-2.9將會被截斷爲-2。對於②號粗體字代碼而言,height被強制轉換爲Int類型,此時小數部分將會截斷,所以height將會被截斷爲4,所以計算獲得的totalHeight2的值爲20。

經過上面的介紹不難發現,當進行類型轉換時,應該儘可能向表數範圍大的數據類型轉換,這樣程序會更加安全,好比前面介紹的Byte向Short轉換、Int向Double轉換,而反過來轉換則可能致使溢出。Kotlin語言各類數值型的表數範圍由小到大的順序爲:Byte→Short→Int→Long→Float→Double。

表達式類型的自動提高

當一個算術表達式中包含多個數值型的值時,整個算術表達式的數據類型將發生自動提高。Kotlin定義了與Java基本類似的自動提高規則。

  •  全部的Byte類型、Short類型將被提高到Int類型。
  •  整個算術表達式的數據類型自動提高到與表達式中最高等級操做數一樣的類型。操做數的等級排列如圖3.10所示,位於箭頭右邊類型的等級高於位於箭頭左邊類型的等級。

下面程序示範了一個典型的錯誤。

程序清單:codes\02\2.6\AutoPromote.kt

// 定義一個Short類型變量

var sValue: Short = 5

// 表達式中的sValue將自動提高到Int類型,則右邊的表達式類型爲Int

// 將一個Int類型值賦給Short類型變量將發生錯誤

sValue = sValue - 2

上面的「sValue–2」表達式的類型將被提高到Int類型,這樣就把右邊的Int類型值賦給左邊的Short類型變量,從而引發錯誤。

下面代碼是表達式類型自動提高的正確示例代碼(程序清單同上)。

var b: Byte = 40

var c: Short = 97

var i: Int = 23

var d: Double = .314

// 右邊表達式中最高等級操做數爲d(Double類型)

// 則右邊表達式的類型爲Double類型,result將會推斷爲Double類型

val result = b + c + i * d

// 將輸出144.222

println(result)

必須指出,表達式的類型將嚴格保持和表達式中最高等級操做數相同的類型。下面代碼中兩個Int類型整數進行除法運算,即便沒法除盡,也將獲得一個int類型結果(程序清單同上)。

var iVal: Int = 3

// 右邊表達式中兩個操做數都是Int類型,故右邊表達式的類型爲Int

// 雖然23/3不能除盡,但依然獲得一個Int類型整數

val intResult = 23 / iVal;

println(intResult) // 將輸出7

從上面程序中能夠看出,當兩個整數進行除法運算時,若是不能整除,獲得的結果將是把小數部分截斷取整後的整數。

若是表達式中包含了字符串,則又是另外一番情形了。由於當把加號(+)放在字符串和數值之間時,這個加號是一個字符串鏈接運算符,而不是進行加法運算。看以下代碼:

// 輸出字符串Hello!a7

println("Hello!" + 'a' + 7)

// 輸出字符串hHello!

println('a' + 7 + "Hello!"))

對於第一個表達式「"Hello!" + 'a' +

7」
,先進行「"Hello!" + 'a'」運算,把'a'轉換成字符串,拼接成字符串Hello!a,接着進行「"Hello!a" +
7」
運算,這也是一個字符串鏈接運算,獲得結果是Hello!a7。對於第二個表達式,先進行「'a' +
7」
加法運算,此時是對Char型值作加法運算,此時將會獲得'a'後面第7個字符(字符編碼加7),所以此時會獲得'h',「'h' + "Hello!"」運算,'h'會自動轉換成字符串,將變成兩個字符串的鏈接運算,從而獲得hHello!。

以上內容節選自《瘋狂Kotlin講義》:一本讓您最直接認識Kotlin的瘋狂講義


本書即將於2017年11月發售 敬請期待
往期連載
第一期: 第一期:juejin.im/post/59c0b7…

第二期:juejin.im/post/59c1d6…

第三期:juejin.im/post/59e407…

第四期:juejin.im/post/59ed77…

第五期:juejin.im/post/59eec3…

第六期:juejin.im/post/59effb…

第七期:juejin.im/post/59f153…

第八期:juejin.im/post/59f283…

第九期:juejin.im/post/59f686…

相關書籍《瘋狂Android講義》https://item.jd.com/11689014.html
相關文章
相關標籤/搜索