Kotlin筆記

要點(diǎn)1:主構(gòu)造器

class User constructor(var id:Int, var name:String?, var job:String?) {
  init{
    // 初始化代碼塊
  }
  // 次構(gòu)造器必須(可間接)調(diào)用主構(gòu)造器
  constructor() : this(null, null, null)
}

要點(diǎn)2:data class [語法糖]

  • 編譯器會自動生成:equals、hashCode牙甫、toString、copy函數(shù)
data class User constructor(var id:Int, var name:String?, var job:String?) 
  • Copy函數(shù):
val user = User(1, "Name","Engineer")
val userCopy = user.copy()
println(user == userCopy)  // true, '=='比較對象
println(user === userCopy)  // false, '==='比較地址
  • 解構(gòu):可以不用返回包裝類调违,直接返回所有類屬性
fun getUserInfo() = User(1, "Name","Engineer")
fun main() {
    // 寫法:
    val(id, name, job) = execute()
    println("id=$id, name=$name, job=$job")
}

原理:data class自動生成component1,2,3...方法對應(yīng)構(gòu)造器參數(shù)

@Nullable
public final String component1() { return this.id; }

@Nullable
public final String component2() { return this.name; }

@Nullable
public final String component3() { return this.job; }

要點(diǎn)3:非空判斷

// kotlin語法
var job = user.job ?: "自由職業(yè)"
// 等價于 
var job = user.job
if (job == null) {
  job = "自由職業(yè)"
}

?. 聯(lián)用

// kotlin寫法
if (user.name?.length ?:0 < 6) {
}
// 等價于
if (user.name == null || user.name!!.length < 6) {
}

要點(diǎn)4:利用filter和forEach來替代for循環(huán)及if條件判斷

// 原寫法
for(user in users) {
  if(user.job == "Engineer") {
    selectedUsers.add(user)
    println(user.name)
  }
}
// 使用forEach簡化后
users.forEach { //it代指參數(shù)
  if (it.job == "Engineer") {
    selectedUsers.add(user)
    println(user.name)
  }
}
// 使用filter簡化
users.filter { it.job == "Engineer" }.forEach { println(it.name) }
  • 寫法說明:函數(shù)如果最后一個參數(shù)是lambda窟哺,則可以將lambda寫在()外,如果僅有l(wèi)ambda一個參數(shù)技肩,則()也可以省略且轨。

要點(diǎn)5:循環(huán)-Kotlin

// repeat函數(shù),循環(huán)n次
repeat(50) {
  println(it)
}
// for-i循環(huán)虚婿,使用區(qū)間
val array = intArrayOf(1,2,2,3,4,5,6,7,8,9,50) 
for (i in 0 until array.size) {
}
for (i in array.indices) {
}

要點(diǎn)6:函數(shù)嵌套-kotlin

  • Kotlin允許函數(shù)內(nèi)嵌套函數(shù)旋奢,內(nèi)部函數(shù)可以訪問外部函數(shù)的屬性
  • 優(yōu)點(diǎn):如該內(nèi)部函數(shù)僅有此調(diào)用,則可以增強(qiáng)代碼可讀性然痊,避免被其他人調(diào)用
  • 缺點(diǎn):嵌套函數(shù)會在每次被調(diào)用時生成額外對象至朗,在循環(huán)中則不建議使用嵌套函數(shù),避免生成過多垃圾對象
private fun outerFun() {
  val verifyCode = code.text.toString()
  ...
  fun verify() : Boolean {
    if (verifyCode?.length?:0<6) {
      Logger.e("驗(yàn)證碼不正確")
      return false
    }
  }
}

要點(diǎn)7:對象自定義get方法名剧浸,禁用set

  • Kotlin會為非private的var對象創(chuàng)建get()/set()方法锹引;
  • 如果不想讓set方法暴露,可使用private set修飾
  • 如果想自定義get方法名辛蚊,可使用注解@get:JvmName("selfieGetApp")
companion object {
  @get:JvmName("selfieGetApp")
  @JvmStatic
  lateinit var currentApp: Context
    private set
}

