Kotlin中的一些常用關鍵字以及特性

關鍵字

  1. Object:

    1. 簡化生成靜態(tài)內部類

    2. 生成匿名內部類對象

    3. 生成單例對象

      如果object只是聲明,它代表一個靜態(tài)內部類。如果用變量接收object表達式,它代表一個匿名內部類對象。

    object Admin {
        private var username = "admin"
        private var password = "admin"
    
        fun info(): String {
            return "${this.username}/${this.password}"
        }
    
        fun changePassword(password:String){
            this.password = password
        }
    }
    
    fun main(args: Array<String>) {
        Admin.changePassword("new-password")
        println(Admin.info()) // admin/new-password
    }
    
  2. 伴生對象:

    1. 可以把伴生對象看成是一個普通Java類的單例對象,因為它最終也是按照普通類對象進行編譯的,只不過默認給你生成了一個唯一的實例。
    2. Kotlin為什么沒有static的東西,我覺得第一個原因是我們不僅可以引用一個kt文件中的類,也可以引用它所定義的變量以及方法,完全可以用這種方式實現(xiàn)所謂的靜態(tài)屬性以及靜態(tài)方法;如果前面的方式不能滿足需求,companion object帶給我們的優(yōu)勢是我們可以像對待其他普通類一樣繼承類或實現(xiàn)接口,相對于static class給我們帶來了更大的自由度
    class Admin {
    
        companion object {
            private var username = "admin"
            private var password = "admin"
    
            fun info(): String {
                return "${this.username}/${this.password}"
            }
    
            fun changePassword(password:String){
                this.password = password
            }
        }
    }
    
    fun main(args: Array<String>) {
        Admin.changePassword("new-password")
        println(Admin.info()) // admin/new-password
        Admin.changePassword("new-password2")
        println(Admin.info()) // admin/new-password2
    }
    
  1. By:

    1. 類的代理 class

      //kotlin代理 編譯后實為java中的靜態(tài)代理
      interface Animal{
          fun bark()
      }
      
      class Dog : Animal {
          override fun bark() {
              println("DOG's Bark()")
          }
      }
      
      class Zoo(animal: Animal) : Animal by animal {
          override fun bark() {
              println("ZOO’s Bark")
          }
      }
      
      fun main(args: Array<String>) {
          Zoo(Dog()).bark()
      }
      
      
      interface Base {
          val message: String
          fun print()
      }
      
      class BaseImpl(val x: Int) : Base {
          override val message = "BaseImpl: x = $x"
          override fun print() { println(message) }
      }
      
      class Derived(b: Base) : Base by b {
          // 在 b 的 `print` 實現(xiàn)中不會訪問到這個屬性
          override val message = "Message of Derived"
        //但是在復寫了print方法后,執(zhí)行的依然是Derived的print方法調用的本類中的成員變量
      //    override fun print() {
      //        println(message)
      //    }
      }
      
      fun main() {
          val b = BaseImpl(10)
          val derived = Derived(b)
          derived.print()
          println(derived.message)
      }
      
    2. 屬性延遲加載 lazy

    3. 監(jiān)聽屬性變化 Delegates.observable ( 擴展 Delegates.vetoable )

    4. 自定義監(jiān)聽屬性變化 ReadWriteProperty

    5. 屬性非空強校驗 Delegates.notNull()

    6. Map值 映射到類屬性 map

  2. inner

    1、inner修飾的內部類可理解為java中的非靜態(tài)內部類,調用方式:

    外部類().內部類().方法();

    2、kotlin內部類默認為靜態(tài)的,理解為java中使用static修飾的內部類,調用方式:

    外部類.內部類().方法();

    3、如果需要在靜態(tài)內部類中使用外部類,可參考java中實現(xiàn)方式,在內部類中定義外部類弱引用,通過構造方法傳入外部類對象;

    class InnerTest{
        var a=5
    
        class NotInner{
            fun m1(i: Int):Int {
    //            a=i  編譯不通過
                return i + 1
            }
        }
    
        //inner修飾過的內部類可以訪問外部內成員變量
        inner class WithInner{
            fun m2(i: Int):Int {
                a=i
                return a
            }
        }
    }
    
    
    fun main(args: Array<String>) {
        print(InnerTest.NotInner().m1(5)) //調用沒有被inner修飾過的內部類時,外部類不需要被實例化,類似與java中的靜態(tài)內部類
        print(InnerTest().WithInner().m2(5)) //InnerTest類需要實例化才能調用被inner修飾過的內部類
    
    }
    
  3. 解構Operator:

    1. 無date關鍵詞

      //解構 方法體必須聲明為componentN()
      class Boy(var age: Int, var name: String){
          operator fun component1()=age
          operator fun component2()=name
      }
      
      
      
      fun main(args: Array<String>) {
          var p1 = Person(19, "張三", "張二狗")
          var(age,name,lastname)=p1
      }
      
    2. 有date關鍵字

      //數(shù)據(jù)類中自帶了operator操作符,無需使用componentN()函數(shù)
      data class Person(val age: Int, val name: String, val lastName: String)
          
          
      fun main(args: Array<String>) {
          var (age, name) = Boy(15, "珠海")
      }
      
  4. 循環(huán)

    for(i in 1..10){}//包括10
    for(i in 1 until 10) //不包括10
    for(i in 10 downTo 1)
    for(i in 1..10 step 2) //步進2
    repeat(10){} //循環(huán)10次 
    
