语法
- 中缀表达式 - 1 
 2
 3
 4- // 声明 
 infix fun <A, B> A.to(that : B): Pair<A, B>
 // 使用: A 中缀方法 B
 1 to 2
- 可变参数 - 1 
 2
 3
 4- // varargs,类似于java的 ... ,但是位置没有限制 
 // 可以使用 * 来传入外部的变量作为可变参数的变量
 val letters = arrayof("a", "b", "c")
 printLetters(*letters)
- 原生字符串 - 1 
 2
 3
 4- val str = """ 
 123
 abc
 """
- 判断 - 结构相等:== ,判断内容是否相等
- 引用相等:=== , 判断引用是否一样
 
- 区间 - 1 
 2
 3
 4
 5- // 区间[IntRange] 
 1 .. 10 // [1,...,10]
 1 until 10 // [1,...,9)
 10 downTo 1 // [10,9...1]
 1 .. 10 step 2 // [1,3,5...]
- 遍历 - 1 
 2
 3
 4- // 遍历 
 for (i in array) {}
 // 获取索引
 for (i in array.indices) {}
- 延迟初始化: - by lazy- 1 
 2
 3
 4
 5
 6- // 默认线程安全 
 val str by lazy { "str" }
 // 并行模式
 val str by lazy(LazyThreadSafetyMode.PUBLICATION) { "str" }
 // 不做任何线程安全保证,也不会有任何线程开销
 val str by lazy(LazyThreadSafetyMode.NONE) { "str" }- 变量必须是不可以变的:val
- 在首次调用时才会初始化
- lazy属性会默认加入同步锁,在同一时刻只允许一个线程堆lazy属性进行初始化
 
- 变量必须是不可以变的:
- 函数 - 1 
 2
 3
 4- // lambda 表达式 
 val foo = {x: Int, y: Int -> x + y} // foo.invoke(1, 2) 或 foo(1, 2)
 // lambda 表达式函数体
 fun foo(x: Int) = {y: Int -> x + y} // foo(1).invoke(2) 或 foo(1)(2)
- 匿名内部类 - 1 
 2
 3
 4
 5
 6
 7
 8- // lambda 表达式 
 val runnable = Runnable{}
 // 匿名实现类
 val runnable = object : Runnable {
 override fun run() {}
 }
 // 或匿名内部类
 executor.submit(object:Runnable{...})
- 密封类: - sealed- 1 
 2
 3- sealed class State 
 class SuccessStatus:Status
 class ErrorStatus:Status- 要继承必须将子类定义在同一个文件中
 
- 内联类 - 类似于包装类型,在编译时会把实际值替换到调用处 
 由于- Kotlin不能使用- IntDef模拟枚举的调用,可以考虑内联类来模拟枚举- 1 
 2
 3
 4
 5
 6- inline class State(val ordinal:Int) 
 companion object {
 // 模拟枚举
 val Idle = State(0)
 val Busy = State(1)
 }
- 可见性修饰符 - 修饰符 - 含义 - 与Java比较 - public - Kotlin中默认修饰符,全局可见- 与Java中public效果相同 - protected - 受保护修饰符,类及子类可见 - 含义一致,作用域除了类和子类,包内也可见 - private - 私有修饰符,类内修饰只有本类可见,类外修饰文件内可见 - 私有修饰符,只有类内可见 - internal - 模块内可见 - 无 
- 内部类和静态内部类 - 1 
 2
 3
 4- class OutClass{ 
 class StaticClass{} // 静态内部类
 inner class InnerClass{} // 内部类
 }
- 委托代替接口实现 - 1 
 2
 3
 4
 5
 6
 7
 8- interface CanFly { 
 fun fly()
 }
 open class Flyer : CanFly {
 override fun fly() {
 }
 }
 class Bird(flyer: Flyer) : CanFly by flyer
