對於 Null 的檢查是 Kotlin 的特點之一。強制你在編碼過程中考慮變量是否可為 null,因此可以避免很多在 Java 中隱藏的 NullPointerException。
但是,當你用插件直接將 Java 代碼轉換為 Kotlin 時,你會發現有很多 !! 在里面。但其實 !! 意味着「有一個潛在未處理的 KotlinNullPointerException 在這里」。
這里就介紹 6 個避免 !! 的方法:
1. 用 val 而不是 var
在 Kotlin 中 val 代表只讀,var 代表可變。建議盡可能多的使用 val。val 是線程安全的,並且不需要擔心 null 的問題。只需要注意 val 在某些情況下也是可變的就行了。
可以看看這里:Mutable vals in Kotlin
2. 使用 lateinit
有些情況我們不能使用 val,比如,在 Android 中某些屬性需要在 onCreate() 方法中初始化。對於這種情況,Kotlin 提供了 lateinit 關鍵字。
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。對於基礎數據類型,我們可以這樣:
private var mNumber: Int by Delegates.notNull<Int>()
3. 使用 let 函數
下面是 Kotlin 代碼常見的編譯錯誤:

許多開發者都會選擇 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

