《Kotlin 實戰》第3章筆記
Kotlin 實戰筆記
集合
Kotlin 的集合分為可變集合和不可變集合,不可變集合類似 Java 中的 List、Set、Map,而可變集合如 MutableList
val set1 = setOf(1, 2, 3) val set2 = hashSetOf(1, 2, 3) val set3 = mutableSetOf(1, 2, 3) val list1 = listOf(1, 2, 3) val list2 = arrayListOf(1, 2, 3) val list3 = mutableListOf(1, 2, 3) val map1 = mapOf(1 to "one", 2 to "two", 3 to "three") val map2 = hashMapOf(1 to "one", 2 to "two", 3 to "fifty-three") val map3 = mutableMapOf(1 to "one", 2 to "two", 3 to "three")
預設引數值
Kotlin 中宣告的函式可以指定預設的引數值:
fun <T>joinToString( collection: Collection<T>, //下面三個引數都有預設值 separator: String = "", prefix: String = "", postfix: String = "" ) {} fun main(args:Array<String>) { val list = listOf(1, 2, 3) //有預設值的引數可以不傳值 joinToString(list) joinToString(list, "") joinToString(list, "", "") joinToString(list, "", "", "") }
上面這個例子中joinToString(list, "", "", "")
的呼叫可以做得更優雅:
//呼叫時標明引數的名稱 joinToString(list, separator = "", prefix = "", postfix = "")
注意:在呼叫一個函式時,如果指定了一個引數名稱,那麼之後的所有引數都需要標明名稱:
//正確示例 joinToString(list, "", prefix = "", postfix = "") //錯誤示例 joinToString(list, separator = "", "", postfix = "")
頂層函式和屬性
在 Kotlin 中可以直接在一個 Kotlin 檔案宣告函式和屬性,不必像 Java 那樣必須在類中才能宣告屬性和方法。
//檔名:KotlinTest.kt package com.itscoder.ljuns.practise.kotlin.chapter3 //類似於 Java 中 private static final test1 = 0; val test1: Int = 0 //類似於 Java 中 public static final test2 = 0; const val test2: Int = 0 //類似於 Java 中 private static int test3; var test3: Int = 0 //類似於 Java 中 public static final void test() {} fun test() {}
看看編譯後生成的檔案:
//類名就是檔名 public final class KotlinTestKt{ private static final int test1 = 0; public static final int test2 = 0; private static int test3; public static final int getTest1() { return test1; } public static final int getTest3() { return test3; } public static final void setTest3(int var0) { test3 = var0; } public static final void test() { } }
拓展函式和屬性
拓展函式
Kotlin 可以在不修改原始碼的情況下給原有的類新增函式,即拓展函式。
新建一個 kotlin 檔案 StringUtil.kt:
/** * 給 String 類拓展了一個 lastChar() 的函式,拓展函式名可以和成員函式名相同 * String:接收者型別,即要拓展的類或介面 * this:接收者物件,可省略 */ fun String.lastChar(): Char = this.get(this.length - 1) // 省略 this fun String.lastChar(): Char = get(length - 1)
上面程式碼給 String 這個類拓展了一個返回最後一個字元的函式,用法和其他普通函式一樣:
print("Kotlin".lastChar())
編譯後生成的 Java 檔案:
public final class StringUtilKt{ public static final char lastChar(@NotNull String $receiver){ Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); return $receiver.charAt($receiver.length() - 1); } }
所以,如果是在 Java 中呼叫的話就是這樣:
System.out.println(StringUtilKt.lastChar("Java"));
此外,拓展函式不能被重寫,舉個例子:
open class View{ open fun click() = println("view click") } // 繼承 View open class Button:View() { // 重寫 click() override fun click() = println("button click") } // 分別有拓展函式 fun View.showOff() = println("I`m a View") fun Button.showOff() = println("I`m a Button") fun main(args:Array<String>) { val view: View = Button() view.click() // 列印結果:button click // 呼叫拓展函式時變數型別由靜態型別決定,即 View view.showOff() // 列印結果:I`m a View View().showOff() // 列印結果:I`m a View Button().showOff() // 列印結果:I`m a Button }
注意:如果一個類的成員函式和拓展函式有相同的函式名,成員函式會被優先使用
拓展屬性
和拓展屬性類似,可以給已存在的類新增拓展屬性。
在拓展函式的例子中新增拓展屬性:
/** * 給 String 類拓展了一個 lastChar 的屬性,拓展屬性名可以和成員屬性名相同 * 必須提供對應的 gettr()、setter() 方法 */ val String.lastChar: Char get() = get(length - 1)
可變引數
Kotlin 中可變引數的定義和使用與 Java 有點不同:
// 用 vararg 來宣告可變引數 fun test(vararg value: String) = println(value.size) fun main(args:Array<String>) { // 這種呼叫和 Java 中一樣 test("one", "two", "three") // Kotlin 不允許傳入一個數組,要加一個特殊符號 * test(*args) }
看看編譯後的檔案:
public static final void test(@NotNull String... value){ Intrinsics.checkParameterIsNotNull(value, "value"); int var1 = value.length; System.out.println(var1); } public static final void main(@NotNull String[] args){ Intrinsics.checkParameterIsNotNull(args, "args"); test("one", "two", "three"); test((String[])Arrays.copyOf(args, args.length)); }
所以如果在 Java 中去呼叫 Kotlin 定義的可變引數,使用方式還是和以前一樣的。