這篇文章簡(jiǎn)單梳理下Kotlin的語(yǔ)法糖踊跟。
一阁危、內(nèi)置類(lèi)型
1.1 基本類(lèi)型
- 整數(shù)類(lèi)型:Byte、Short状飞、Int和Long毫胜,Int是默認(rèn)類(lèi)型
- 浮點(diǎn)類(lèi)型:Float和Double书斜,Double是默認(rèn)類(lèi)型
- 字符類(lèi)型:Char
- 布爾類(lèi)型:Boolean
增加無(wú)符號(hào)類(lèi)型:UByte、UShort酵使、Uint荐吉、ULong
Kotlin數(shù)據(jù)基本類(lèi)型均為對(duì)象類(lèi)型。
Unit 等同于void口渔,Any等同于Object样屠,這是kotlin與java區(qū)別的地方。
- var 變量
- val 只讀變量 //作為局部變量等價(jià)于java final常量缺脉,而作為全局變量可以配置get方法痪欲,return值可以不同。
- const val 全局靜態(tài)常量
類(lèi)型自動(dòng)推導(dǎo)
var b:Int =2 推導(dǎo)為:var a = 2
注:不能直接聲明var a攻礼,要么初始化var a = 2业踢,要么聲明好類(lèi)型var a : Int
強(qiáng)制類(lèi)型轉(zhuǎn)換
var l = 1L
var d = l.toDouble() //這里不像java,類(lèi)型轉(zhuǎn)換必須主動(dòng)調(diào)用toXXX()
字符串比較:
== 比較內(nèi)容 equals
===比較地址 ==
字符串模版
val c = "world"
println("hello $c”)
Raw字符串
val n = """
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body>
<div id="container">
<H1>Hello World</H1>
</div>
</body>
</html>
""".trimIndent()//trim掉公共的空白
別名
typealias ArrayList<E> = java.util.ArrayList<E>
空類(lèi)型安全
操作符 | 描述 |
---|---|
? | 可空操作符礁扮,聲明可空類(lèi)型陨亡。 var str:String? = "aaa" |
?. | 安全調(diào)用操作符,為空返回null深员。str?.length |
?.let{} | ?.與let一起使用,用于遍歷集合時(shí)蛙埂,則忽略null值倦畅,只對(duì)非空值執(zhí)行操作。 for (item in listWithNulls) { ? ? item?.let { println(it) } // 輸出 abc 并忽略 null } |
?: | Elvis操作符,檢查結(jié)果為空返回后面的值绣的。val a = b?.length ?: 0 |
!! | 非空斷言運(yùn)算符叠赐,將任何值轉(zhuǎn)換為非空類(lèi)型,若該值為空則拋出NPE屡江。 |
as? | 嘗試轉(zhuǎn)換成指定類(lèi)型芭概,如果嘗試轉(zhuǎn)換不成功則返回null。var b: Int ? = a as? Int |
filterNotNull | 過(guò)濾一個(gè)可空類(lèi)型元素集合中的非空元素惩嘉。val list: List<Int> = nullableList.filterNotNull() |
另外普調(diào)類(lèi)型與對(duì)應(yīng)的空類(lèi)型的繼承關(guān)系:
String 是String?的子類(lèi)
var x:String = “Hello”
var y:String? = “World”
x = y // 不行罢洲,編譯器報(bào)type mismatch錯(cuò)誤
y = x //可以
String! 為平臺(tái)類(lèi)型,無(wú)法判斷是否為空文黎,需要開(kāi)發(fā)者自己去做安全訪問(wèn)惹苗。
附:看類(lèi)型快捷鍵 shift+control+p
1.2 數(shù)組
IntArray //int[]
Array<Int> //Integer[] 對(duì)象類(lèi)型 Array<Person>
數(shù)組的創(chuàng)建
val c0 = intArrayOf(1, 2, 3, 4, 5) //int[] arr = {1,2,3,4,5}
val c1 = IntArray(5) // int[] arr = new int[5]
val c2 = Array<Int>(5,{it})// 第二個(gè)參數(shù)是方法類(lèi)型, init: (Int) -> T
數(shù)組的遍歷
for each:
for (e in c0) {
println(e)
}
c0.forEach {
println(it)
}
for i:
for (i in c0.indices) {
//i是對(duì)應(yīng)的index
println(c0[i])
if(1 in e){// 對(duì)應(yīng)元素是否在數(shù)組中耸峭,!in 對(duì)應(yīng)元素不在數(shù)組中
println(“1 exists in variable e"])
}
}
1.3 區(qū)間
區(qū)間
val intRange = 1..10 // [1, 10]
val charRange = 'a'..'z'
開(kāi)區(qū)間
val intRangeExclusive = 1 until 10 // [1, 10)
val charRangeExclusive = 'a' until 'z'
倒序區(qū)間
val intRangeReverse = 10 downTo 1 // [10, 9, ... , 1]
val charRangeReverse = 'z' downTo 'a'
步長(zhǎng)
val intRangeWithStep = 1..10 step 2
val charRangeWithStep = 'a'..'z' step 2
1.4 運(yùn)算符
直接查看官方文檔
https://kotlinlang.org/docs/reference/operator-overloading.html
二桩蓉、 集合
2.1 集合框架
這里一種寫(xiě)法就用java寫(xiě)法就行,區(qū)別就是不用new
var list = ArrayList<String>()
list.add("1")
println(list.get(0))
var map = HashMap<String,String>()
map.put("key","value")
println(map.get("key”))
也可以按標(biāo)準(zhǔn)kotlin寫(xiě)法:
val list = listOf(1, 2, 3)//不可變list(不能添加和刪除元素)
val mutableList = mutableListOf(1, 2, 3)//可變list
val arrays = mutableListOf<Int>()//僅僅初始化劳闹,沒(méi)有元素院究,必須指定泛型類(lèi)型
val map = mapOf( //不可變map
"a" to 1,
"b" to 2
)
val mutableMap = mutableMapOf( //可變map
"a" to 1,
"b" to 2
)
val maps = mutableMapOf<Int,String>()
list操作:
mutableList.add(4) //set
mutableList.forEach {
mutableList[2] = 5 //get
println(it)
}
map操作
mutableMap["c"] = 3//set
mutableMap["c"]//get
mutableMap.set("c", 3)//java式寫(xiě)法set
mutableMap.get("c")//get
同時(shí)注意:
add 操作可用 += 代替, 同理remove 為 -=
例如:mutableList += 4
這里單獨(dú)介紹下循環(huán)
for循環(huán)表達(dá)式
for(item in arrays){//item是每個(gè)元素
print(item)
}
for(i in arrays.indices){
print(array[i])
}
while與do..while這部分與java沒(méi)區(qū)別
2.2 集合變換與序列
2.2.1 集合的映射操作:filter洽瞬、map、flatMap
filter:保留滿(mǎn)足條件的元素
list.filter{it %2 == 0}
變換序列:list.asSequence().filter{it %2 == 0} //.asSequence()類(lèi)似java的 .streammap:集合中的所有元素意義映射新集合
list.map{it2+1}
變換序列:list.asSequence().map{it2+1}flatMap:集合中的所有元素意義映射新集合业汰,并合并這些集合得到新集合
list.flatMap{0 until it}.joinToString().let(::println)
.asSequence懶漢式操作案例:
val list = listOf(1, 2, 3, 4)
list.asSequence().filter {
println("filter:$it")
it % 2 == 0
}.map {
println("map:$it")
it * 2 + 1
}.forEach {
println("foreach:$it")
}
打印結(jié)果:
filter:1
filter:2
map:2
foreach:5
filter:3
filter:4
map:4
foreach:9
去掉.asSequence對(duì)比:
list.filter {
println("filter:$it")
it % 2 == 0
}.map {
println("map:$it")
it * 2 + 1
}.forEach {
println("foreach:$it")
}
打印結(jié)果:
filter:1
filter:2
filter:3
filter:4
map:2
map:4
foreach:5
foreach:9
這部分體會(huì)是有點(diǎn)類(lèi)似于rxjava
2.2.2 集合的聚合操作 sum伙窃、reduce、fold
sum 所有元素求和
reduce 將元素依次按規(guī)則聚合蔬胯,結(jié)果與元素類(lèi)型一致
fold 給定初始化值对供,將元素按規(guī)則聚合,結(jié)果與初始化值類(lèi)型一致
list.fold(StringBuilder()){
acc,i->acc.append(i)
}
三氛濒、表達(dá)式
3.1 if表達(dá)式
kotlin可以把if表達(dá)式的結(jié)果賦值給一個(gè)變量
val max = if (a > b) a else b
3.2 when表達(dá)式
when 將它的參數(shù)和所有的分支條件順序比較产场,直到某個(gè)分支滿(mǎn)足條件。
c = when (x) {
1 -> print("x等于1")
in 10..20 -> print(“x在區(qū)間10-20范圍內(nèi)")
else -> { //default
}
}
將條件轉(zhuǎn)移到分支
var x:Any = …
c = when{
x is String -> c = x.length
x == 1 -> c = 100
else -> c = 20
}
括號(hào)內(nèi)條件還能做賦值
c = when(var input = readLine()){ //since kotlin 1.3
null -> 0
else -> input.length
}
循環(huán)中才使用的返回與跳轉(zhuǎn)舞竿,高階函數(shù)forEach不能使用:
- return京景。默認(rèn)從最直接包圍它的函數(shù)或者匿名函數(shù)返回。
- break骗奖。終止最直接包圍它的循環(huán)确徙。
- continue。繼續(xù)下一次最直接包圍它的循環(huán)执桌。
3.3 try…catch表達(dá)式
c = try{
a/b
}catch(e:Exception){
e.printStackTrace()
0
}
3.4 Lambda表達(dá)式
使用:
func()
Lambda表達(dá)式定義:
Kotlin
Lambda表達(dá)式參數(shù)省略
val f1:Function1<Int,Unit> = {p ->
println(p)
}
轉(zhuǎn)為:
val f1:Function1<Int,Unit> = {
println(it)
}
3.5 SAM轉(zhuǎn)換
一個(gè)參數(shù)類(lèi)型問(wèn)只有一個(gè)方法的Java接口的Java方法調(diào)用時(shí)可用lambda表達(dá)式做轉(zhuǎn)換作為參數(shù)鄙皇。
val eventManager = EventManager()
//匿名內(nèi)部類(lèi):object:類(lèi)型
val onEvent = object:EventManager.OnEventListener{
override fun onEvent(event:Int){
println(“onEvent $event")
}
}
eventManager.addOnEventListener(onEvent)
eventManager.removeEventListener(onEvent)
四、函數(shù)
kotlin函數(shù)有自己的類(lèi)型仰挣,可以賦值伴逸、傳遞、并在合適的條件下調(diào)用
函數(shù)返回值支持類(lèi)型推導(dǎo)膘壶。
4.1 函數(shù)類(lèi)型:
4.2 函數(shù)的引用
變長(zhǎng)參數(shù):vararg
fun main(vararg args: String) {…}
4.3 多返回值
可以用Pair和Triple進(jìn)行包裝
Pair
val pair = "Hello" to "World"
val pair1 = Pair("Hello", "Kotlin")
val first = pair.first
val second = pair.second
val (x, y) = pair
Triple
val triple = Triple("a", 1, 1.0)
val first = triple.first
val second = triple.second
val third = triple.third
val (x, y, z) = triple
比如:
fun multiReturn():Triple<Int,Long,String>{
return Triple(1,3L,"aaa")
}
fun main() {
val (i, l, s) = multiReturn()
println(i+l)
}
默認(rèn)參數(shù)和具名參數(shù)
fun defaultParameter(x: Int = 5, y: String, z: Long = 0L){...}
fun main() {
defaultParameter(y = "aaa")
}
4.4 高階函數(shù)
參數(shù)類(lèi)型包含函數(shù)類(lèi)型或返回值類(lèi)型為函數(shù)類(lèi)型的函數(shù)為高階函數(shù)
public inline fun <R> IntArray.map(transform: (Int) -> R): List<R> {//參數(shù)類(lèi)型包含函數(shù)類(lèi)型(Int) -> R错蝴,返回值類(lèi)型包含函數(shù)類(lèi)型List<R>
return mapTo(ArrayList<R>(size), transform)
}
函數(shù)類(lèi)型為最后一個(gè)參數(shù)可以移到括號(hào)外面,且省略小括號(hào):
intArray.forEach{ it -> Unit
println(it)
}
省略為:
intArray.forEach { print(it) }
而
intArray.forEach { print(it) } 又等價(jià)于 intArray.forEach(::print) //::print 匹配類(lèi)型為(Int) -> Unit的函數(shù)引用颓芭,可直接傳入
完整案例:
fun cost(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
print("cost:${System.currentTimeMillis() - start}")
}
fun fibonacci(): () -> Long {
var first = 0L
var second = 1L
return {
val next = first + second
val current = first
first = second
second = next
current //return current
}
}
fun main(args: Array<String>) {
cost {
val fib = fibonacci()
for (i in 0..10) {
print(fib())
}
}
}
4.5 內(nèi)聯(lián)函數(shù) inline
函數(shù)體內(nèi)的多個(gè)函數(shù)執(zhí)行優(yōu)化為一個(gè)函數(shù)體來(lái)執(zhí)行顷锰,提升代碼執(zhí)行性能。常用于高階函數(shù)亡问,將參數(shù)函數(shù)和自身方法體合和一個(gè)函數(shù)體來(lái)執(zhí)行官紫。
inline fun cost(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
print("cost:${System.currentTimeMillis() - start}")
}
內(nèi)聯(lián)高階函數(shù)的return
val ints = intArrayOf(1, 2, 3, 4)
ints.forEach {
if (it == 3) return@forEach //僅僅跳出這一次內(nèi)聯(lián)函數(shù)的調(diào)用相當(dāng)于continue,continue只能用在循環(huán)中
print(it)
}
non-local return
ints.forEach {
if (it == 3) return //直接退出
print(it)
}
禁止non-local return :關(guān)鍵字 crossinline
inline fun Runnable(crossinline block:()->Unit):Runnable{ //也可以使用no inline block:()->Unit,禁止函數(shù)內(nèi)聯(lián)州藕,這樣前面的inline就沒(méi)有意義了万矾。
return object : Runnable{
override fun run(){
block()
}
}
}
內(nèi)聯(lián)函數(shù)的限制
- public/protected 的內(nèi)聯(lián)方法只能訪問(wèn)對(duì)應(yīng)類(lèi)的public成員
- 內(nèi)聯(lián)函數(shù)的內(nèi)聯(lián)函數(shù)參數(shù)不能被存儲(chǔ)(賦值給變量)
- 內(nèi)聯(lián)函數(shù)的內(nèi)聯(lián)函數(shù)參數(shù)只能傳遞給其他內(nèi)聯(lián)函數(shù)參數(shù)
簡(jiǎn)而言之:
- public 只能訪問(wèn)public
- 內(nèi)聯(lián)只能訪問(wèn)內(nèi)聯(lián)
- 參數(shù)不能被存