Kotlin 带来的好处
Data Class
data class就是一个类中只包含一些数据字段,类似于vo,pojo,java bean。一般而言,我们在Java中定义了这个数据类之后要重写一下toString,equals等方法,要生成get,set方法。
然而在Kotlin中这些都不在需要自己手动去敲了,编译器在背后默默给我们生成了如下的东西:
- equals()/hashCode()
- toString()方法
- componentN()方法
- copy()方法
因此我们在Android开发中可以方便生成bean数据了。
如何申明一个简单的数据类? 有一下几点要求:
- 主构造函数必须要至少有一个参数
- 主构造函数中的所有参数必须被标记为val或者var
- 数据类不能有以下修饰符:abstract , inner , open , sealed
Extension Functions
Extension Function是Kotlin中比较酷炫的功能,可以直接对已有类进行扩展,扩展的功能当做静态方法使用,而这个方法并不需要原来类的代码,并且这个类可以使任何基于JVM的语言。
当我们想计算字符串内某个字符出现的次数,有了扩展方法,我们可以直接把 howMany 这个方法添加至 String 类:
fun String.howMany(char: Char): Int {
var count = 0
val lowerCaseLetter = char.toLowerCase()
for (i in 0 until length) {
if (lowerCaseLetter == this[i].toLowerCase()) count++
}
return count
}
我们就可以通过这个扩展函数计算字符串内某个字符出现的次数。
Null Safety
- Kotlin定义变量时,通过给变量的类型后增加?操作符,可以设置该变量是否可以接受空引用(即可赋值为null)。 var a:String?=null //可接受空引用 var b:String=”fish_leong” //不可接受空引用
-
不接受空引用的变量,在IDE中编写代码阶段,IDE通过语法检查帮助我们检查出NPE错误,对该类型的变量也不需要再做null判断,相对减少了不必要的代码,同时也减少了苦逼的debug、打log的排查错误的时间,提高了效率。
- 可接受空引用的变量的两种操作方式
-
安全调用(Safe Calls)
如果该变量时可接受空引用的变量,在调用它的成员属性或成员方法时,要使用?安全调用,这样即便变量是null,也不会抛出异常,只会返回null
var strB:String? = null var numA = strB?.toInt() // numA=null
-
Elvis 操作符的使用 如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。 请注意,当且仅当左侧是null时,才会对右侧表达式求值。
-
!!操作符(The !! Operator)
对于需要NPE的人,就要用到这个操作符了,当一个变量使用!!时,如果该变量是null,则会抛出NPE。
可以利用kotlin各特性写出对付空安全更优雅的代码
How to remove all !! from your Kotlin code
Coroutines
之前做项目一直用的Java,Java并没有提供对协程的直接支持,对这个概念一直没有过接触,像Go、Python都是提供了对协程直接支持的。线程的调度是基于CPU算法和优先级,还是要跟底层打交道的,协程是完全由应用程序来调用的,但是他还是要基于线程来运行的,所以说是一个轻量级的线程管理。阿里已经开源了好几个协程相关的框架,这个另开一整篇文章来叙述,
与 Java 的交互
Google官方肯定提供了kotlin与Java交互的api,与 Android SDK 和 Java 程序语言库兼容,Kotlin 代码中可以方便调用 Java 库 。
以下是我《kotlin实战》、《kotlin核心编程》和kotlin官方文档阅读的思维导图,以后会补充细节。
Kotlin基础
- ${ }
- if带返回值的表达式
- when表达式
- 智能转换/类型推导
- is关键字
- for迭代map
- in关键字检查集合和区间的成员
- kotlin支持原生字符串、字符串模板
- 异常处理中kotlin不要求声明函数可以抛出的错误
函数的定义与调用
- 集合类增加了丰富的api
- 命名参数
- 默认参数值
- 顶层函数和属性,消除静态工具类
- 扩展函数和属性
- 可变参数
- 中缀调用 infix修饰符 解构声明
- 三重引号
- 局部函数
类、对象和接口
- kotlin接口可以包含默认实现和属性
- open、final和abstract修饰符
- internal声明在同一模块中可见
- 嵌套类默认不是内部类,使用inner关键字来存储外部类的引用
- 密封类:定义受限的类继承结构
- 初始化语句和从构造方法
- 使用field标识符在访问器方法体中引用属性的支持字段
- 数据类:equals、hashCode、toString、copy方法
- 类委托使用by关键字帮助避免出现许多相似的委托方法
- 对象声明:创建单例
- 伴生对象:工厂方法和静态成员
- 伴生对象可以实现接口,拥有扩展函数和属性
- 对象表达式是java中匿名内部类的替代品
Lambda编程
- 把代码块作为函数参数
- kotlin可以把lanbda放在括号外,可以使用it关键字引用单个lambda参数
- 在作用域中访问变量,包含这个lambda调用的函数中的变量:lambda捕捉
- 成员引用:在函数名称前加上::,可以替代lambda传递给函数
- 集合的函数API:fliter、map、all、any
- 惰性集合操作:序列,不需要创建新的集合来保存中间结果
- 序列的两种操作方式:中间操作与末端操作
- 可以把lambda作为实参传给接收Java函数式接口(带单抽象方法的接口,即SAM接口)作为形参的方法 *
- 带接收者的lambda,可以在这种lambda中直接访问一个特殊接收者对象方法 *
- 带接收者的lambda:with,允许你调用一个对象的多个方法,而不需要反复写出这个对象的引用
- 带接收者的lambda:apply,使用构建者风格的api创建和初始化任何对象
代数数据系统与模式匹配
kotlin的类型系统
- kotlin对可空类型的支持,Type?比Java上的Optional效率更高
- 安全调用(?.)、Elvis运算符(?:)、非空断言(!!)及let函数简洁处理可空类型
- 安全转换:as?
- 可通过内联函数在运行时获取泛型参数的具体类型
- 泛型的协变和逆变
多态和扩展
- 参数多态
- 特设多态
- 扩展函数,实质对应Java的静态方法
- 扩展函数接收器:调度接收器和扩展接收器 *
运算符重载及其他约定
高阶函数:Lambda作为形参和返回值
泛型
元编程:注解与反射
- 运行时期和编译时期
- kotlin只支持运行时期的元编程——反射
- KClass、KCallable、KParameter、KFunction、KProperty *
Kotlin设计模式
- 改造工厂模式,object是天生的单例,伴生对象创建工厂模式和静态工厂方法。此外,伴生对象还支持扩展。
- 内联函数简化抽象工厂
- 具名可选参数:弱化构建者模式的使用,利用类原生的require方法对参数的值进行约束
- 委托属性实现观察者模式
- 高阶函数简化设计模式
- 重载iterator方法来改造迭代器模式
- 偏函数结合orElse方法实现责任链模式
- ADT实现状态模式
- 通过扩展改造装饰者模式
函数式语言
- 狭义函数式语言:Haskell
- 引用透明性和副作用
- 纯函数与局部可见性
- 通过interface和泛型模拟出高阶类型和类似Haskell的Typeclass
- Monoid抽象数据类型,只要满足monoid中的同一律和结合律,就能定义一个Monoid结构,合适fold操作
- Monad核心是为高阶类型扩展flatMap操作 *
- 用类型处理错误
异步和并发
- 同步异步和阻塞非阻塞
- 协程
- launch与runBlocking
- async和await
- 并发线程安全问题
- Actor结合Akka
- CQRS架构