要點(diǎn)8:類型推斷

  • 可簡化函數(shù)聲明
// 原函數(shù)聲明
fun saveCache(key:String?, value:String?) : Unit { 
  cacheMap.putString(key, value)
}
fun getCache(key:String?) : String? { 
  return cacheMap.getString(key, null)
}
// 類型推斷用上粤蝎,簡化后
fun saveCache(key:String?, value:String?) = cacheMap.putString(key, value)
fun getCache(key:String?) = cacheMap.getString(key, null)

要點(diǎn)9:函數(shù)參數(shù)默認(rèn)值

  • 可簡化重復(fù)代碼,避免函數(shù)重載
  • 如在Java中調(diào)用袋马,則通過注解@JvmOverloads初澎,生成對應(yīng)的重載函數(shù)
// 函數(shù)定義
@JvmOverloads
fun toast(string:String?, duration:Int=Toast.LENGTH_SHORT) {
  Toast.makeText(BaseApplication.currentApplication, string, duration).show()
}

// 函數(shù)調(diào)用
toast("Hello World")
toast("Hello World", 3000)

要點(diǎn)10:擴(kuò)展 (kotlin非常好用的一個特性)

  • 可給任何一個類加上成員屬性或成員函數(shù)
  • 可用來替換工具類
  • 如果把已存在的函數(shù)或?qū)傩杂脭U(kuò)展覆蓋了怎么辦?
    答:以原有成員函數(shù)為準(zhǔn)
  • 如果為父子類均擴(kuò)展了相同函數(shù)怎么辦虑凛?
    答:編譯器生成拓展函數(shù)時碑宴,分別以父/子類的類型作為第一個函數(shù)參數(shù),所以調(diào)用域是哪個就會調(diào)用到哪個的拓展函數(shù)
// 定義:給Float類擴(kuò)展dp2px函數(shù)
fun Float.dp2px() : Float {
  // 使用this訪問自身
  return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, displayMetrics)
}

// 調(diào)用
12f.dp2px()

再來一個添加擴(kuò)展成員屬性的例子

// 取LinearLayout第一個子元素
val LinearLayout.firstChild: View
    get() = getChildAt(0) 

要點(diǎn)11:內(nèi)聯(lián)函數(shù)(inline關(guān)鍵字)

詳見 Kotlin內(nèi)聯(lián)函數(shù)使用場景

要點(diǎn)12:函數(shù)類型 作為 參數(shù)/返回值

  • Kotlin中允許函數(shù)作為函數(shù)的參數(shù)或返回值桑谍,從而可替代Java中接口類包裝
  • 實(shí)際上延柠,函數(shù)類型參數(shù) 是kotlin在Functions.kt中預(yù)定義好的一系列接口,從Function0..22
// 定義一個函數(shù)
fun setOnClickListener(listener : (View) -> Unit) {
}

val view = View(context)
// 調(diào)用1:  ‘::’雙冒號傳遞函數(shù)對象
view.setOnClickListener(::onClick)
fun onClick(view : View) {
  println("點(diǎn)擊")
}
//調(diào)用2:匿名函數(shù)
view.setOnClickListener(fun (view:View) {
  println("點(diǎn)擊")
})
//調(diào)用3:Lambda形式
view.setOnClickListener { //使用it代指view
  println("點(diǎn)擊")
}

要點(diǎn)13:抽象屬性

Kotlin支持在接口聲明抽象屬性

interface BaseView<T> {
    val presenter:T
}
// 實(shí)現(xiàn)處
val userPresenter = UserPresenter(this)
override val presenter: UserPresenter?
  get() = userPresenter 

要點(diǎn)14:kotlin特性-委托

  • by lazy:
    作用1:by lazy包含的代碼只會加載一次
    作用2:by lazy修飾的對象僅在被調(diào)用時才創(chuàng)建
    于是锣披,要點(diǎn)13中的代碼就可以優(yōu)化為:
override val presenter: LessonPresenter by lazy {
  UserPresenter(this)
}
  • 通過by關(guān)鍵詞實(shí)現(xiàn)屬性委托:

