Kotlin記錄知識點(一)

  1. 字符串字面值可以包含模板表達式 ,即一些小段代碼,會求值並把結果合併到字符串中。 模板表達式以美元符($)開頭,由一個簡單的名字構成:
val s = "abc"
println("$s.length is ${s.length}") // 輸出“abc.length is 3”
  1. 當某個變量的值可以爲 null 的時候,必須在聲明處的類型後添加 ? 來標識該引用可爲空
    如果 str 的內容不是數字返回 null:
fun parseInt(str: String): Int? {
    // ……
}
  1. 次構造函數
//如果類有一個主構造函數,每個次構造函數需要委託給主構造函數, 
//可以直接委託或者通過別的次構造函數間接委託。委託到同一個類的另一個構造函數用 this 關鍵字即可
class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf<Person>();
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
  1. is 運算符檢測一個表達式是否某類型的一個實例。 如果一個不可變的局部變量或屬性已經判斷出爲某類型,那麼檢測後的分支中可以直接當作該類型使用,無需顯式轉換.
fun getStringLength(obj: Any): Int? {
    if (obj !is String) return null

    // `obj` 在這一分支自動轉換爲 `String`
    return obj.length
}
  1. for 循環
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
    println("item at $index is ${items[index]}")
}

//output 
item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit
  1. when 表達式
    when 既可以被當做表達式使用也可以被當做語句使用。如果它被當做表達式, 符合條件的分支的值就是整個表達式的值,如果當做語句使用, 則忽略個別分支的值。(像 if 一樣,每一個分支可以是一個代碼塊,它的值是塊中最後的表達式的值。)
fun describe(obj: Any): String =
    when (obj) {
        1          -> "One"
        "Hello"    -> "Greeting"
        is Long    -> "Long"
        !is String -> "Not a string"
        else       -> "Unknown"
    }

fun main() {
    println(describe(1))
    println(describe("Hello"))
    println(describe(1000L))
    println(describe(2))
    println(describe("other"))
}
//output:
One
Greeting
Long
Not a string
Unknown
  1. 伴生對象
    類內部的對象聲明可以用 companion 關鍵字標記:
class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}
fun main(){
val instance  = MyClass().create()
}

可以省略伴生對象的名稱,在這種情況下將使用名稱 Companion

class MyClass {
    companion object { }
}

val x = MyClass.Companion

請注意,即使伴生對象的成員看起來像其他語言的靜態成員,在運行時他們仍然是真實對象的實例成員,而且,例如還可以實現接口

interface Factory<T>{
 fun create(): T
}
class MyClass{
	companion object :Factory<MyClass>{
		override fun create(): MyClass = MyClass()
	}
}
val f:Factory<MyClass> = MyClass
  1. let函數
    使用let函數處理需要針對一個可null的對象統一做判空處理.
    let擴展函數的實際上是一個作用域函數,當你需要去定義一個變量在一個特定的作用域範圍內,let函數的是一個不錯的選擇.

object.let{
   it.todo()//在函數體內使用it替代object對象去訪問其公有的屬性和方法
   ...
}

//另一種用途 判斷object爲null的操作
object?.let{//表示object不爲null的條件下,纔會去執行let函數體
   it.todo()
}
//具體的使用例子
 fun setEmptyView(layoutResId: Int) {
        weakRecyclerView.get()?.let {
            val view = LayoutInflater.from(it.context).inflate(layoutResId, it, false)
            setEmptyView(view)
        }
    }
  1. varval 的唯一區別在於 var 既有 getter 又有 setter,val 只有 getter 沒有 setter
var a = 3
// var a: Int = 3
// 省略可推斷類型.

var b = 3
    // Warning: Redundant setter.
    get() = field
    // Warning: Redundant setter.
    set(value) {
        field = value
    }

// 編譯錯誤: Property must be initialized or be abstract.
// var c: Int

// 編譯錯誤: Property must be initialized.
// var d
//     get() = 3

val e
    get() = 3

var f
    get() = 3
    // Warning: Redundant setter.
    set(value) {}

val 屬性沒有 setter,就像 private val a = 0 的屬性與 Java 中的 private final 字段完全相同。
幕後字段 field,用來在 getter 和 setter 中訪問當前屬性,相當於 Java 中的 private 字段。
一定條件下屬性可以不賦予初始化值,對應在 Java 中不會生成字段,只會生成 getter 和 setter
收錄於這個人的博客

  1. 關鍵字with
    它是將某對象作爲函數的參數,在函數塊內可以通過 this 指代該對象返回值爲函數塊的最後一行或指定return表達式。可以看出with函數是接收了兩個參數,分別爲T類型的對象receiver和一個lambda函數塊.
fun main(args: Array<String>) {
    val user = User("帶哥", 32, "110911")

    val result = with(user) {
        println("my name is $name, I am $age years old, my phone number is $phoneNum")
        110
    }
    println("result: $result")
}

//java
 public static final void main(@NotNull String[] args) {
      User user = new User("帶哥", 32, "110911");
      String var4 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + 		   user.getPhoneNum();
      System.out.println(var4);
      int result = 110;
      String var3 = "result: " + result;
      System.out.println(var3);
   }
  1. run函數
    它彌補了let函數在函數體內必須使用it參數替代對象,在run函數中可以像with函數一樣可以省略,直接訪問實例的公有屬性和方法,另一方面它彌補了with函數傳入對象判空問題,在run函數中可以像let函數一樣做判空處理.
fun main(args: Array<String>) {
    val user = User("帶哥", 32, "110911")

    val result = user.run {
        println("my name is $name, I am $age years old, my phone number is $phoneNum")
        110
    }
    println("result: $result")
}
  1. apply關鍵字
    是一個擴展函數,把this作爲參數傳遞,它返回this(即它本身).可以從下面的例子看到.
class User(val name: String, val age: Int, val phoneNum: String)

fun main(args: Array<String>) {
    val user = User("hub", 11, "123123123")

    val result = user.apply {
        println("my name is $name, I am $age years old, my phone number is $phoneNum")
    }
    println("result: $result")
}

//output
//my name is hub, I am 11 years old, my phone number is 123123123
//result: User@48140564

//實際運用中

// 正常方法
fun createInstance(args: Bundle) : MyFragment {
    val fragment = MyFragment()
    fragment.arguments = args
    return fragment
}
// 改進方法
fun createInstance(args: Bundle) 
              = MyFragment().apply { arguments = args }
  1. also
    T.let返回不同類型的值,而T.also返回T本身即this.
class User(val name: String, val age: Int, val phoneNum: String)

fun main(args: Array<String>) {
    val user = User("max", 11, "123123123")
//注意打印加花括號,否則打印的是地址
//使用it還代替this
    val result = user.also {
        println("my name is ${it.name}, I am ${it.age} years old, my phone number is ${it.phoneNum}")
    }
    println("result: $result")
}

最後我們看看這些函數直接的區別.圖片來自這裏.

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章