数据分析师 [????????????????] 邀请 [????????????????] 网 cp15115.com
kotlin 变量的使用, kotlin 的基本数据类型都是引用类型, 和 java 的 String 一样都是对象
不可变变量, 相当于 java 的 final 修饰, 申明时候必须初始化
使用原型: val 变量名: 类型 = 变量值
使用举例:
- val valInt = 1
- val valInt2:Int = 2
valInt 不指定类型, 会根据赋值自动推导. val 定义的变量作为常量存在, 其值不可改变.
可变变量, 不为 null, 申明时候必须初始化
使用原型: var 变量名: 类型 = 变量值
使用举例
- var valLong: Long = 12222
- valLong = 2
var 申明的变量可以改变其值, 但是未申明可以为 null, 赋值 null 会报错.
可变变量, 可为 null, 通过问号标记
使用原型: var 变量名: 类型? = 变量值
使用举例
- var varNullString: String?
- varNullString = null
- varNullString = "sss"
空安全
当对象或者变量使用问好修饰后, 编译器会强制强制要求进行空安全检查, 尽可能避免运行时出现空指针异常. 空检查时候, 如果被检查对象为 null, 此行代码不会执行
- // 定义一个可空变量
- var varNullString: String?
- // 第一种使用方式, 建议使用这种
- var len = test?.length
- // 类似 java 中
- //if(test!=null){
- // len=test.length
- //
- }
- // 第二种使用方式
- len = test!!.length // 这种当 test 为 null 时会报异常
- // 类似 java 中
- //if (test != null) {
- // len = test.length
- //
- } else {
- // 抛出异常
- //
- }
- // 第三种使用方式
- len = test?.length ?: 10
- // 类似 java 中
- //if(test!=null){
- // len = test.length
- //
- }else{
- // len = 10;
- //
- }
类与继承, 接口
官方文档
类, 接口, 继承, 实现接口和 java 非常类似
类与 java 区别:
1,kotlin 的类中字段默认时 public, 对外可见, 修改控制访问权限时可以设置为 private,protect 等.
2,kotlin 的类中字段默认全部实现 get,set 方法, 需要修改这两个方法时候可以重写
3,kotlin 的类可以重写 init 方法, 此方法在类实例化时候调用, 可以做初始化操作
接口与 java 区别
1,kotlin 的接口和 java 有点区别可以定义包含方法体的方法, java 的接口只能定义抽象方法.
2,kotlin 接口可以定义变量, 和接口中的方法一样, 类实现接口时必须重写字段.
可见性
可见性官方文档
关键字 可见范围
public 任何看到声明类的客户都会看到其 public 成员
private 表示仅在此类中可见 (包括其所有成员)
protected 与 private 子类中的 + 可见相同
internal 模块内可见
继承, 实现
kotlin 和 java 一样, 只能单继承, 可以实现多个接口
原型
class 类名 {
}
或者
class 类名: 接口 1, 接口 2, 接口 3, 父类 {
}
使用举例
定义父类 ClassParent,open 关键字修饰后才可以被继承
- open class ClassParent(data: String) {
- /**
- * 父类中字段
- */
- var dataParent: String? = data
- }
定义一个接口 InterfaceParent
- interface InterfaceParent {
- /**
- * 抽象字段
- */
- var dataInterface: String
- /**
- * 接口中的抽象方法, 实现接口后必须重写
- */
- fun setData(data: Int)
- /**
- * 接口中带方法体的方法
- */
- fun setData2(data: Int) {
- // 接口中的方法可以有方法体
- }
- }
ClassA 实现接口 InterfaceParent, 继承父类 ClassParent
- class ClassA : ClassParent, InterfaceParent {
- var dataA: Int? = null
- /**
- * 接口中的抽象字段, 实现接口时候必须重写
- */
- override var dataInterface: String = ""
- /**
- * 类的初始化块
- */
- init {
- dataInterface = "类的初始化块"
- }
- /**
- * 父类有一个带参数的构造方法, 子类必须重写
- */
- constructor(data: String) : super(data) {
- }
- /**
- * 多参数构造方法
- */
- constructor(data: String, dataA: Int?) : super(data) {
- this.dataA = dataA
- }
- /**
- * 重写 InterfaceParent 中方法
- */
- override fun setData(data: Int) {
- dataA = data
- }
- }
方法
kotlin 中方法概念和 java 相同, 方法原型和 java 不同, 功能比 java 强大, 支持函数作为参数和返回值 (高阶函数)
普通方法
方法原型
fun 方法名 (参数 1: 参数类型, 参数 2: 参数类型): 返回值类型 {
- // 实现功能
- }
使用举例
无参无返回
- /**
- * 定义一个无参方法打印 data 的值
- * 方法返回值是 void
- */
- fun printData() {
- Log.i(log, "data=$data")
- }
有参有返回值
- /**
- * 定义参数为 String,Boolean 的方法
- * 方法返回值是 Boolean
- */
- fun printData(d: String, b: Boolean): Boolean {
- data = d
- this.b = b
- Log.i(log, "data=$data ; b=${this.b}")
- return b
- }
参数默认值方法
方法定义时候参数设置默认值, 调用方法时候有默认值的参数可以不传递, kotlin 自动使用默认值
使用举例
定义方法 reformat,normalizeCase,upperCaseFirstLetter 默认为 true,divideByCamelHumps 默认 false
- fun reformat(
- str: String,
- normalizeCase: Boolean = true,
- upperCaseFirstLetter: Boolean = true,
- divideByCamelHumps: Boolean = false
- ) {
- // 实现功能
- }
使用 reformat 方法
- reformat("")
- reformat("", false)
- reformat("", false, upperCaseFirstLetter = false)
- reformat("", false, upperCaseFirstLetter = false, divideByCamelHumps = false)
方法原型
使用举例
高阶函数 (详见底部高阶函数介绍)
静态方法, 变量
官方文档
kotlin 静态方法, 变量类似 java 中 public static final 修饰的变量, 方法, 使用 companion object 包裹即可, 常量需要 const 修饰
- companion object {
- // 放置静态方法, 变量
- }
使用举例
定义一个类
- class StaticData {
- companion object {
- // 常量需要 const 修饰
- const val staticVal = "类似于 java 的 public static final"
- var staticVar = ""
- fun setStaticData(data: String) {
- staticVar = data
- }
- }
- }
使用静态常量, 方法
- val temp = StaticData.staticVal
- StaticData.staticVar = temp
- StaticData.setStaticData(temp)
控制流
官方文档
if 使用
与 java 中 if 类似使用
- // Traditional usage
- var max = a
- if (a <b) max = b
- // With else
- var max: Int
- if (a> b) {
- max = a
- } else {
- max = b
- }
- // As expression
- val max = if (a> b) a else b
for 使用
与 java 的 for 类似使用, 功能略强
collection 为定义的集合, step count 为循环步进, 默认为 1
- for (item in collection step count){
- print(item)
- }
在 1-3 之间遍历, 步进为 1
- for (i in 1..3) {
- println(i)
- }
在 1-6 之间遍历, 步进为 2
- for (i in 6 downTo 0 step 2) {
- println(i)
- }
when 使用
类似 java 的 switc, 功能比 switch 强大, case 条件可以时常量, 集合, 表达式, 类型, when 条件可以时一个表达式
- val list = ArrayList<Int>()
- var data = 1
- when (data) {
- 1 -> {
- // 等于 1
- }
- 2 -> {
- // 等于 2
- }
- in 3..5 -> {
- // 在 3-5 之间
- }
- in list -> {
- // 在 list 集合中
- }
- !in 6..7 -> {
- // 不在 6-7 之间
- }
- is Int -> {
- // 类型为 Int 时候
- }
- else -> {
- // 其它, default
- }
- }
协程
官方文档
百度百科定义协程:
协程不是进程或线程, 其执行过程更类似于子例程, 或者说不带返回值的函数调用. 一个程序可以包含多个协程, 可以对比与一个进程包含多个线程, 因而下面我们来比较协程和线程. 我们知道多个线程相对独立, 有自己的上下文, 切换受系统控制; 而协程也相对独立, 有自己的上下文, 但是其切换由自己控制, 由当前协程切换到其他协程由当前协程来控制.
需要单独依赖库
API "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines"
通过 GlobalScope 使用, Dispatchers 定义协程执行在什么线程, 可选 IO,MAIN,Default, 耗时操作一般在 IO 线程执行, kotlin 通过线程池管理 IO 线程; 刷新界面使用 MAIN, 默认在调用处所在线程时使用 Default.GlobalScope.launch 执行时候会有一个返回值, 调用返回值中的
join 方法可以让主协程或者线程卡在 join 处, 直到子协程执行完成;
cancel 方法取消协程;
cancelAndJoin 方法取消并等待子协程
- GlobalScope.launch(Dispatchers.IO) {
- }
使用举例
1, 开启子线程执行任务
- GlobalScope.launch(Dispatchers.IO) {
- // 这里是在子线程
- // 延迟 500 毫秒
- delay(500)
- Log.i(log, "这里是协程 1,Thread id=${Thread.currentThread().id}")
- }
2, 子线程执行, 结果返回主线程
- GlobalScope.launch(Dispatchers.Main) {
- val job = GlobalScope.launch(Dispatchers.IO) {
- // 这里是在子线程
- delay(2000)
- Log.i(log, "这里是 IO 协程, Thread id=${Thread.currentThread().id}")
- }
- // 这里是在 UI 线程
- // 主协程会阻塞在这里, 直到子协程执行完成
- job.join()
- // 取消任务
- //job.cancel()
- // 取消 job 并且等待它完成
- //job.cancelAndJoin()
- Log.i(log, "这里是 Main 协程, Thread id=${Thread.currentThread().id}")
- }
3, 定时任务
- GlobalScope.launch(Dispatchers.IO) {
- repeat(10) {
- i ->
- // 这里是在子线程, 10 此重复时, 每次的线程可能不相同
- Log.i(log, "I'm repeat $i ...,Thread id=${Thread.currentThread().id}")
- delay(100)
- }
- }
高阶函数
高阶函数简单理解就是函数的参数或者返回值是函数的函数
原型
- fun hight(a:funA,b:funB):funC{
- }
使用举例
普通 2 个普通函数, 返回 Int 类型数据, kotlin 中函数的定义可以和变量一样使用 val 定义
- private val data1 = fun(): Int {
- return 10
- }
- private val data2 = fun(): Int {
- return 2
- }
将函数用作一个函数的返回值的高阶函数
- fun getData2(): () -> Int {
- return data2
- }
定义高阶函数 higherFunction
- /**
- *
- * @param aFun 一个无参数, 返回值类型为 Int 的函数类型
- * @param cFun 一个无参数, 返回值类型为 Int 的函数类型
- * @param bFun 一个有两个 Int 类型参数, 返回值类型为 Int 的函数; 类型
- * @return Int 类型
- */
- private fun higherFunction(
- aFun: () -> Int,
- cFun: () -> Int,
- bFun: (a: () -> Int, b: () -> Int) -> Int
- ): Int {
- // 将参数 a,c 传入到参数 b(函数), 得到结果
- return bFun.invoke(aFun, cFun)
- }
定义高阶函数 higherFunctionAdd
- /**
- * 高阶函数 higherFunctionAdd,higherFunctionSubtract,higherFunctionMult
- * @param aFun 一个无参数, 返回值类型为 Int 的函数
- * @param bFun 一个无参数, 返回值类型为 Int 的函数
- * @return Int 类型
- */
- private val higherFunctionAdd = fun(aFun: () -> Int, bFun: () -> Int): Int {
- // 调用函数 aFun,bFun
- return aFun.invoke() + bFun.invoke()
- }
定义高阶函数 higherFunctionSubtract
- private val higherFunctionSubtract = fun(aFun: () -> Int, bFun: () -> Int): Int {
- // 调用函数 aFun,bFun
- return aFun.invoke() - bFun.invoke()
- }
定义高阶函数 higherFunctionMult
- private val higherFunctionMult = fun(aFun: () -> Int, bFun: () -> Int): Int {
- // 调用函数 aFun,bFun
- return aFun.invoke() * bFun.invoke()
- }
使用高阶函数
- // 使用高阶函数 higherFunction, 实际是 data1 + data2 ,(10 + 2)
- val res = higherFunction(data1, getData2(), higherFunctionAdd)
- // 使用高阶函数 higherFunction, 实际是 data1 - data2 ,(10 - 2)
- val res2 = higherFunction(data1, getData2(), higherFunctionSubtract)
- // 使用高阶函数 higherFunction, 实际是 data1 * data2 ,(10 * 2)
- val res3 = higherFunction(data1, getData2(), higherFunctionMult)
来源: http://www.bubuko.com/infodetail-3253076.html