本文是對<<Kotlin in Action>>
的學習筆記,若是須要運行相應的代碼能夠訪問在線環境 try.kotlinlang.org,這部分的思惟導圖爲: java
在kotlin
中,建立HashSet
、ArrayList
和HashMap
的方法以下: 正則表達式
Java
集合類:
這麼作的緣由,是由於使用標準的
Java
集合使
kotlin
能夠更容易地與
Java
代碼交互。當從
Kotlin
調用
Java
函數的時候,不用轉換它的集合類來匹配
Java
的類,反之亦然。
在這些集合對象上,咱們除了可使用Java
當中定義的基本函數之外,還可使用kotlin
提供的擴展方法,例以下面的last
和max
: 數組
下面,咱們定義一個函數,它的做用的是打印集合當中的元素,並指定元素之間添加分隔符、前綴和後綴: bash
運行結果爲:在上面的例子中,咱們指定了分隔符、前綴和後綴三個參數,可是對於這個函數的使用者來講,若是不去看這些函數的聲明,很難看出這些String
類型的含義,這時候就可使用 命名參數 的方法來調用,這有兩點好處:函數
下面,咱們使用命名參數,並在不改變函數定義的狀況下,改變傳入參數的順序,也能夠獲得和上面相同的運行結果: 學習
對於命名參數,有如下幾點須要注意:ui
Java
函數時,不能使用命名參數。在kotlin
中,能夠在聲明函數的時候,指定參數的默認值,這樣就能夠避免建立重載的函數,例如上面的例子,咱們能夠在 定義函數 時,指定三個String
的默認值,而在 調用函數 的時候,若是沒有傳遞這些參數,那麼將會採用默認值: spa
在Java
中,全部的代碼都須要寫做類的函數,可是在項目中,不少代碼並不能歸屬到類中,這時候咱們通常會定義一個xxUtils
類,並在其中聲明static
的靜態方法。3d
在kotlin
中,咱們能夠把這些函數直接放到代碼文件的頂層,不用從屬於任何的類,這些放在文件頂層的函數仍然是包內的成員,若是你須要從包外訪問它,則須要import
,但再也不須要額外包一層。code
若是咱們想要在Java
中調用這些頂層函數,則須要經過Kotlin
根據包含函數的文件的名稱生成的類,例如咱們有兩個文件
KotlinMethod.kt
:fun kotlinFunc() {}
複製代碼
JavaCallKotlin.java
:public class JavaCallKotlin {
public JavaCallKotlin() {
KotlinMethodKt.kotlinFunc();
}
}
複製代碼
前者包含一個頂層函數,那麼在Java
中,就會根據該文件名生成一個{文件名}Kt
的類型,再經過這個類來調用這個頂層函數。
若是不想使用默認的類名,能夠在.kt
文件的開頭加上@file:JvmName("類名")
的註解。
和函數同樣,屬性也能夠放到文件的頂層。默認狀況下,頂層屬性和其餘任意的屬性同樣,是經過訪問器暴露給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;
}
}
複製代碼
擴展函數 實際上是一個類的成員函數,只不過它定義在類的外面,咱們所須要作的,就是在聲明擴展函數的時候,把須要擴展的類或者接口的名稱,放到它的前面,用來調用這個擴展函數的對象,就叫作 接收者對象。
在擴展函數中,能夠直接訪問被擴展的類的其它方法和屬性,就好像是在這個類本身的方法中訪問它們的同樣,可是擴展函數不容許你打破它的封裝性,擴展函數不能訪問私有的或者是受保護的成員。
下面咱們給String
類添加一個擴展函數,返回它的最後一個字符:
若是須要在Java
中調用擴展函數,那麼把接收者對象做爲第一個參數傳進去便可:
//接收者對象做爲第一個參數。
char lastChar = KotlinMethodKt.last("Kotlin");
複製代碼
這裏假設咱們有兩個類,View
和Button
,其中Button
繼承於View
,咱們給這兩個類都添加一個名爲showOff
的擴展函數。
Button
的對象,可是
Kotlin
會把擴展函數當作靜態函數來對待,所以
擴展函數不存在重寫。
擴展屬性提供了一種方法,用來擴展類的API
,能夠用來訪問屬性,用的是屬性語法而不是函數的語法,儘管他們被稱爲屬性,但它們沒有任何狀態,由於沒有合適的地方來存儲它們。
如今,咱們給StringBuilder
添加一個可讀寫的屬性lastChar
,用於獲取或者改變它的最後一個字符,包含如下幾點要素:
var/val
關鍵字開頭var
那麼提供get()/set(value : T)
方法,而若是是val
屬性,那麼提供get()
方法,其中T
爲屬性的類型。使用關鍵字 vararg,能夠用來聲明一個函數將有可能有任意數量的參數,下面例子中,咱們定義一個能夠接收可變數量Int
類型的函數,以後和在Java
中同樣,它會被轉換爲[I
的整型數組類型:
*
操做符進行解包:
運行結果爲:
中綴調用 不是特殊的內置結構,而是一種特殊的函數調用。在中綴調用中,沒有添加額外的分隔符,函數名稱是直接放在目標對象名稱和參數之間。例如咱們聲明瞭一個to
函數。
//通常函數調用。
1.to("One")
//中綴調用。
1 to "One"
複製代碼
中綴調用能夠與 只有一個參數的函數 一塊兒使用,不管是普通的函數仍是擴展函數,要容許使用中綴符號調用函數,須要使用infix
修飾符來標記它,下面是一個建立Person
的函數,咱們採用了擴展函數的方法,這裏的Any
是Kotlin
中全部類的父類,和Java
中的Object
相同:
在Java
中,咱們會使用split
來分割字符串,它接受一個正則表達式做爲參數。可是當咱們想分割"."
時,會獲得一個空的數組,由於.
號表示任何字符的正則表達式。 而在kotlin
中,它提供了一個接受Regex
類型的重載函數,這樣確保了當有一個字符串傳遞給這些函數的時候,不會被當作正則表達式,咱們可使用擴展函數toRegex
將字符串轉換爲正則表達式。
假設有下面這個字符串
/Users/yole/kotlin-book/chapter.adoc
複製代碼
咱們須要經過這個字符串獲取到chapter.adoc
的目錄、文件名和擴展名,若是使用擴展函數,那麼代碼以下:
.
模式從字符串的一開始就進行匹配,因此第一組(.+)
包含最後一個斜線以前的子串,這和子串包含全部前面的斜線,由於它們匹配」任何字符「的模式。在Java
的一個函數當中,有可能存在重複代碼,例如在註冊模塊中,可能須要校驗輸入的多個字段是否有效,那麼校驗的邏輯就能夠提取出一個函數,而Kotlin
就提供了一種方法:能夠在函數中嵌套這些提取的函數,局部函數定義方式和普通函數是相同的。