- 解构 - 普通类想要使用结构方式可以手动写component1 component2一一对应的结构函数 - 1 
 2
 3
 4
 5- // 数据类最多支持五个参数的解构 
 val pair = Pair(1, 2)
 val triple = Triple(1, 2, 3)
 val (n1, n2) = pair
 val (a, b, c) = triple
- 伴生类 - 1 
 2
 3
 4
 5- class OutClass{ 
 companion object { //相对于饿汉式静态内部类,全局只有一个实例
 fun testFun() {}
 }
 }
- object单例- 1 - object Child - 相当于 - 1 
 2
 3
 4
 5
 6
 7
 8- public final class Child { 
 
 public static final Child INSTANCE;
 private Child() {}
 static {
 INSTANCE = new Child();
 }
 }
- 操作符 - 1 
 2
 3
 4
 5
 6- var obj:TestData? = null 
 val result = obj?.value ?: -1 // 如果 obj 为空,则返回 1
 val result = obj!!.value // 明确知道obj不为空
 val stu: Student? = getStu() as Student // 强制转换,如果为空会报错
 val stu: Student? = getStu() as? Student // 强制转换,如果 getStu 返回空,则转换为空
- 泛型内联特化 - 1 
 2
 3
 4
 5- inline fun <reified T> method(t:T) { 
 val ts = Array<T>(3){}
 val jclass = T::class.java
 val list = ArrayList<T>()
 }
- 数组 - 1 
 2
 3- val a1 = arrayOf(o1, o2, o3) // 普通数组 
 val a2 = intArrayOf(1, 2, 3) // 基本数据类型数组:longArrayOf、floatArrayOf、doubleArrayOf....
- 泛型多继承 - 1 
 2
 3
 4
 5- interface Ground 
 open class Fruit
 class Water: Fruit(),Ground
 fun <T> cut(t: T) where T : Fruit, T : Ground {}
- 作用域操作符 - 如果需要返回自身的:apply{this} 或 also{it}
- 不需要返回自身的:run{this}或let{it}
- 满足条件才执行:data.takeIf { it.age >= 18 }.let {...}
- 不满足条件才执行:data.takeUnless { it.age >= 18 }.let {...}
 
- with和- apply- 1 
 2- inline fun <T, R> with(receiver: T, block: T.() -> R): R 
 inline fun <T> T.apply(block: T.() -> Unit): T
- 惰性求值:序列 - 1 
 2
 3
 4
 5
 6- val list = listOf(1, 2, 3, 4, 5) 
 // 该操作会产生两个临时集合来记录元素,如果元素非常多时,就会有效率问题
 list.filter {it > 2}.map {it * 2}
 // 通过惰性求值减少临时集合的情况
 list.asSequence().filter {it > 2}.map {it * 2}.toList()
- 无限序列 - 1 
 2- val naturalNumList = generateSequence(0) {it + 1} 
 naturalNumList.takeWhile {it <= 9}.toList()
- 内联函数 - 内联函数能将函数内容编译到调用处,减少函数调用 - 1 
 2
 3
 4
 5- inline fun cost(block:() -> Unit) 
 // crossinline 禁止传递的block函数调用 r eturn 方法
 inline fun cost(crossinline block:() -> Unit)
 // noinline 该函数参数不做内联
 inline fun cost(noinline block:() -> Unit)- 内联函数注意事项 - 由于JVM对普通函数有内联优化,所以普通函数比一定要采用内联函数,这样只会增加复杂性
- 尽量避免有大量函数体的函数进行内联,这样会增加字节码数量
- 内联函数无法使用闭包成员【闭包:内部函数持有外部函数变量】
 
- 运算符重载 - 参考:https://kotlinlang.org/docs/reference/operator-overloading.html 
 operator fun 类名.重载符号(一个参数):返回值 {}
- 扩展函数 - 1 
 2
 3
 4
 5- class Person{...} 
 // 为Person类增加名为ext的扩展方法
 fun Person.ext(s:Any) {
 println(s)
 }
