目錄介紹
- 01.可空性
- 02.安全調用運算符:?.
- 03.Elvis運算符:?:
- 04.安全轉換運算符:as?
- 05.非空斷言:!!
- 06.let函數說明
- 07.可空類型的擴展
- 08.Java中判斷方式
- 09.kotlin是否解決NPE
- 10.kotlin如何約束非空判斷
- 11.導致NPE的場景
想換個工作,渴望同行內推我
-
個人信息
- 姓名:楊充【26歲】
- 郵箱:[email protected]
- 微信:13667225184
- GitHub:https://github.com/yangchong211
- 博客彙總:https://github.com/yangchong211/YCBlogs
- 幹活集中營:Android端技術博客和開源項目審覈員
- 目前工作情況:在職狀態
- 技術項目和博客:GitHub項目7k以上star,follower1.1k以上,發表博客100多篇。
- 熱愛技術:開源項目和博客多次被鴻洋,郭霖,Android技術週刊,幹活集中營等等推薦。
- 學歷:武漢軟件工程職業學院,大專學歷
- 工作年限:3年多
- 工作地點:北京
-
關於近期投遞簡歷一點感想
- 從進入Android這個行業以來,前兩次幾乎都是朋友內推,面試機會相對容易,都是一個App一個人做或者兩個人做,用戶相對來說並不多。這次想着離職,主要是想進入一個較大的平臺,大概可以理解爲Android端有個至少四五人,可以進行技術交流,渴望自己能夠在技術上突破,這就像自己平時獨自跑步,和跟着一羣跑馬拉松的人跑步,那種緊張感肯定是不一樣的。
- 近段時間,嘗試着向一些較大的公司投遞簡歷,大概在拉鉤上投了15個左右(不喜歡海投),發現絕大多數簡歷到不了技術那裏,就被人事說學歷不夠,經驗不夠,工作不匹配等情況回絕。不過也可以理解,看簡歷無非就是學歷和經驗,貌似自己的履歷是差了一點。
- 這大概是第一次在網上發一個主動希望同行內推的介紹,如果你的公司有Android方面的招聘,能否內推一下我這個小人物,感謝。
01.可空性
-
在 Kotlin 中,類型系統區分一個引用是可以容納 null (可空引用)還是不能容納(非空引
用)。 例如,String 類型的常規變量不能指向 nullvar name: String = "yc" //編譯錯誤 //name = null
-
如果希望一個變量可以儲存 null 引用,需要顯式地在類型名稱後面加上問好來標記它:
var name: String? = "yc" name = null
- 問號可以加在任何類型的後面來表示這個類型的變量可以存儲 null 引用:Int?、Doubld? 、Long? 等
-
Kotlin 對可空類型的顯式支持有助於防止 NullPointerException 導致的異常問題,編譯器不允許不對可空變量做 null 檢查就直接調用其屬性
fun check(name: String?): Boolean { //編譯器不允許不對 name 做 null 檢查就直接調用其屬性 return name.isNotEmpty() }
-
需要顯式地進行 null 檢查
fun check(name: String?): Boolean { if (name != null) { return name.isNotEmpty() } return false }
02.安全調用運算符:?.
-
安全調用運算符:?.
- 允許把一次 null 檢查和一次方法調用合併爲一個操作,如果變量值非空,則方法或屬性會被調用,否則直接返回 null
-
例如,以下兩種寫法是完全等同的:
fun check(name: String?) { if (name != null) { println(name.toUpperCase()) } else { println(null) } } fun check(name: String?) { println(name?.toUpperCase()) }
03.Elvis運算符:?:
-
Elvis 運算符:?:
- 用於替代 ?. 直接返回默認值 null 的情況,Elvis 運算符接收兩個運算數,如果第一個運算數不爲 null ,運算結果就是其運算結果值,如果第一個運算數爲 null ,運算結果就是第二個運算數
-
例如,以下兩種寫法是完全等同的:
fun check(name: String?) { if (name != null) { println(name) } else { println("yc") } } fun check(name: String?) { println(name ?: "yc") }
04.安全轉換運算符:as?
-
安全轉換運算符:as? 用於把值轉換爲指定的類型,如果值不適合該類型則返回 null
fun check(any: Any?) { val result = any as? String println(result ?: println("is not String")) }
05.非空斷言:!!
-
非空斷言用於把任何值轉換爲非空類型,如果對 null 值做非空斷言,則會拋出異常
fun main(args: Array<String>) { var name: String? = "yc" check(name) //7 name = null check(name) //KotlinNullPointerException } fun check(name: String?) { println(name!!.length) }
06.let函數說明
-
let 函數可用於在表達式不爲 null 時才執行指定代碼塊
fun main(args: Array<String>) { var name: String? = "yc" check(name) //yc name = null check(name) //什麼都不會輸出 } fun check(name: String?) { name?.let { println(name) } }
07.可空類型的擴展
-
爲可空類型定義擴展函數是一種更強大的處理 null 值的方式,可以允許接收者爲 null 的調用,並在該函數中處理 null ,而不是在確保變量不爲 null 之後再調用它的方法
- 例如,如下方法可以被正常調用而不會發生空指針異常
val name: String? = null println(name.isNullOrEmpty()) //true
- isNullOrEmpty() 的方法簽名如下所示,可以看到這是爲可空類型 CharSequence? 定義的擴展函數,方法中已經處理了方法調用者爲 null 的情況
@kotlin.internal.InlineOnly public inline fun CharSequence?.isNullOrEmpty(): Boolean { contract { returns(false) implies (this@isNullOrEmpty != null) } return this == null || this.length == 0 }
08.Java中判斷方式
8.1 防禦式編程
-
“防禦式編程”大家應該不陌生,核心思想是不信任任何“外部”輸入。
- 不管是真實的用戶輸入還是其他模塊傳入的實參,具體點就是各種判空。創建一個方法需要判空,創建一個邏輯塊需要判空,甚至自己的代碼內部也需要判空(防止對象的回收之類的)。
public void showToast(Activity activity) { if (activity == null) { return; } }
8.2 契約式編程
-
各個模塊之間約定好一種規則,大家按照規則來辦事,出了問題找沒有遵守規則的人負責,這樣可以避免大量的判空邏輯。Android 提供了相關的註解以及最基礎的檢查來協助開發者,示例如下:博客
public void showToast(@NonNull Activity activity) { ...... }
- 給 Activity 增加了 @NonNull 的註解,就是向所有調用這個方法的人聲明瞭一個約定,調用方應該保證傳入的 activity 非空。當然聰明的你應該知道,這是一個很弱的限制,調用方沒注意或者不理會這個註解的話,程序就依然還有 NPE 導致的 crash 的風險。
09.kotlin是否解決NPE
- 有些文章說 Kotlin 幫開發者解決了NPE(NullPointerException),這個說法是不對的。Kotlin沒有幫開發者解決了NPE,而是通過在語言層面增加各種強規則,強制開發者去自己處理可能的空指針問題,達到儘量減少(只能減少而無法完全避免)出現 NPE 的目的。
10.kotlin如何約束非空判斷
-
聲明階段
- 變量需要決定自己是否可爲空,比如 private var goodsId: String ?= null,這樣就是可接受 null
-
傳遞階段
- 在變量傳遞階段,必須保持“可空性”一致,比如形參聲明是不爲空的,那麼實參必須本身是非空或者轉爲非空才能正常傳遞。示例如下:
private var goodsId: String? = null private fun Main(){ getName(goodsId!!) } private fun getName(name : String){ Log.i("", "---$name") }
- 還有一種方式,在方法中添加?
private fun Main(){ getName(goodsId) } private fun getName(name : String?){ Log.i("", "---$name") }
-
使用階段
- 在使用階段,需要嚴格判空
var time: Long? = 1000 private fun Main(){ time!!.toFloat() time?.toInt() }
-
得出結論
- 總的來說 Kotlin 爲了解決 NPE 做了大量語言層級的強限制,的確可以做到減少 NPE 的發生。但這種既“契約式”(判空)又“防禦式”(聲明空與非空)的方案會讓開發者做更多的工作,會更“麻煩”一點。
11.導致NPE的場景
11.1 方法參數聲明非空
-
比如,請求網絡接口,需要傳遞參數,這種情況下每個字段都可能爲空,爲了增強邏輯,可以在方法參數上加上"?",可以避免後端處理參數值時拋出空指針異常。博客
/** * 用戶登陸 */ @POST("user/login") fun userLogin( @Query("username") userName: String?, @Query("password") password: String? ): Observable<ResponseBean<LoginBean>>
11.2 !! 強行轉爲非空
-
當將可空類型賦值給非空類型時,需要有對空類型的判斷,確保非空才能賦值(Kotlin 的約束)。使用!! 可以很方便得將“可空”轉爲“非空”,但可空變量值爲 null,則會 crash。
- 因此使用上建議在確保非空時才用 !!: param!!
- 否則還是儘量放在判空代碼塊裏:
param?.let { doSomething(it) }
想換個工作,渴望同行內推我
-
個人信息
- 姓名:楊充【26歲】
- 郵箱:[email protected]
- 微信:13667225184
- GitHub:https://github.com/yangchong211
- 博客彙總:https://github.com/yangchong211/YCBlogs
- 幹活集中營:Android端技術博客和開源項目審覈員
- 目前工作情況:在職狀態
- 技術項目和博客:GitHub項目7k以上star,follower1.1k以上,發表博客100多篇。
- 熱愛技術:開源項目和博客多次被鴻洋,郭霖,Android技術週刊,幹活集中營等等推薦。
- 學歷:武漢軟件工程職業學院,大專學歷
- 工作年限:3年多
- 工作地點:北京
-
關於近期投遞簡歷一點感想
- 從進入Android這個行業以來,前兩次幾乎都是朋友內推,面試機會相對容易,都是一個App一個人做或者兩個人做,用戶相對來說並不多。這次想着離職,主要是想進入一個較大的平臺,大概可以理解爲Android端有個至少四五人,可以進行技術交流,渴望自己能夠在技術上突破,這就像自己平時獨自跑步,和跟着一羣跑馬拉松的人跑步,那種緊張感肯定是不一樣的。
- 近段時間,嘗試着向一些較大的公司投遞簡歷,大概在拉鉤上投了15個左右(不喜歡海投),發現絕大多數簡歷到不了技術那裏,就被人事說學歷不夠,經驗不夠,工作不匹配等情況回絕。不過也可以理解,看簡歷無非就是學歷和經驗,貌似自己的履歷是差了一點。
- 這大概是第一次在網上發一個主動希望同行內推的介紹,如果你的公司有Android方面的招聘,能否內推一下我這個小人物,感謝。
關於其他內容介紹
01.關於博客彙總鏈接
02.關於我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 簡書:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜馬拉雅聽書:http://www.ximalaya.com/zhubo/71989305/
- 開源中國:https://my.oschina.net/zbj1618/blog
- 泡在網上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 郵箱:[email protected]
- 阿里雲博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault頭條:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e