作者簡介:CSDN博客專家、華為云享專家認證
系列專欄:Kotlin 初學者
學習交流:三人行必有我師焉;擇其善者而從之,其不善者而改之,
目錄
一、空安全
1.1 空指標
1.2 可空性(?)
1.3 安全呼叫運算子(?.)
1.4 let運算子
1.5 使用非空斷言運算子(!!.)
1.6 使用空合并運算子(?:)
1.7 使用型別轉換運算子(as)
1.7.1 不安全的轉換運算子:as
1.7.8 安全轉換運算子:as?
二、例外
2.1 概念
2.2 try...catch塊
2.2.1 使用catch塊的try語法
2.2.2 使用finally塊的try語法
2.2.3 try catch語法與finally塊
2.3 finally塊
2.4 throw關鍵字
2.5 先決條件
一、空安全
1.1 空指標
在Java中,定義一個變數可以默認不賦值,因為Java的系統會給我們默認賦一個默認值,并且Java可定義一個賦值為null的變數,這樣在使用這個變數的時候都會去顯示判斷該變數是否為null,這使得在Java中我們司空見慣的空指標例外NullPointerException,帶給了我們很多麻煩,
Kotlin 的型別系統旨在從我們的代碼中消除 NullPointerException,
NPE 的唯一可能的原因可能是:
-
顯式呼叫 throw NullPointerException()
-
使用了下文描述的 !! 運算子
-
外部 Java 代碼導致的
-
對于初始化,有一些資料不一致(如一個未初始化的 this 用于建構式的某個地方)
除非另有規定,變數不可為null值,這樣一來,運行時崩潰從根源上得到解決,如下圖,報錯:變數"name"必須初始化:

1.2 可空性(?)
Kotlin區分可空型別和非可空型別,所以,你要一個可空型別變數運行,而它又可能不存在,對于這種潛在危險,編譯器時刻警惕著,為了應對這種風險,Kotlin不允許你在可空型別值上呼叫函式,除非你主動接手安全管理,如下圖:

那么完美如何使得變數變為可空型別,
定義一個可空型別的變數的格式為:修飾符 變數名 :型別? = 值
fun main() {
//可空性
//資料型別后面加"?",表示可為該資料型別或者為null
var age :Int? = 15
age = null//未報錯
}

1.3 安全呼叫運算子(?.)
-
可空型別變數?.屬性/函式,如果可空型別變數為null時,回傳null
-
能有效避免空參考例外(NullPointException),因為只要鏈式其中的一個為null,則整個運算式都為null
當使用可用型別呼叫函式呼叫函式時必須使用安全呼叫運算子(?.),否則編譯都不通過,

//安全呼叫運算子
println(age?.plus(20))//null
函式中使用可空型別
當一個函式有回傳值時,如果函式中的代碼使用 ?. 去回傳一個值,那么函式的回傳值的型別后面也要加上?符號,
//回傳值Int為可空
fun userInfo() : Int? {
//name 為可空的String型別屬性
var name:String?="Java"
name=null
//使用安全呼叫運算子(?.)
return name?.length
}
1.4 let運算子
let的用法:變數?.let{ … }
let運算子的作用:當時用符號?.驗證的時候忽略掉null
安全呼叫允許在可空型別上呼叫函式,但是如果還想做點額外的事,比如創建新值,或判斷不為null就呼叫其他函式,怎么辦?可以使用帶let函式的安全呼叫運算子,你可以在任何型別上呼叫let函式,它的主要作用是讓你在指定的作用域內定義一個或多個變數,
//let
var type: String? = "java"
type = type?.let {
if (it.isNotBlank()) {
"$it,非空白字串"
}else{
"Kotlin"
}
}
println(type)
type = ""//空字符
type = type?.let {
if (it.isNotBlank()) {
"$it,非空白字串"
}else{
"Kotlin"
}
}
println(type)

1.5 使用非空斷言運算子(!!.)
!!.又稱感嘆號運算子,當變數值為null時,會拋出NullPointerException,
//非空斷言運算子
type = null
println(type!!.toString())

1.6 使用空合并運算子(?:)
?:運算子的意思是,如果左邊的求值結果為null,就使用右邊的結果值,
type = null
// println(type!!.toString())//空指標例外
println("------------")
//空合并運算子(?:)
//當type為空是,運行列印"Kotlin"
println(type ?: "Kotlin")
type = "Java"
//當type 為"Java"是,運行列印"Java"
println(type ?: "Kotlin")

使用?:+let代替if/else
println("---?:+let----")
type = ""
type = type?.let { "Kotlin" }?:"Java"
println(type)
type = null
type = type?.let { "Kotlin" }?:"Java"
println(type)

1.7 使用型別轉換運算子(as)
1.7.1 不安全的轉換運算子:as
有時無法轉換變數并拋出例外,這稱為不安全轉換,不安全的強制轉換由中綴運算子執行,
可以為空的字串(String?)不能轉換為非null Int型別,這會引發例外,
var asTest :String? = ""
//不安全的轉換運算子
println(asTest as Int)

