優雅的運用 Kotlin 的 null safety 特性,而不要簡單的直接用 !!雙感嘆號

對於 Null 的檢查是 Kotlin 的特色之一。強制你在編碼過程當中考慮變量是否可爲 null,所以能夠避免不少在 Java 中隱藏的 NullPointerException。android

可是,當你用插件直接將 Java 代碼轉換爲 Kotlin 時,你會發現有不少 !! 在裏面。但其實 !! 意味着「有一個潛在未處理的 KotlinNullPointerException 在這裏」。安全

這裏就介紹 6 個避免 !! 的方法:ide

1. 用 val 而不是 var

在 Kotlin 中 val 表明只讀,var 表明可變。建議儘量多的使用 val。val 是線程安全的,而且不須要擔憂 null 的問題。只須要注意 val 在某些狀況下也是可變的就好了。函數

能夠看看這裏:Mutable vals in Kotlin

2. 使用 lateinit

有些狀況咱們不能使用 val,好比,在 Android 中某些屬性須要在 onCreate() 方法中初始化。對於這種狀況,Kotlin 提供了 lateinit 關鍵字。ui

private lateinit var mAdapter: RecyclerAdapter<Transaction>

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mAdapter = RecyclerAdapter(R.layout.item_transaction) } fun updateTransactions() { mAdapter.notifyDataSetChanged() }

 

要注意,訪問未初始化的 lateinit 屬性會致使 UninitializedPropertyAccessException編碼

而且 lateinit 不支持基礎數據類型,好比 Int。對於基礎數據類型,咱們能夠這樣:spa

private var mNumber: Int by Delegates.notNull<Int>() 

3. 使用 let 函數

下面是 Kotlin 代碼常見的編譯錯誤:.net

 

 

 

 

許多開發者都會選擇 quick-fix:插件

 

private var mPhotoUrl: String? = null fun uploadClicked() { if (mPhotoUrl != null) { uploadPhoto(mPhotoUrl!!) } }

 

但這裏選擇 let 函數是一個更優雅的解決方法:線程

private var mPhotoUrl: String? = null fun uploadClicked() { mPhotoUrl?.let { uploadPhoto(it) } }

 

4. 建立全局函數來處理更復雜的狀況

let 是一個對於 null 檢查很好的替代品,但有時咱們會遇到更復雜的狀況。好比:

if (mUserName != null && mPhotoUrl != null) { uploadPhoto(mUserName!!, mPhotoUrl!!) }

 

你能夠選擇嵌套兩個 let,但這樣可讀性並很差。這時你能夠構建一個全局函數:

fun <T1, T2> ifNotNull(value1: T1?, value2: T2?, bothNotNull: (T1, T2) -> (Unit)) { if (value1 != null && value2 != null) { bothNotNull(value1, value2) } }

 

5. 使用 Elvis 運算符

Elvis 運算符在 Groovy 和 PHP 等語言中都存在。對於當值可能爲 null 的狀況特別方便:

fun getUserName(): String { if (mUserName != null) { return mUserName!! } else { return "Anonymous" } }

 

上面的代碼就能夠簡化爲:

fun getUserName(): String { return mUserName ?: "Anonymous" }

 

爲何叫 Elvis 呢?由於 ?: 很像貓王的髮型:

 

6. 自定義崩潰信息

若是咱們使用 !!,那麼當這個變量爲 null 時,只會簡單的拋出一個 KotlinNullPointerException。這時咱們能夠用 requireNotNull 或 checkNotNull 來附帶異常信息,方便咱們調試。

uploadPhoto(requireNotNull(intent.getStringExtra("PHOTO_URL"), { "Activity parameter 'PHOTO_URL' is missing" })) 

總而言之,絕大多數狀況下你都不須要 !!,能夠用上面提到的 6 個技巧來消除 !!。這樣能讓代碼更安全、更容易 debug 而且更乾淨。

原文:How to remove all !! from your Kotlin code
相關文章
相關標籤/搜索