目錄
1、對null的約定
2、Java中對null值處理
3、Kotlin中 null安全的實作
4、Kotlin的null異常報錯
1、對null的約定
kotlin對變量的null進行了區分
var name: String = "Zhang San" //為不可null的變量
var name1: String? = null //為可null的變量
var name2: String = null //報錯
相同資料類型的可null和不可null的兩個變量是兩種完全不同的類型的變量
- 1、它們之間不能直接互相指派
- 2、不可null和可null的兩種類型之間的轉換類似于int和float (可null是不可null的進階類型)
private fun testNull(){
name=name1 //1、報錯,不可null的變量不能直接轉換為可null
name=name1!! //2、可以加兩個感歎号進行類型強轉
name1=name //3、不可null可的變量可以隐式轉換為可null
}
2、Java中對null值處理
java中對null的處理是給了我們兩個注解:@NotNull 被注解的變量不能指派為null,當指派為null的時候會給出黃色的警告 @Nullable 被注解的變量可以
注意:這些注解隻會在我們書寫代碼的時候,給我們一個黃色警告,來讓我們避免的錯誤的指派為null,但是當我們不小心傳了一個null的時候他們在運作的時候是會報錯的,但是在Kotlin,你如果聲明該類型為可null,則不會報錯。
左邊是我們的源碼,右邊是編譯後的class檔案,明顯看出,這兩個注解隻是警告作用,并沒有實際的判null操作。
我們看到上面代碼中,我們對變量name2和printNam()函數的參數都用@NotNull 進行了注解,在我們給它們指派為null的時候,會給我們一個黃色的警告,并且會給我們說明。但是我們強行運作這段代碼的時候,它是會直接報錯的。
而用了@Nullable 注解的pringName1()函數的參數時,它會警告我們讓我們對str進行if null值的判斷。
3、Kotlin中 null安全的實作
null安全的實作其實就是對你聲明的變量進行兩步null判斷處理,下面有源碼解釋:
第一步:給你變量加上@Nullable @NotNull 注解,讓你的在書寫代碼的時候就減少指派null的錯誤情況
第二步:在編譯代碼之後會自動給你的的變量進行null值判斷。
下面左邊是我們的源碼,右邊是編譯成class檔案之後我們反編譯得到的源碼,如果想看反編譯kotlin檔案,可以看這裡:Kotlin-20-如何檢視Kotlin編譯成class後的代碼。
從反編譯的源碼中我們看到,當我們聲明一個可null的變量 name1時,它不僅會給我們添加上@Nullable的注解,讓我們在書寫代碼的時候就盡量避免指派錯誤,更重要的時候,綠色框中,在編譯後,它會自動幫我們添加對參數可null的判斷,這樣在運作的時候就不會再報錯。
而當我們中聲明一個變量為不可null的時候,因為我們在聲明指派階段,就不會造成null的情況,是以運作代碼的時候,一般是不會報錯的,除非有一種情況會報錯--->看第4節
輸出結果:
0
null
4、Kotlin的null異常報錯
上面我們講了 可null的參數,編譯之後會自動添加判null操作,而不可null的參數,又在聲明的時候無法指派為null,那怎麼樣才會出現null異常呢?
當調用Java中的null對象輸出的時候會報錯。
//java中的代碼
public class TestNull {
String name="";
@Nullable
String name1=null;
@NotNull
String name2=null;
}
//Kotlin中的代碼
fun printName(str: String) {
println(str.length)
}
fun printName1(str: String?) {
println(str?.length)
}
fun main() {
val test= TestNull()
printName1(test.name2)
printName(test.name2)
// printName(test.name1) ---報錯 因為name1是可null類型,無法指派到不可null類型上。
}
輸出結果:
從輸出結果看出pringName1 對null做了處理,是以不會報錯,但是Kotlin中對不可null類型隻是進行了抛出異常的處理,并沒有做其他處理,是以這樣在調用Java的null值時還是會報錯。