最近挺長一段時間,Flutter相關的技術文章和討論各類刷屏,而我:前端
摸魚挺長一段時間,折騰了不少花裏胡哨的東西,最近打算重拾Android開發的老本行,廣度 -> 深度,好好複習幾個月,準備Android面試,儘管常常有人調侃:android
每一個人的時間都是有限的,一旦作出學習某塊知識的選擇,意味着付出了暫時沒法學習其餘知識的機會成本,須要取捨。不可能等什麼都學會了再去面試,學完得猴年馬月,並且技術,是學不完的…
如何在有限時間內效益最大化,選擇學什麼顯得尤其重要,看下掘金Android類的TAG:web
排行第一的是Flutter和Kotlin,二者的區別,在《Kotlin 和 Flutter 對於開發者究竟意味着什麼?》中的描述:面試
Flutter和Kotlin並不衝突!apache
- Kotlin可解讀爲:Android逐漸放棄Java這個開發依賴。
- Flutter則可解讀爲:Google 開始放棄 Android,迎接新操做系統 Google Fuchsia的準備。
接着二選一咯,具體學哪一個,仍是看市場需求,拉鉤隨手搜下Flutter和Kotlin的崗位需求:編程
其中一則Flutter崗的任職要求:安全
可能作過RN和前端的開發仔更適合學Flutter吧~app
行吧,仍是作回原生開發仔,Android原生開發,愈來愈多的公司加上「熟悉Kotlin」這條招聘要求,被如火如荼的Flutter浪潮淹沒,你們可能都忘了,在今年五月的Google I/O大會上,官方曾宣佈:「Kotlin編程語言是Android應用開發的首選語言」!編程語言
初次接觸Kotlin已經是三年前,在上家公司用Kotlin重構了平板的應用市場和電臺APP。說來慚愧,至今仍是一個API選手,不過相信在座不少Android開發和我同樣,都停留在會用的程度。函數
不想止步於會用,還想了解下原理,因此有了這個系列。本節先來刨一刨Kotlin中的空安全~
NullPointerException(NPE),空指針異常,在Java開發時,若是不想遇到這種異常,須要在使用前不停地判斷它是否爲Null。而在Kotlin中是空安全的,在編譯期就處理Null,以此避免執行時異常。另外空安全不是Kotlin特有的,其餘不少的變成語言也有,接着簡單描述下Kotlin空安全的相關用法。
Kotlin中經過「非空類型」和「可空類型」來規避空NPE,非空類型不能設置爲Null值:
可空類型能夠設置爲Null值,在類型後加上 可空操做符(?) 便可,代碼示例以下:
可空類型,直接訪問它的屬性或方法,會報錯:
能夠經過 安全調用操做符(?.) 或 非空斷言運算符(!!) 來解決,代碼示例以下:
運行結果以下:
三目條件運算符的簡略寫法:若是不是空,就返回它,不然返回另外一個值。代碼示例以下:
Kotlin中可使用as
關鍵字來進行類型轉換,而使用as?
表示安全類型的轉換。最多見的使用場合,後臺接口返回一個參數,須要咱們本身作下類型轉換,直接用as的話,若是參數爲null或者非String類型,就可能引起異常,若是用as? ,參數異常則不會轉換,代碼示例以下:
運行結果以下:
let函數除了可用於在同一個做用域下操做變量外(代碼更優雅)外:
tvTitle.let {
it.text = "標題"
it.textSize = 18.0f
it.gravity = Gravity.LEFT or Gravity.CENTER
it.setOnClickListener {}
}
複製代碼
還能夠用做作判null操做,好比下面這樣的代碼:
test咱們已經設置了一個值,可是仍是報錯,添加上一個非空斷言便可:
還有個更優雅的寫代碼方式,就是用?.let{},修改後的代碼以下:
另外?.let{}遍歷集合會忽略null值,只對非null值執行操做;除此以外,還能夠用集合操做函數filterNotNull過濾出非空元素。
如題,Kotlin中並非絕對的空指針安全,最多見的就是在Kotlin去調Java代碼,好比下面這個例子:
//Java
public class Test {
public static String getMsg() {
return null;
}
}
//Kotlin
fun main() {
println(Test.getMsg().length)
}
複製代碼
運行後就直接報錯:
當你與Java代碼進行互操做時,Null安全性確實被破壞了,固然想規避這個問題也很簡單,加個?便可,示例以下:
fun main() {
println(Test.getMsg()?.length)
}
複製代碼
運行結果以下:
接着咱們來探究下,Kotlin中究竟是怎麼實現空安全的,寫下簡單的代碼:
fun test_1(str: String) = str.length
fun test_2(str: String?) = str?.length
fun test_3(str: String?) = str!!.length
fun test_4(str: Any?) { str as String }
fun test_5(str: Any?) { str as? String }
複製代碼
接着依次點擊:Tools -> Kotlin -> Show Kotlin Bytecode,生成字節碼:
生成後的Java代碼以下:
接着分析一波,首先是test_1函數,能夠看到這裏有一個@NotNull的註解,而後是:
Intrinsics.checkParameterIsNotNull(str, "str");
複製代碼
Intrinsics是Kotlin的一個內部類,定位到checkParameterIsNotNull函數:
再跟:
行吧,其實就是直接對參數判空,若是爲空拋出參數爲空的異常。接着看下test_2函數,比較簡單,判斷是否爲空,不爲空的話,調用對應的方法,不然返回一個null。再接着是test_3函數,直接判斷是否爲空,空的話直接拋出Npe異常。
而後是test_4函數,判空,若是空拋出類型轉換異常,不然執行後續代碼;最後是test_5函數,建立一個新對象把參數的值傳給他,而後進行類型判斷,若是不是特定類型,對象賦值null,而後把執行類型強轉後的對象賦值給一個新的對象。
綜上,Kotlin中對空安全背後的處理套路以下:
- 一、非空類型的屬性編譯器添加@NotNull註解,可空類型添加@Nullable註解;
- 二、非空類型直接對參數進行判空,若是爲空直接拋出異常;
- 三、可空類型,若是是?.判空,不空才執行後續代碼,不然返回null;若是是!!,空的話直接拋出NPE異常。
- 四、as操做符會判空,空的話直接拋出異常,不爲空才執行後續操做,沒作類型判斷!運行時可能會報錯!
- 五、as?則是新建一個變量,參數賦值給它,而後判斷是否爲特定類型,賦值爲null,接着把這個變量的值賦值給另外一個新的變量,這裏有一點注意:as?處理後的參數可能爲空!!!因此調用as?轉換後的對象還須要添加安全調用操做符(?.)
提醒:(這裏直接用編譯後Java代碼的緣由是比較直觀~)
- @NotNull註解對應字節碼裏的:@Lorg/jetbrains/annotations/NotNull;
- @Nullable註解對應字節碼裏的:@Lorg/jetbrains/annotations/Nullable;
以上就是本人關於Kotlin中空安全實現原理的解讀,若是紕漏或建議,歡迎在評論區指出,謝謝~
參考文獻:
若是本文對你有所幫助,歡迎
留言,點贊,轉發
素質三連,謝謝😘~