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("我是主協程,我執行完了")

}

結果:

關於協程的內容就介紹到這裏,其他的以後再補充

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