1拇厢、Kotlin 中沒有基礎(chǔ)數(shù)據(jù)類型,都是用它的包裝類型辈末,他的包裝類型是一個(gè)類愚争,我們可以使用類里面很多有用的方法映皆。
2、kotlin訪問修飾符
訪問修飾符可以修飾類轰枝,也可以修飾類的成員捅彻。
(1)類訪問修飾符
(2)類成員訪問修飾符
有幾點(diǎn)需要講一下:
? ? ? ? ? ?1、 internal 修飾符是 Kotlin 獨(dú)有而 Java 中沒有的鞍陨;
? ? ? ? ? ?2步淹、protected 修飾符在Kotlin和Java中的異同點(diǎn)
? ? ? ? ? ? ? ? ?· protected 修飾類,在 Java 中該類只能被同包名下的類訪問诚撵,Kotlin 中就算是同包名的類也不能訪問 protected 修飾的類缭裆。
? ? ? ? ? ? ? ? ?·?protected 修飾類成員,在 Java 中可以被同包名或子類可訪問寿烟;在 Kotlin 中只能被子類訪問澈驼。
訪問修飾符小結(jié):
(1)如果不寫訪問修飾符,在 Java 中是 default 修飾符 (package-private)筛武;在 Kotlin 中是 public 的
(2)internal 訪問修飾符是 Kotlin 獨(dú)有缝其,只能在模塊內(nèi)能訪問的到
(3)protected 修飾類的時(shí)候,不管是 Java 和 Kotlin 都只能放到內(nèi)部類上
(4)在 Kotlin 中徘六,要繼承 protected 類内边,要么子類在同一內(nèi)部類名下;要么該類的的外部類和 protected 類的外部類有繼承關(guān)系
(5)在 Kotlin 中待锈,繼承 protected 類假残,子類也必須是 protected 的
(6)在 Kotlin 中,對(duì)于 protected 修飾符炉擅,去掉了同包名能訪問的特性
(7)如果某個(gè) Kotlin 類能夠被繼承,需要 open 關(guān)鍵字阳惹,默認(rèn)是 final 的
3谍失、新建 bean 類的時(shí)候,常常需要聲明 equals莹汤、hashCode快鱼、toString 等方法,我們需要寫很多代碼纲岭。在 Kotlin 中抹竹,只需要在聲明類的時(shí)候前面加 data 關(guān)鍵字就可以完成這些功能。
4止潮、kotlin 新建內(nèi)部類,例如:
class OuterClass {
? ? //在 Kotlin 中內(nèi)部類默認(rèn)是靜態(tài)的窃判,不持有外部類的引用
? ? class InnerStaticClass{
? ? }
? ? //如果要聲明非靜態(tài)的內(nèi)部類,需要加上 inner 關(guān)鍵字
? ? inner class InnerClass{
? ? }
}
編譯后代碼如下:
class OuterClass {
? public static final class InnerStaticClass {
? }
? public final class InnerClass {
? }
}
5喇闸、companion object
companion object?稱之為伴生對(duì)象袄琳,伴生體里面放的是一些靜態(tài)成員:如靜態(tài)常量询件、靜態(tài)變量、靜態(tài)方法唆樊。例如
companion object {
? ? //公有常量
? ? const val FEMALE: Int = 0
? ? const val MALE: Int = 1
? ? //私有常量
? ? val GENDER: Int = FEMALE
? ? //私有靜態(tài)變量
? ? var username: String = "chiclaim"
? ? //靜態(tài)方法
? ? fun run() {
? ? ? ? println("run...")
? ? }
}
6宛琅、Kotlin 中的 Interface
在 Java8 之前,Interface 中是不能包含有方法體的方法和屬性逗旁,只能包含抽象方法和常量嘿辟。
在 Kotlin 中的接口在定義的時(shí)候可以包含有方法體的方法,也可以包含屬性片效。例如
//聲明一個(gè)接口红伦,包含方法體的方法 plus 和一個(gè)屬性 count
interface InterfaceTest {
? ? var count: Int
? ? fun plus(num: Int) {
? ? ? ? count += num
? ? }
}
//實(shí)現(xiàn)該接口
class Impl : InterfaceTest {
? ? //必須要覆蓋 count 屬性
? ? override var count: Int = 0
}
7、lambda 表達(dá)式
在 Java8 之前堤舒,lambda 表達(dá)式在 Java 中都是沒有的色建。
(1)lambda 總是放在一個(gè)花括號(hào)里 ({})
(2)箭頭左邊是 lambda 參數(shù) (lambda parameter)
(3)箭頭右邊是 lambda 體 (lambda body)
8、高階函數(shù)
如果某個(gè)函數(shù)是以另一個(gè)函數(shù)作為參數(shù)或者返回值是一個(gè)函數(shù)舌缤,我們把這樣的函數(shù)稱之為高階函數(shù)箕戳。
例如:
//Kotlin library filter function
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
//調(diào)用高階函數(shù) filter,直接傳遞 lambda 表達(dá)式
list.filter { person ->
? ? person.age > 18
}
function type:
名稱 : (參數(shù)) -> 返回值類型
(1)冒號(hào)左邊是?function type?的名字
(2)冒號(hào)右邊是參數(shù)
(3)尖括號(hào)右邊是返回值
比如:predicate: (T) -> Boolean?predicate 就是名字国撵,T 泛型就是參數(shù)陵吸,Boolean 就是返回值類型
高階函數(shù)是以另一個(gè)函數(shù)作為參數(shù)或者其返回值是一個(gè)函數(shù),也可以說高階函數(shù)參數(shù)是?function type?或者返回值是?function type
在調(diào)用高階函數(shù)的時(shí)候介牙,我們可以傳遞 lambda壮虫,這是因?yàn)榫幾g器會(huì)把 lambda 推導(dǎo)成?function type
9、高階函數(shù) let环础、with囚似、apply、run(
內(nèi)聯(lián)函數(shù)
) 總結(jié)
(1)let 函數(shù)一般用于判斷是否為空
//let 函數(shù)的定義
public inline fun <T, R> T.let(block: (T) -> R): R {
? ? return block(this)
}
//let 的使用
message?.let { //lambda參數(shù)it是message
? ? val result = it.substring(1)
? ? println(result)
}
(2)?with 是全局函數(shù)线得,apply 是擴(kuò)展函數(shù)饶唤,其他的都一樣
(3)run 函數(shù)的 lambda 是一個(gè)帶有接受者的 lambda,而 let 不是贯钩,除此之外功能差不多
10募狂、Kotlin泛型
Java 泛型:不變性 (invariance)、協(xié)變性 (covariance)角雷、逆變性 (contravariance)
Kotlin泛型:協(xié)變祸穷、逆變
Kotlin 泛型擦除和具體化
Kotlin 和 Java 的泛型只在編譯時(shí)有效,運(yùn)行時(shí)會(huì)被擦除 (type erasure)勺三。例如下面的代碼就會(huì)報(bào)錯(cuò):
//Error: Cannot check for instance of erased type: T
//fun <T> isType(value: Any) = value is T
Kotlin 提供了一種泛型具體化的技術(shù)雷滚,它的原理是這樣的:
我們知道泛型在運(yùn)行時(shí)會(huì)擦除,但是在 inline 函數(shù)中我們可以指定泛型不被擦除吗坚,
因?yàn)?inline 函數(shù)在編譯期會(huì) copy 到調(diào)用它的方法里揭措,所以編譯器會(huì)知道當(dāng)前的方法中泛型對(duì)應(yīng)的具體類型是什么胯舷,
然后把泛型替換為具體類型,從而達(dá)到不被擦除的目的绊含,在 inline 函數(shù)中我們可以通過 reified 關(guān)鍵字來標(biāo)記這個(gè)泛型在編譯時(shí)替換成具體類型
如下面的代碼就不會(huì)報(bào)錯(cuò)了:
inline fun <reified T> isType(value: Any) = value is T
11桑嘶、Kotlin 集合
Kotlin 中的集合底層也是使用 Java 集合框架那一套。在上層又封裝了一層?可變集合?和?不可變集合?接口躬充。
(1)聲明可變集合
(2)聲明不可變集合
Kotlin 集合常用的 API
1) all逃顶、any、count充甚、find以政、firstOrNull、groupBy 函數(shù)
2) filter伴找、map盈蛮、flatMap、flatten 函數(shù)
延遲集合操作之 Sequences(Sequence就是就是為了避免創(chuàng)建多余的集合的問題技矮。)
val list = listOf<Person>(Person("chiclaim", 18), Person("yuzhiqiang", 15),
? ? ? ? Person("johnny", 27), Person("jackson", 190),
? ? ? ? Person("pony", 85))
//把 filter 函數(shù)放置前面抖誉,可以有效減少 map 函數(shù)的調(diào)用次數(shù)
list.asSequence().filter { person ->
? ? println("filter---> ${person.name} : ${person.age}")
? ? person.age > 20
}.map { person ->
? ? println("map----> ${person.name} : ${person.age}")
? ? person.age
}.forEach {
? ? println("---------符合條件的年齡 $it")
}
Sequence 的原理圖如下所示:
對(duì) Sequence 做一個(gè)小結(jié):
(1)如果集合的數(shù)據(jù)量很大啊,可以使用集合操作的延遲 Sequence
(2)Sequence 的 filter衰倦、map 等擴(kuò)展還是是一個(gè)非 inline 的高階函數(shù)
(3)集合的 Sequence 只有調(diào)用 forEach袒炉、toList 等操作,才會(huì)觸發(fā)對(duì)集合的操作樊零。有點(diǎn)類似 RxJava我磁。
12、Koltin 和 Java 交互的一些問題
1) Kotlin 和 Java 交互上關(guān)于空的問題
2) 關(guān)于 Kotlin 基本類型初始化問題
3) Kotlin 泛型具體化無法被 Java 調(diào)用
? ? 如果我們定義了一個(gè) inline 函數(shù)驻襟,且使用了泛型具體化夺艰,該方法不能被 Java 調(diào)用。反編譯后發(fā)現(xiàn)該方法是私有的沉衣。只能Kotlin 代碼自己調(diào)用郁副。
4) Kotlin 間接訪問 Java default class