在咱們熟知的Java
中,定義一個變量能夠默認不賦值,由於Java
的系統會給咱們默認賦一個默認值,而且Java
可定義一個賦值爲null
的變量,這樣在使用這個變量的時候都會去顯示判斷該變量是否爲null
。從代碼的簡潔性以及代碼的閱讀性來講,就差了Koltin
一籌了,那麼Kotlin
定義一個變量可爲null
的變量怎麼定義呢?下面針對Kotlin
的這些特性,做出一個詳細的講解。html
在前面的變量、常量中咱們已經講解到了變量的定義。這裏不做詳述。若你有興趣,請參見Kotlin——初級篇(二):變量、常量、註釋git
定義一個可空類型的變量的格式爲:
修飾符 變量名 : 類型? = 值
github
這裏爲了演示,定義變量和定義可空變量的區別,會提到定義變量的代碼。數組
例:安全
// 定義一個不可爲空的變量,用var修飾的變量能夠被從新賦值,用val修飾的變量則不能,可是不能賦值爲null var a : Int = 12 val b : Int = 13 a = 20 // a = null 不能複製爲null // b = 20 不能被從新賦值 if(a == null){ // 這樣的判斷毫無心義,由於變量a永遠不可能null } /* 定義可空類型的變量,即變量能夠被賦值爲null 定義格式爲:修飾符 變量名 : 類型? = 值 */ var nullA : Int? = 12 val nullB : Int? = 13 nullA = null if(nullA == null){ println("nullA = $nullA") }
能夠看出:變量 nullA 的值爲 null
yii
分析:要定義一個可空類型的變量時,即在定義變量的類型後面加上?
符號就好了。在使用的時候,記住要判斷該段該變量是否爲空,這個操做在Java
中常常會用到...,若是定義一個不可爲空類型的變量時,則判斷將毫無心義,由於這個變量永遠不會爲空。ide
在上面咱們提到,可空類型須要判斷在使用,這裏介紹除了
if ... else...
以外的其餘方式函數
1.2.一、if...else...判斷post
例:ui
var str : String? = "123456" str = null if (str == null){ println("變量str爲空") }else{ println("str.length => ${str.length}") }
輸出結果爲:
變量str爲空
1.2.二、使用符號?.
判斷
- 該符號的用法爲:
可空類型變量?.屬性/方法
。若是可空類型變量爲null時,返回null- 這種用法大量用於鏈式操做的用法中,能有效避免
空引用異常(NullPointException)
,由於只要鏈式其中的一個爲null
,則整個表達式都爲null
例:
var str : String? = "123456" str = null println(str?.length) // 當變量str爲null時,會返回空(null)
輸出結果爲:
null
1.2.三、鏈式調用
?.
這種符號去判斷是否爲null
,在Kotlin
中使用的地方是不少,特別是對於鏈式調用來講體驗性更好。
例:這裏簡單寫一個建造者模式,來模擬?.
在鏈式調用中的用法
class Test{ class Builder{ private var name : String? = "Tom" private var age : Int? = 0 private var sex : String? = "男" fun setName(name : String) : Builder?{ this.name = name return this } fun setAge(age : Int) : Builder?{ this.age = age return this } fun setSex(sex: String?) : Builder?{ this.sex = sex return this } override fun toString(): String { return "Builder(name=$name, age=$age, sex=$sex)" } } } fun main(args: Array<String>) { val builder : Test.Builder? = Test.Builder().setName("Lily")?.setSex("nv")?.setAge(10) println(builder.toString()) }
輸出結果爲:
Builder(name=Lily, age=10, sex=女)
若是你上面的代碼看不懂能夠看下的代碼,你能夠看下面的例子:頂一個可空類型的字符串的長度加5再減去10
val testStr : String? = null val result = testStr?.length?.plus(5)?.minus(10) println(result)
能夠看出輸出結果爲: null
1.2.四、函數中使用可空類型的狀況下
當一個函數/方法有返回值時,若是方法中的代碼使用
?.
去返回一個值,那麼方法的返回值的類型後面也要加上?
符號
例:
fun funNullMethod() : Int? { val str : String? = "123456" return str?.length }
輸出結果爲:
6
1.2.五、let操做符
let
操做符的做用:當時用符號?.
驗證的時候忽略掉null
let
的用法:變量?.let{ ... }
例:排除掉數組中的空元素
val arrTest : Array<Int?> = arrayOf(1,2,null,3,null,5,6,null) // 傳統寫法 for (index in arrTest) { if (index == null){ continue } println("index => $index") } // let寫法 for (index in arrTest) { index?.let { println("index => $it") } }
輸出結果爲:
index => 1 index => 2 index => 3 index => 5 index => 6
注意:上面的兩種寫法的效果是相同的,能夠看出使用let{}高階函數減小了好幾行代碼
Evils
其實不是一個操做符,而是evil
的複數,而evil
的意思在這裏能夠理解爲屏蔽、安全的
操做符,這樣的操做符有三種:
?:
這個操做符表示在判斷一個可空類型時,會返回一個咱們本身設定好的默認值.!!
這個操做符表示在判斷一個可空類型時,會顯示的拋出空引用異常(NullPointException)
.as?
這個操做符表示爲安全的類型轉換.
當咱們定義了一個可空類型的變量時,若是該變量不爲空,則使用,反之使用另一個不爲空的值
例:
val testStr : String? = null var length = 0 // 例: 當testStr不爲空時,輸出其長度,反之輸出-1 // 傳統寫法 length = if (testStr != null) testStr.length else -1 // ?: 寫法 length = testStr?.length ?: -1 println(length)
輸出結果爲:
-1
分析:此操做符通常和?.
操做符連用。當且僅當?:
左邊的表達式爲null
時,纔會執行?:
右邊的表達式。
!!
操做符可謂是給愛好空引用異常(NullPointException)
的開發者使用,由於在使用一個可空類型變量時,在該變量後面加上!!
操做符,會顯示的拋出NullPointException
異常
例:
val testStr : String? = null println(testStr!!.length)
輸出結果爲:
能夠看出,在未作空判斷的狀況下直接使用操做符!!
的狀況下,拋出了空異常
其實這裏是指
as
操做符,表示類型轉換,若是不能正常轉換的狀況下使用as?
操做符。當使用as
操做符的使用不能正常的轉換的狀況下會拋出類型轉換(ClassCastException)異常
,而使用as?
操做符則會返回null
,可是不會拋出異常
2.3.一、使用as
例:
// 會拋出ClassCastException異常 val num1 : Int? = "Koltin" as Int println("nun1 = $num1")
輸出結果爲:
2.3.二、使用as?
例:
val num2 : Int? = "Koltin" as? Int println("nun2 = $num2)
輸出結果爲:
num2 = null
這一章在實際的項目開發當中用到的地方是不少的,若是用好了各類空安全的操做符,估計你的項目中就不會拋出以及
異常了,在這裏我作了一個總結,但願會對各位有所幫助:
項目中會拋出空引用(NullPointerException)
異常的狀況
- 在可空類型變量的使用時,用了
!!
操做符- 顯式拋出空引用異常
throw NullPointerException()
- 外部 Java 代碼致使的
- 對於初始化,有一些數據不一致(如一個未初始化的 this 用於構造函數的某個地方)
項目中會拋出類型轉換(ClassCastException)
異常的狀況
- 在類型轉換中使用了
as
操做符- 使用了
toXXX()
方法不能轉換的狀況下- 外部 Java 代碼致使的
儘可能避免使用的操做符
- 儘量的不要使用
!!
操做符,多使用?:
、?.
操做符,以及let{}
函數- 儘量的使用
as?
操做符去替換掉as
,在不肯定是否能夠安全轉換的狀況下不使用toXXX()
方法
若是各位大佬看了以後感受還闊以,就請各位大佬隨便star
一下,您的關注是我最大的動力。
個人我的博客:Jetictors
個人github:Jetictors
個人掘金:Jetictors