在关于Kotlin初体验中基础语法基本上已经介绍了一遍,这篇文章主要是对于Kotlin的一些特性的用法和理解算是补充和进阶吧。
Kotlin的修饰符:
Kotlin 的写法(默认为 public) 作用域:
public: 默认,总是可见
internal: 同模块可见
protected: 类似于private,但对子类也可见
private: 声明范围与同模块的子作用域可见
在Kotlin初体验中也提到过Kotlin的空安全,用操作符“?”来明确指定一个对象,或者一个属性变量是否可以为空。
@限定this:
@作为标记,可以作为跳出循环的break或return:
:: 操作符:
表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法
需要注意test 函数的第三个参数传入 tests 时,要确定这个参数个数、类型、返回值都一致。
引用其他类中的方法只需要在::操作符前加上需要调用的方法的对象
集合:
Kotlin没有自己的集合API而是直接调用Java原有的集合,不过Kotlin优化了集合的操作
data关键字:
在kotlin中 data 修饰符 相当于 java中 public 、 getter 、 setter 、 toString 等的集合.
@JvmOverloads方法自动重载:
$符号在kotlin中表示引用某个参数,类似于java中的%s
扩展方法:
之前在初体验这篇文章提到过kotlin的一大特色扩展方法,拓展方法可以在任何地方为已有类进行方法的拓展,拓展之后的方法使用和原生方法一致。
引用一下官方描述:
Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator. This is done via special declarations called extensions. Kotlin supports extension functions and extension properties.
意思就是Kotlin无需通过继承或装饰器模式,即可为特定类扩展出新的函数和属性.
举个例子以Toast为例,生成一个Toast需要我们传入三个参数,其中最关键的就是Context上下文对象,因为创建窗口需要建立在上下文的基础上才能完成,因此我们通常需要写一个Toast的工具来来方便我们使用,但是有了拓展方法之后就能在任意Context子类下直接调用我们拓展的方法。
在Java中”万物皆为对象“,所有的方法和属性都是基于类存在的,但是很多类都是封装好的,如果需要对它进行拓展的话就必须对它进行继承,这样会加大了我们的复杂性和耦合性.这就是Kotlin引入扩展方法的原因吧.
扩展方法实际上就是一个对应Java中的静态方法,这个静态方法参数为接收者类型的对象,然后利用这个对象就可以访问这个类中的成员属性和方法了,并且最后返回一个这个接收者类型对象本身。这样在外部感觉和使用类的成员函数是一样的。
扩展方法不能被重写
根据测试结果显示扩展方法并不是类的一部分,尽管子类和父类拥有了相同的扩展方法. 从测试来看,子类和父类拥有了相同的扩展方法,实际上就是定义两个同名的静态扩展方法分别传入父类和子类,那么调用的方法肯定也是父类中的方法和子类中的方法,所以输出肯定是父类的.
因为拓展方法的原理是基于静态函数的,所以不符合面向对象的规则。简单说就是,它不管最终生成的是什么对象,它只关心系统识别出来是什么对象,只会按照引用的类型来调用。
协程:
先简单介绍一下什么是协程,很多人对这个词很陌生.其实协程就是被认为可暂停计算的实例,即可以在某些点暂停并稍后可能在另一个线程上恢复执行的协程。协同程序相互呼叫(以及来回传递数据)可以形成协作式多任务处理的机制。
简单来说就是协程是一种“轻量级线程“,从Kotlin 1.1开始引入。由于一些耗时操作(如网络IO、文件 IO、CPU或GPU密集型任务)会使线程阻塞直到操作完成,协程提供了一种避免线程阻塞、开销更小且更加可控的异步操作。
添加 dependencies :
示例:
咦launch、CommonPool、delay是啥??下面来解释一下:
launch
launch方法定义在kotlinx.coroutines.experimental
解释一下launch方法有3个参数:context(上下文)、start(启动选项)、block(真正要执行的代码块,必须是suspend修饰的方法)
launch方法返回一个Job,Job是协程创建的后台任务的概念,它持有该协程的引用。Job继承自CoroutineContext类型。一个Job有三种状态:
New 新建 (初始状态)
Active 活动中(默认状态)
Completed 已结束(最终状态)
很明显可以看出launch方法以非阻塞当前线程的方式,启动一个新的协程后台任务,并返回一个Job对象作为当前协程的引用。
CommonPool
CommonPool是共享线程池的意思,它的主要作用是来调度计算密集型任务的协程的执行。它的实现使用的是java.util.concurrent包下面的API。首先尝试创建一个java.util.concurrent.ForkJoinPool,如果不可用,就使用java.util.concurrent.Executors来创建一个普通的线程池:Executors.newFixedThreadPool.(ForkJoinPool是一个可以执行ForkJoinTask的ExcuteService,它采用了work-stealing模式:所有在池中的线程尝试去执行其他线程创建的任务,这样很更加高效);
delay
delay()方法相当于Thread.sleep()的功能,但是比它更好:它不会阻塞线程,而只是挂起协程本身.当协程在等待时,线程将返回到池中, 当等待完成时, 协同将在池中的空闲线程上恢复.
说到delay()这个方法就不能不提一下suspend关键字,在源码中可以看见delay()这个方法前面有个suspend关键字修饰,我们称之为挂起方法.挂起方法只能从协程代码内部调用,普通的非协程的代码不能调用.挂起方法只允许由协程或者另外一个挂起方法里面调用.
-----------------------------------------------------------------------------未完待续