Kotlin入门

Google指定Android开发官方语言

Posted by wushiqian on January 28, 2020

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

  1. Kotlin定义变量时,通过给变量的类型后增加?操作符,可以设置该变量是否可以接受空引用(即可赋值为null)。 var a:String?=null //可接受空引用 var b:String=”fish_leong” //不可接受空引用
  2. 不接受空引用的变量,在IDE中编写代码阶段,IDE通过语法检查帮助我们检查出NPE错误,对该类型的变量也不需要再做null判断,相对减少了不必要的代码,同时也减少了苦逼的debug、打log的排查错误的时间,提高了效率。

  3. 可接受空引用的变量的两种操作方式
  • 安全调用(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架构

DSL构建