網站首頁 編程語言 正文
一、lateinit延遲初始化關鍵字
Kotlin中很多語法特性,如變量不可變,變量不可為空,等等 這些特性都是為了盡可能地保證程序安全而設計的,比如你的類中存在很多全局變量實例,為了保證它們的能夠滿足Kotlin的空指針檢查語句標準,你不得不做非空判斷保護,即使你非常確定它們不會為空。
下面距離看一下 :
class MainActivity : AppCompatActivity() {
private var s: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
s = "test"
Log.d("TAG", "onCreate: ${s!!.length}")
}
}
我們將s 設置為了全局變量 , 但是它的賦值工作在onCreate()方法進行的,因此不得不將s賦值為null。
雖然你確定在打印前已經將s賦值成功,但是打印s的長度仍然要進行判空處理才行,否則編譯不通過。
當你的代碼中越來越多的全局變量實例時,這個問題就會變得越來越明顯,到時候可能必須寫大量額外判空處理的代碼,卻只是為了滿足Kotlin的編譯要求。
幸運的是,這個問題有解決辦法的且非常之簡單,就是對全局變量進行延遲初始化。
初始化使用的關鍵字 lateinit ,它可以高速編譯器,我會在晚些時候對這個變量進行初始化,這樣就不用一開始就賦值為null了。
class MainActivity : AppCompatActivity() {
private lateinit var s: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
s = "test"
Log.d("TAG", "onCreate: ${s.length}")
}
}
可以看到,加上了lateinit關鍵字 ,這樣一開始就不用賦值為null了,打印長度的時候也不用進行判空處理了,當然使用lateinit關鍵字 也不是沒有風險,如果沒有進行賦值,那么程序一定會崩潰,并拋出異常。
另外,我們可以通過代碼來判斷全局變量是否已完成了初始化工作,這樣某些時候可以有效避免重復對某一個變量進行初始化操作。
class MainActivity : AppCompatActivity() {
private lateinit var s: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!::s.isInitialized) {
s = "test"
}
Log.d("TAG", "onCreate: ${s.length}")
}
}
二、使用密封類優化代碼
新建一個Kotlin文件,代碼如下 :
interface Result
class Success(val msg: String) : Result
class Failure(val error: Exception) : Result
這里定義了一個Result接口,用于表示某個操作的執行結果,接口中沒有編寫任何內容。然后定義了兩個類去實現Result接口:一個Success類用于表示成功時結果,一個Failure類用于表示失敗時結果。
接下來再定義一個getResultMsg()方法 ,用于獲取最后執行結果的信息,代碼如下:
fun getResultMsg(result: Result) = when (result) {
is Success -> result.msg
is Failure -> result.error.message
else -> throw IllegalArgumentException()
}
getResultMsg()方法中接受一個Result參數,我們通過when語句來判斷,如果Result屬于Success就返回成功的消息,如果Result是Failure就返回錯誤的信息,到目前為止代碼是沒什么問題的,煩人的是不得不寫一個else條件語句,否則Kotlin編譯不通過,其實代碼永遠也走不到else里 因為只有兩種類型的存在,只是為了滿足Kotlin的語法而已。
另外,編寫else條件還有一個潛在的風險,如果我們新增一個Unknown類并實現了Result接口,用于表示未知的執行結果,但是忘記了在getResultMsg()方法中添加相應的條件,編譯器不會提醒我們的,而是直接進入else條件里面去,從里面拋出異常并導致程序崩潰。
Kotlin的密封類很好的解決了此問題,密封類的關鍵字是sealed class ,它的用法同樣很簡單,我們可以輕松的將Result接口改造成密封類寫法:
sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
fun getResultMsg(result: Result) = when (result) {
is Success -> result.msg
is Failure -> result.error.message
}
代碼沒什么變化,只是將interface改成了 sealed class。密封類是一個可繼承的類,因此在繼承它的時候還需要加上一對括號。
密封類的優點是,可以再getResultMsg() 方法中取消else條件語句。
為什么取消掉else條件語句還能編譯通過呢,Kotlin編譯器會自動檢查該密封類有哪些子類,并強制要求將每一個子類所對應的條件全部處理。這樣就可以保證,即使沒有else條件,也不可能出現漏寫的情況,如果現在新增一個Unknown類,并也讓它繼承自Result,此時getResultMsg()方法就一定會報錯,必須添加Unknown語句條件才能編譯通過。
注意:密封類及其所有子類只能定義同一個文件的頂層位置,不能嵌套在其他類中,這也是被密封類底層實現機制所限制的。
原文鏈接:https://blog.csdn.net/m0_63970488/article/details/126065532
相關推薦
- 2022-06-23 詳解windows?server?2012的DHCP保留地址導出導入、DHCP故障轉移配置、DNS條
- 2022-07-21 IC設計中glitch free時鐘選擇器的設計過程
- 2023-02-15 Python二進制轉化為十進制數學算法詳解_python
- 2022-10-20 Flutter組件實現進度指示器_Android
- 2021-12-19 詳細易懂注解,二維數組楊輝三角的實現,算法入門
- 2022-04-28 C++實現簡單班級成績管理系統_C 語言
- 2022-09-12 Nginx報404錯誤的詳細解決方法_nginx
- 2022-06-11 Kubernetes集群環境初始化_云其它
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支