筆者最近幾個月在學習kotlin瞎颗,然后用來重構項目坐搔,反正是不斷踩坑中婉徘,踩的很開心??漠嵌,這個過程中碰到了一些問題咐汞,值得記錄下來, 供大家參考。
如何定義一個非空變量
本次的問題是如何定義一個非空變量儒鹿,有哪些實現(xiàn)手段呢化撕?
在此之前糊肤,我先講講如何定義常量變量贯莺,為了方便學習kotlin的語法特性卢未,推薦使用idea開發(fā)工具撵枢。
那么現(xiàn)在創(chuàng)見一個java工程脐湾,選擇kotlin支持钦购。
創(chuàng)建一個文件您单,內容如下
class User {
var name:String? = null
val id:String? = null
}
fun main(args: Array<String>) {
println("Hello World")
}
在這里我們定義了一個model類User却紧,User類有兩個屬性贱傀,一個是變量name可空惨撇,一個是常量id可空
我們想知道這個文件最終對應的java代碼是什么,有什么辦法呢府寒,我只會反編譯額魁衙。接著就編譯這個App.kt文件,idea中選擇app.kt文件株搔,然后單擊右鍵Recompile App.kt,就會編譯出class文件剖淀,接著我們用JD_GUI反編譯工具,去查看這兩個class文件的內容
這個就是最終的反編譯出來的java代碼纤房,我們可以理解為kotlin編譯后得到的就是這樣的java代碼纵隔。
我們關注的重點是User類,id是定義的一個常量炮姨,反編譯出來的代碼里面將它設置了為final類型捌刮,默認的訪問級別也是private,這也是kotlin的設計理念(不知道說的對不對_)舒岸,屬性私有化,對外提供geter绅作,seter。而變量name蛾派,就跟我們平常定義java屬性的方式類似俄认,private String name
,到此洪乍,如何定義一個常量變量就講完了眯杏,對應生成的java代碼我們也看到了,接下來回到正題典尾,如何定義一個非空變量,有哪些手段?
先看一段代碼片段吧(來自https://github.com/leanote/leanote-android)
我們拿這個NoteFragment來描述糊探,我需要在onCreate方法中初始化這個mNoteFragment钾埂,但是我不想讓kotlin的代碼中河闰,出現(xiàn)mNoteFragment?.setMode(mode)
這樣的代碼?
不想各個地方都出現(xiàn)這樣的代碼褥紫,如果把mNoteFragment定義為非空的那就好了姜性,說干就干,該如何修改呢髓考?
不可能直接這樣改
var mNoteFragment: NoteFragment = NoteFragment.newInstance()
,這樣有問題的部念,就不多說了。
考慮到kotlin的語言特性我想到的只有
lateinit var mNoteFragment: NoteFragment
這樣在onCreate方法里面初始化是可以的氨菇。
var mNoteFragment: NoteFragment by Delegates.notNull<NoteFragment>()
和這種委托的模式
我們先看這一段代碼儡炼,lateinit方式的
class MainActivity {
lateinit var mNoteFragment: String
fun onCreate() {
mNoteFragment = newInstance()
}
companion object {
fun newInstance():String {
return "NoteFragment"
}
}
}
這種情況下生成的java代碼如下
lateinit var mNoteFragment: String
被翻譯成了@NotNull public String mNoteFragment
mNoteFragment被定義為了public訪問級別
接著看看委托模式下的
import kotlin.properties.Delegates
class MainActivity {
var mNoteFragment: String by Delegates.notNull<String>()
fun onCreate() {
mNoteFragment = newInstance()
}
companion object {
fun newInstance():String {
return "NoteFragment"
}
}
}
反編譯的java代碼比較復雜,暫時也沒有深究查蓉,感覺要麻煩多了
我們定義的mNoteFragment屬性不見了乌询,反而多了一個mNoteFragment$delegate屬性,而且還是在構造方法中做的初始化操作豌研,以及一個$$deletegatedProperties在靜態(tài)代碼塊初始化的不知道什么東西的東西妹田,雖然沒有了mNoteFragment,但是還是有對應的geter,setter方法鹃共,具體就不深究了鬼佣,暫時功力有限。
總結
到此為止霜浴,講完了晶衷。
定義一個非空屬性,基本上常用的手段就是lateinit和委托模式坷随。