- 扩展属性 - 1 
 2- val Data.extValue:boolean 
 get() = this.otherValue % 2 == 0
- 静态扩展函数 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- class Son { 
 companion object {
 val age = 10
 }
 }
 fun Son.Companion.foo() {
 println("age = $age")
 }
 // 这样就可以不创建类的情况下直接调用
 Son.foo()
- 代理观察者 - 1 
 2
 3
 4
 5
 6
 7- class Data() { 
 var price: Int by Delegates.observable(0, { property, oldValue, newValue ->
 // 当price的值变更时触发该函数
 })
 }
 val data = Data()
 data.price = 100
- 代理限制 - 1 
 2
 3
 4
 5
 6
 7
 8- class Data() { 
 var price: Int by Delegates.vetoable(0, { property, oldValue, newValue ->
 newValue > 0
 })
 }
 val data = Data()
 data.price = 100
 data.price = -100 // 该值不会设置成功
- 原始方式创建协程 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- suspend { 
 // coroutine heandle!
 }.createCoroutine(object : Continuation<Unit> {
 override val context: CoroutineContext
 get() = Dispatchers.Default
 override fun resumeWith(result: Result<Unit>) {
 // Coroutine end!
 }
 }).resume(Unit)
- 顶层协程 - 1 
 2- val job = GlobalScope.launch {} 
 job.cancel()
- 会阻塞当前线程直到协程作用域内的代码全部执行完 - 1 - runBlocking {} 
- 创建子协程,必须在协程作用域内使用 - 1 
 2- val job = launch{} 
 job.cancel()
- 挂起函数 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- // 没法使用launch函数 
 suspend fun name(){}
 // 通过coroutineScope生成带协程作用域的挂起函数
 suspend fun name()=coroutineScope{
 launch{}
 }
 // 注意:coroutineScope也会阻塞当前协程,必须得里面的子协程执行完了才行
 runBlocking {
 coroutineScope {
 launch {}
 }
 // 得等coroutineScope执行完了才会走到这
 }
 // 得等runBlocking执行完了才会走到这
- 协程统一取消 - 1 
 2
 3
 4
 5
 6- val job = Job() 
 val scope = CoroutineScope(job)
 scope.launch{
 // 协程域
 }
 job.cancel()
- 超时协程 - 1 - withTimeout(100){} 
- 返回结果的协程域 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- val r1 = async{ 
 // 返回deferred时协程就已经开始跑了
 }
 val r2 = async{
 // 返回deferred时协程就已经开始跑了
 }
 println("${r1.await()} - ${r2.await()}")// 阻塞返回结果
 // async简化版
 val result = withContext(Dispatchers.Dafault) {} // 阻塞返回结果,其中Dispatchers.Dafault为低并发策略
- suspendCoroutine结合回调函数,需要在协程域和挂起函数中使用- 1 
 2
 3
 4
 5
 6
 7
 8- suspend fun request(address:String):String { 
 return suspendCoroutine {continuation ->
 new Thread({
 continuation.resume(结果)// 成功
 continuation.resumeWithException(结果)// 失败
 }).start()
 }
 }
- 同步代码块和同步代码函数 - 1 
 2
 3
 4
 5
 6
 7- fun method2() { 
 synchronized(this) {
 }
 }
 fun method1() {
 }
- volatile - 1 - private var count = 1 
- ReentrantLock- 1 
 2- val lock = ReentrantLock() 
 lock.withLock { method() }
- 反射 - 首次使用会比java的慢 - 1 
 2- Kotlin class:String::class String::class.java.kotlin 
 Java class: String::class.java
- 注解变更java调用命名 - 1 
 2
 3
 4
 5
 6
 7- ("name")//作用于文件名 
 ("name")//作用于变量get函数
 // 带默认参数函数适配java调用
 //这样就会生成重载方法来适配默认参数
 inernal // 声明的对象不想被java访问到,可以使用@JvmName("%abc")等特殊字符声明,这样java就被限制了