Kotlin初探之语法简介分析

前言

部门经理让我在技术分享会上分享Kotlin的语法,因为Kotlin已经被Google定为一级开发语言了,正好之前也有学习Kotlin的计划于是花2天时间熟悉了下Kotlin的语法以及特性。

语法

关于语法的介绍比较多,这里就贴一些典型的例子

  • 变量的声明
    var a : Int?=null        //?表示该变量可为null
    var b : Int = 2          // 不加?表示该变量不为null
    var c = "Hello World"   //类型自推导

在Kotlin中声明变量是用标识符var ,常量用val
格式是

    var 变量名 :类型?= ....   //?表示该变量可为null,不加?表示该变量不为null
  • 类型转换
    var e : Long= b.toLong()     //通过toLong(),toByte()等方法进行类型转换
    var f : Int= "1".toInt()    //将字符串"1"变为一个Int
  • 字符串拼接
    var name:String?="Bryant"
    var anotherName:String?= "Hello $name"
  • 函数的定义
    fun 关键字声明 具体形式 fun 函数名(变量名1 : 类型,变量名2 : 类型……):返回值类型
     fun sum(a:Int,b:Int):Int = a+b   //当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可写成单表达式函数
   //表达式有多个使用大括号,when的作用类似于Java中的Switch
   fun typeCheck(obj:Any):Int?{
       when(obj){
           !is Int ->return null
           else -> return obj
       }
   }

Kotlin还支持给函数参数默认值

  fun init(a : Int = 1 ,b : Int = 2) : Int = a+b  //如果不给a,b赋值,那么就使用默认值
  • for循环的使用
    遍历items
 val items = listOf<String>("apple","banana","orange","juice")
 for(i in items.indices){
            println("item: ${items[i]}")   //根据索引输入item
  }

或者这种形式

        for(i in items){
             println("item: $i")     //直接输出item
        }
  • !! 和 ?.的含义
    抛出NullPointerException异常使用 !!
   var a : String?=null
   println(a!!.length)

安全调用操作符写作 ?. 使用这个符号会得到null的输出,还是这个例子,我们会打印null

   var a : String?=null
   println(a?.length)

Kotlin 的类型系统旨在从我们的代码中消除 NullPointerException。NPE 可能的原因是
显式调用 throw NullPointerException()
使用了 !! 操作符
外部 Java 代码导致的
对于初始化,有一些数据不一致(如一个未初始化的 this 用于构造函数的某个地方)
安全的类型转换
如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException。 另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null:

     val aInt: Int? = a as? Int
  • 冒号 (:) 的作用
    变量(常量)的声明 ,参数的声明,实现接口,方法返回值的声明 等作用

基础的语法大概就是这么多,接下来介绍一个比较推荐的东西——协程

协程

  • 协程是什么?
    一些 API 启动长时间运行的操作(例如网络 IO、文件 IO、CPU 或 GPU 密集型任务等),并要求调用者阻塞直到它们完成。协程提供了一种避免阻塞线程并用更廉价、更可控的操作替代线程阻塞的方法:协程挂起。
    协程通过将复杂性异步放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器!)上调度执行,而代码则保持如同顺序执行一样简单。
  • 协程的具体实现
    直接上代码
    我们先进行一个简单的异步输出操作
   fun main(args: Array<String>) = runBlocking<Unit>{     //创建主协程
      var job = launch(CommonPool){
            delay(1000)
            println("我是子协程,我延迟了一秒")
      }
     println("我是主协程,我先执行")
     delay(2000)
     println("我是主协程,我执行完了")

}

我们看一下结果
这里写图片描述
这里的delay方法是一个挂起方法(suspend),它只能在协程中被调用,因为我们在main方法后面加了

      fun main(args: Array<String>) = runBlocking<Unit>

因为main方法现在是一个协程,并且是主协程
那么这串代码就好理解了,我们开始先定义一个协程的任务,然后顺序执行,子协程运行的同时,主协程还在运行,在这个例子中子协程比主协程先运行完,所以如图上输出结果,但是还有一种情况是子协程需要运行的时间比主协程的长

fun main(args: Array<String>) = runBlocking{     //创建主协程
      var job = launch(CommonPool){
            delay(3000)
            println("我是子协程,我延迟了3秒")
      }
     println("我是主协程,我先执行")
     delay(1000)
     println("我是主协程,我执行完了")

}

结果:
这里写图片描述

我们发现子协程里面的输出不见了,由此可见,子协程的执行时间是要小于主协程的,但有时我们又不知道子协程运行了多长时间怎么办,我们采用join方法

fun main(args: Array<String>) = runBlocking{     //创建主协程
      var job = launch(CommonPool){
            delay(3000)
            println("我是子协程,我延迟了3秒")

      }
     println("我是主协程,我先执行")
     job.join()
     println("我是主协程,我执行完了")

}

这里写图片描述

这样我们就不用计算子协程需要运行的时间,但是如果我们想要取消子协程的任务怎么办,也很简单,只需要在主协程中加一条job.cancel()就能取消子协程

fun main(args: Array<String>) = runBlocking{     //创建主协程
      var job = launch(CommonPool){
          repeat(1000){
              i ->
              println("我是子协程,我重复执行了 $i 次")
              delay(500)
          }
      }
     println("我是主协程,我先执行")
     delay(2000)
     println("我是主协程,我等不及了,你给我取消")
     job.cancel()
     println("我是主协程,我执行完了")

}

结果:

但是cancel()并不是所有协程任务都能取消,比如下面这种情况就不能取消

fun main(args: Array<String>) = runBlocking{     //创建主协程
      var job = launch(CommonPool){
              var nextPrintTime = 0L
              var i = 0
              while (i < 10) { // 循环运算
                  val currentTime = System.currentTimeMillis()
                  if (currentTime >= nextPrintTime) {
                      println("我是子协程,不能被取消,执行了 ${i++} 次")
                      nextPrintTime = currentTime + 500L
                  }
          }
      }
     println("我是主协程,我先执行")
     delay(1300L)
     println("我是主协程,我等不及了,你给我取消")
     job.cancel()
     delay(1300L)
     println("我是主协程,我执行完了")
}

结果:
这里写图片描述

发现如果在进行循环操作的协程不能被取消,我们接下来取消循环运算协程

fun main(args: Array<String>) = runBlocking{     //创建主协程
      var job = launch(CommonPool){
              var nextPrintTime = 0L
              var i = 0
              while (isActive) { // i<10改为 isActive 即可
                  val currentTime = System.currentTimeMillis()
                  if (currentTime >= nextPrintTime) {
                      println("我是子协程,不能被取消,执行了 ${i++} 次")
                      nextPrintTime = currentTime + 500L
                  }
          }
      }
     println("我是主协程,我先执行")
     delay(1300L)
     println("我是主协程,我等不及了,你给我取消")
     job.cancel()
     delay(1300L)
     println("我是主协程,我执行完了")

}

结果:

关于协程的内容就介绍到这里,其他的以后再补充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章