//循環(huán)list
val testList = listOf<String>("a", "b", "c")
for ((index, value) in testList.withIndex()) {
        print(index.toString()+value)
 }
  1. 作用域函數(shù)

    //返回lambda表達式結果
    run{...}
    let{...}
    with(T){...}
    //返回上下文對象
    apply{...}
    also{...}
    
  1. Lambda閉包

     val echo = { name: String -> print(name) }
     echo.invoke("張三")//invoke 調用,操作符重載 等價于下面一條語句
     echo("王二")
    
  1. 高階函數(shù)(使用閉包函數(shù)作為參數(shù)傳入)
//高階函數(shù)
fun onlyif(age:Int,isDebug: Boolean, block: (a:Int) -> Unit) {
    if (isDebug){
        block(age)
    }
}
fun main(args: Array<String>) {
    val lam:(a:Int)->Unit//lambda聲明

    lam={ print(it + 1)} //lambda表達式實現(xiàn)

    onlyif(5,true,lam)//調用方法,傳入參數(shù)
}
  1. inline

通過該關鍵字來優(yōu)化代碼,編譯器將使用函數(shù)的定義體來替代函數(shù)調用語句,這種替代行為發(fā)生在編譯階段而非程序運行階段

 fun plus(i: Int){
     i += 1
 }
 //該段代碼會報Val cannot be reassigned的錯誤,因為kotlin是直接值傳遞,而java在值傳遞時候形參實際上是經過一次復制后的新值(內存地址改變,value不變)
  1. sealed關鍵字

    sealed class CompareResult{
        object Less:CompareResult() {
            override fun toString(): String {
                return "小于"
            }
        }
        object More : CompareResult() {
            override fun toString(): String {
                return "大于"
            }
        }
        object Equals : CompareResult() {
            override fun toString(): String {
                return "相等"
            }
        }
    }
    //一旦使用密封類就要用完密封類中所有的子類,不然會編譯期報錯
    fun check(cr: CompareResult):String {
        when (cr) {
            is CompareResult.Equals -> return cr.toString()
            is CompareResult.More -> return cr.toString()
            is CompareResult.Less -> return cr.toString()
        }
    }
    
    infix fun Int.vs(num: Int): CompareResult =
        if (this > num) {
            CompareResult.More
        }else if (this < num) {
            CompareResult.Less
        }else{
            CompareResult.Equals
        }
    
    fun main(args: Array<String>) {
        print(7 vs 7)
    }
    
  2. infix關鍵字

    使用該關鍵字進行操作符重載

    infix fun Int.vs(num: Int): CompareResult =  //自定義了一個操作符vs 該操作符是以拓展函數(shù)的放法添加在目標類上的。
        if (this > num) {
            CompareResult.More
        }else if (this < num) {
            CompareResult.Less
        }else{
            CompareResult.Equals
        }
    
    fun main(args: Array<String>) {
        print(7 vs 7)
    }
    
  3. enum枚舉

    enum class AE(var age: Int, var lname: String) {
        A(14, "張三") {
            override fun a(a: Int): Int = a + 1
        },
        B(15, "王二") {
            override fun a(a: Int): Int = a + 2
        };
    
        //抽象方法,需要枚舉實例自己實現(xiàn)方法
        abstract fun a(a: Int): Int
    
        //每個枚舉實例都默認實現(xiàn)該方法跟java枚舉一樣
        fun b(str: String): String = str + this.lname
    }
    
    fun check(a: AE) {
        when (a) {
            AE.A -> print(a.lname)
            AE.B -> print(a.age)
        }
    }
    
    fun main(args: Array<String>) {
        check(AE.A)
    }
    
  4. 比較是否相等
    java kotlin
    a==b -> a ===b
    a.equals(b) -> a==b

  5. 集合

    kotlin中的集合默認為只讀類型,可變類型是在不可變類型前添加Mutable

    獲取一個新集合

    
    var nums= mutableListOf<Int>()
    
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容