先看一段不優(yōu)雅的代碼

var userid: String
  set(value) {
     CacheUtils.save("userid", value)
  }
  get() {
     return CacheUtils.get("userid")!!
  }

var username: String
  set(value) {
     CacheUtils.save("username", value)
  }
  get() {
     return CacheUtils.get("username")!!
  }

使用委托優(yōu)化
1贞间、聲明一個Saver類,構(gòu)造函數(shù)傳入key雹仿,實(shí)現(xiàn)getValue/setValue方法執(zhí)行原本的set/get操作

class Saver(var key: String) {
  operator fun getValue(activity: MainActivity, property: KProperty<*>): String {
    return CacheUtils.get(key)!!
  }
  operator fun setValue(activity: MainActivity, property: KProperty<*>, value: String) {
    CacheUtils.save(key, value)
  }
}

2增热、在聲明userid、username變量時胧辽,將對應(yīng)的get/set操作委托給Saver對象

var userid: String by Saver("userid")
var username: String by Saver("username")

通過反編譯看看編譯器是如何實(shí)現(xiàn)的呢峻仇?

// 創(chuàng)建Saver對象 xxx$delegate 
@NotNull
private final MainActivity.Saver userid$delegate = new MainActivity.Saver("userid");
@NotNull
private final MainActivity.Saver username$delegate = new MainActivity.Saver("username");

// 在get/set方法里,通過分別創(chuàng)建的Saver對象執(zhí)行g(shù)etValue/setValue方法
@NotNull
public final String getUserid() {
    return this.userid$delegate.getValue(this, $$delegatedProperties[0]);
}
public final void setUserid(@NotNull String var1) {
    this.userid$delegate.setValue(this, $$delegatedProperties[0], var1);
}

@NotNull
public final String getUsername() {
    return this.username$delegate.getValue(this, $$delegatedProperties[1]);
}
public final void setUsername(@NotNull String var1) {
    this.username$delegate.setValue(this, $$delegatedProperties[1], var1);
}

要點(diǎn)15:kotlin內(nèi)置標(biāo)準(zhǔn)函數(shù)(作用域函數(shù))

詳見 kotlin作用域函數(shù)let/with/run/apply/also

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邑商,一起剝皮案震驚了整個濱河市摄咆,隨后出現(xiàn)的幾起案子凡蚜,更是在濱河造成了極大的恐慌,老刑警劉巖吭从,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朝蜘,死亡現(xiàn)場離奇詭異,居然都是意外死亡影锈,警方通過查閱死者的電腦和手機(jī)芹务,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸭廷,“玉大人枣抱,你說我怎么就攤上這事×敬玻” “怎么了佳晶?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長讼载。 經(jīng)常有香客問我轿秧,道長,這世上最難降的妖魔是什么咨堤? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任菇篡,我火速辦了婚禮,結(jié)果婚禮上一喘,老公的妹妹穿的比我還像新娘驱还。我一直安慰自己,他們只是感情好凸克,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布议蟆。 她就那樣靜靜地躺著,像睡著了一般萎战。 火紅的嫁衣襯著肌膚如雪咐容。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天蚂维,我揣著相機(jī)與錄音戳粒,去河邊找鬼。 笑死虫啥,一個胖子當(dāng)著我的面吹牛享郊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播孝鹊,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼展蒂!你這毒婦竟也來了又活?” 一聲冷哼從身側(cè)響起柳骄,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤曲初,失蹤者是張志新(化名)和其女友劉穎抒痒,沒想到半個月后故响,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丰捷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年停巷,在試婚紗的時候發(fā)現(xiàn)自己被綠了畔勤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情判族,我是刑警寧澤五嫂,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站肯尺,受9級特大地震影響沃缘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜则吟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一槐臀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氓仲,春花似錦水慨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至啥箭,卻和暖如春谍珊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背急侥。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工砌滞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坏怪。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓贝润,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铝宵。 傳聞我的和親對象是個殘疾皇子打掘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容