Exception in thread "main" java.lang.ClassCastException:
Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap')
at com.scc.kotlin.primary.NullKt.main(Null.kt:64)
at com.scc.kotlin.primary.NullKt.main(Null.kt)
1.7.8 安全轉換運算子:as?
as?安全地轉換成一種型別, 如果無法進行轉換,則回傳null,而不是拋出ClassCastException例外,
咱就在上面的實體基礎上修改,
var asTest :String? = ""
//不安全的轉換運算子 as
// println(asTest as Int)//ClassCastException
//安全的轉換運算子 as?
println(asTest as? Int)//null

二、例外
2.1 概念
例外是程式中發生的運行時問題,導致程式終止,這可能是由于記憶體空間不足,陣列越界,條件除以零而發生的,要在程式執行期間處理這種型別的問題,可使用例外處理技術, 例外處理是一種處理運行時問題并維護程式執行流程的技術, 在Kotlin中,所有例外類都是Throwable類的子類, 要拋出例外物件,Kotlin使用throw運算式,
例外處理中使用了四種不同的關鍵字,它們是:
-
try:try塊包含可能生成例外的陳述句集,必須后跟catch 或 finally或兩者,
-
catch:catch塊用于捕獲try塊拋出的例外,
-
finally:finally塊始終執行是否處理例外,所以它用于執行重要的代碼陳述句,
-
throw:throw關鍵字用于顯式拋出例外,
Kotlin的例外處理和Java類似,
未經檢查的例外
未經檢查的例外是由于代碼中的錯誤而引發的例外,此例外型別擴展了RuntimeException類,在運行時檢查未經檢查的例外, 以下是未經檢查的例外的一些示例:
-
ArithmeticException :當將數字除以零時拋出,
-
ArrayIndexOutOfBoundExceptions:嘗試使用不正確的索引值訪問陣列時拋出,
-
SecurityException:由安全管理器拋出以指示安全性違規,
-
NullPointerException:在null物件上呼叫方法或屬性時拋出,
注意:Kotlin不支持已檢查例外,
2.2 try...catch塊
try-catch塊用于代碼中的例外處理, try塊包含可能拋出例外的代碼,catch塊用于處理例外,必須在方法中寫入此塊,try塊必須跟隨catch塊或finally塊或兩者,
2.2.1 使用catch塊的try語法
fun main() {
var name: String? = null
try {
name!!.plus("is good")//報錯:NullPointerException
} catch (e: NullPointerException) {
println(e.message)
}
}
2.2.2 使用finally塊的try語法
var name: String? = null
try {
name!!.plus("is good")//報錯:NullPointerException
} finally {
println("都結束了")
}
2.2.3 try catch語法與finally塊
var name: String? = null
try {
name!!.plus("is good")//報錯:NullPointerException
} catch (e: NullPointerException) {
println(e.message)
} finally {
println("都結束了")
}
2.3 finally塊
finally是這樣的塊:無論是否處理例外,它總是執行,所以它用于執行重要的代碼陳述句,如下:

如上面代碼,已產生例外,但是finally塊中的代碼還是執行了,
注意:如果程式退出(通過呼叫exitProcess(Int)或導致行程中止的任何錯誤),將不執行finally塊,
2.4 throw關鍵字
throw關鍵字用于拋出顯式例外,它用于拋出自定義例外,要拋出例外物件,將使用throw-expression,
fun main() {
try {
//第三步:使用
checkData(name)
name!!.plus("is good")//報錯:NullPointerException
} catch (e: Exception) {
println(e.message)
}
}
//第二步:傳入可空String
fun checkData(str:String?){
//當str為空時,執行ScException()
str?:throw ScException()
}
//第一步:自定義例外
class ScException():IllegalArgumentException("帥次牌例外")

2.5 先決條件
Kotlin中提供一些遍歷的內置函式,使用這些函式可以自定義資訊的例外,這些函式就是先決條件函式,可以用該種函式自定義先決條件,當滿足條件時代碼才會執行,
| 函式 | 描述 |
|---|---|
| checkNotNull | 如果引數為null,則拋出IllegalArgumentException例外,否則回傳非空值 |
| require | 如果引數為false,則拋出IllegalArgumentException例外 |
| requireNotNull | 如果引數為null,則拋出IllegalArgumentException例外,否則回傳非空值 |
| error | 如果引數為null,則拋出IllegalArgumentException例外并輸出錯誤資訊,否則回傳非空值 |
| assert | 如果引數為false,則拋出AssertError例外,并打上斷言編譯器標記 |
try {
//第三步:使用
checkData(name)
name!!.plus("is good")//報錯:NullPointerException
} catch (e: Exception) {
println(e.message)
}
}
//第二步:傳入可空String
fun checkData(str:String?){
//當str為空時,執行lambda運算式
checkNotNull(str,{"帥次牌先決條件例外"})
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/389206.html
標籤:其他
