一、本文概要
本文是對<<Kotlin in Action>>
的學習筆記,如果需要執行相應的程式碼可以訪問線上環境 try.kotlinlang.org,這部分的思維導圖為:
二、在 kotlin 中建立集合
在kotlin
中,建立HashSet
、ArrayList
和HashMap
的方法如下:
Java
集合類:
這麼做的原因,是因為使用標準的Java
集合使kotlin
可以更容易地與Java
程式碼互動。當從Kotlin
呼叫Java
函式的時候,不用轉換它的集合類來匹配Java
的類,反之亦然。
在這些集合物件上,我們除了可以使用Java
當中定義的基本函式以外,還可以使用kotlin
提供的擴充套件方法,例如下面的last
和max
:
三、讓函式更好呼叫
下面,我們定義一個函式,它的作用的是列印集合當中的元素,並指定元素之間新增分隔符、字首和字尾:
執行結果為:3.1 命名引數
在上面的例子中,我們指定了分隔符、字首和字尾三個引數,但是對於這個函式的使用者來說,如果不去看這些函式的宣告,很難看出這些String
型別的含義,這時候就可以使用 命名引數 的方法來呼叫,這有兩點好處:
- 增加函式的可讀性
- 以想要的順序指定需要的引數
下面,我們使用命名引數,並在不改變函式定義的情況下,改變傳入引數的順序,也可以得到和上面相同的執行結果:
對於命名引數,有以下幾點需要注意:
- 如果在呼叫一個函式時,指明瞭一個引數的名稱,那它之後的所有引數都要表明名稱。
- 當呼叫
Java
函式時,不能使用命名引數。
3.2 預設引數值
在kotlin
中,可以在宣告函式的時候,指定引數的預設值,這樣就可以避免建立過載的函式,例如上面的例子,我們可以在 定義函式 時,指定三個String
的預設值,而在 呼叫函式 的時候,如果沒有傳遞這些引數,那麼將會採用預設值:
- 如果使用常規的呼叫語法時,必須按照函式宣告中定義的引數順序來給定引數,可以省略的只有排在末尾的引數。
- 如果使用命名引數,可以省略中間的一些引數,也可以以你想要的任意順序只給定你需要的引數,例如我們只修改字首和字尾,分隔符仍然採用預設值: 執行結果為:
3.3 頂層函式和屬性
在Java
中,所有的程式碼都需要寫作類的函式,但是在專案中,很多程式碼並不能歸屬到類中,這時候我們一般會定義一個xxUtils
類,並在其中宣告static
的靜態方法。
在kotlin
中,我們可以把這些函式直接放到程式碼檔案的頂層,不用從屬於任何的類,這些放在檔案頂層的函式仍然是包內的成員,如果你需要從包外訪問它,則需要import
,但不再需要額外包一層。
3.3.1 在 Java 中呼叫頂層函式
如果我們想要在Java
中呼叫這些頂層函式,則需要通過Kotlin
根據包含函式的檔案的名稱生成的類,例如我們有兩個檔案
KotlinMethod.kt
:
fun kotlinFunc() {}
複製程式碼
JavaCallKotlin.java
:
public class JavaCallKotlin {
public JavaCallKotlin() {
KotlinMethodKt.kotlinFunc();
}
}
複製程式碼
前者包含一個頂層函式,那麼在Java
中,就會根據該檔名生成一個{檔名}Kt
的型別,再通過這個類來呼叫這個頂層函式。
如果不想使用預設的類名,可以在.kt
檔案的開頭加上@file:JvmName("類名")
的註解。
3.3.2 在 Java 中呼叫頂層屬性
和函式一樣,屬性也可以放到檔案的頂層。預設情況下,頂層屬性和其他任意的屬性一樣,是通過訪問器暴露給Java
使用的(如果是val
就只有一個getter
,如果是var
就對應getter
和setter
)。如果想要把一個常量以public static final
的屬性暴露給Java
,可以使用const
來修飾它。
package com.demo.lizejun.kotlinsample.chapter1
//不可變。
val kotlinVal = "kotlinValue"
//可變。
var kotlinVar = "kotlinVariable"
//常量。
const val kotlinConst = "kotlinConst"
//頂層函式。
fun kotlinFunc() {}
複製程式碼
在Java
中,分別通過以下幾種方式來訪問或者修改這幾個頂層屬性:
package com.demo.lizejun.kotlinsample.chapter3;
import com.demo.lizejun.kotlinsample.chapter1.KotlinMethodKt;
public class JavaCallKotlin {
public JavaCallKotlin() {
KotlinMethodKt.kotlinFunc();
//不可變。
KotlinMethodKt.getKotlinVal();
//可變。
KotlinMethodKt.setKotlinVar("newKotlinVar");
KotlinMethodKt.getKotlinVar();
//常量。
String kotlinConst = KotlinMethodKt.kotlinConst;
}
}
複製程式碼
四、擴充套件函式和屬性
擴充套件函式 其實是一個類的成員函式,只不過它定義在類的外面,我們所需要做的,就是在宣告擴充套件函式的時候,把需要擴充套件的類或者介面的名稱,放到它的前面,用來呼叫這個擴充套件函式的物件,就叫做 接收者物件。
在擴充套件函式中,可以直接訪問被擴充套件的類的其它方法和屬性,就好像是在這個類自己的方法中訪問它們的一樣,但是擴充套件函式不允許你打破它的封裝性,擴充套件函式不能訪問私有的或者是受保護的成員。
4.1 擴充套件函式的定義和使用
下面我們給String
類新增一個擴充套件函式,返回它的最後一個字元:
4.2 在 Java 中使用擴充套件函式
如果需要在Java
中呼叫擴充套件函式,那麼把接收者物件作為第一個引數傳進去即可:
//接收者物件作為第一個引數。
char lastChar = KotlinMethodKt.last("Kotlin");
複製程式碼
4.3 不能重寫的擴充套件函式
這裡假設我們有兩個類,View
和Button
,其中Button
繼承於View
,我們給這兩個類都新增一個名為showOff
的擴充套件函式。
Button
的物件,但是Kotlin
會把擴充套件函式當做靜態函式來對待,因此 擴充套件函式不存在重寫。
4.4 擴充套件屬性
擴充套件屬性提供了一種方法,用來擴充套件類的API
,可以用來訪問屬性,用的是屬性語法而不是函式的語法,儘管他們被稱為屬性,但它們沒有任何狀態,因為沒有合適的地方來儲存它們。
現在,我們給StringBuilder
新增一個可讀寫的屬性lastChar
,用於獲取或者改變它的最後一個字元,包含以下幾點要素:
- 擴充套件屬性以
var/val
關鍵字開頭 - 指定擴充套件屬性的名字、型別
- 如果是
var
那麼提供get()/set(value : T)
方法,而如果是val
屬性,那麼提供get()
方法,其中T
為屬性的型別。
五、可變引數、中綴呼叫和庫的支援
5.1 可變引數
使用關鍵字 vararg,可以用來宣告一個函式將有可能有任意數量的引數,下面例子中,我們定義一個可以接收可變數量Int
型別的函式,之後和在Java
中一樣,它會被轉換為[I
的整型陣列型別:
*
操作符進行解包:
執行結果為:
5.2 中綴呼叫
中綴呼叫 不是特殊的內建結構,而是一種特殊的函式呼叫。在中綴呼叫中,沒有新增額外的分隔符,函式名稱是直接放在目標物件名稱和引數之間。例如我們宣告瞭一個to
函式。
//一般函式呼叫。
1.to("One")
//中綴呼叫。
1 to "One"
複製程式碼
中綴呼叫可以與 只有一個引數的函式 一起使用,無論是普通的函式還是擴充套件函式,要允許使用中綴符號呼叫函式,需要使用infix
修飾符來標記它,下面是一個建立Person
的函式,我們採用了擴充套件函式的方法,這裡的Any
是Kotlin
中所有類的父類,和Java
中的Object
相同:
六、字串處理
6.1 分割字串
在Java
中,我們會使用split
來分割字串,它接受一個正規表示式作為引數。但是當我們想分割"."
時,會得到一個空的陣列,因為.
號表示任何字元的正規表示式。
而在kotlin
中,它提供了一個接受Regex
型別的過載函式,這樣確保了當有一個字串傳遞給這些函式的時候,不會被當做正規表示式,我們可以使用擴充套件函式toRegex
將字串轉換為正規表示式。
6.2 正規表示式
假設有下面這個字串
/Users/yole/kotlin-book/chapter.adoc
複製程式碼
我們需要通過這個字串獲取到chapter.adoc
的目錄、檔名和副檔名,如果使用擴充套件函式,那麼程式碼如下:
.
模式從字串的一開始就進行匹配,所以第一組(.+)
包含最後一個斜線之前的子串,這和子串包含所有前面的斜線,因為它們匹配”任何字元“的模式。- 第二組包含最後一個點之前的子串
- 第三組包含剩餘部分
七、區域性函式
在Java
的一個函式當中,有可能存在重複程式碼,例如在註冊模組中,可能需要校驗輸入的多個欄位是否有效,那麼校驗的邏輯就可以提取出一個函式,而Kotlin
就提供了一種方法:可以在函式中巢狀這些提取的函式,區域性函式定義方式和普通函式是相同的。
更多文章,歡迎訪問我的 Android 知識梳理系列:
- Android 知識梳理目錄:www.jianshu.com/p/fd82d1899…
- 個人主頁:lizejun.cn
- 個人知識總結目錄:lizejun.cn/categories/