Kotlin知识归纳(一) —— 基础语法
android Kotlin系列:
Kotlin知識歸納(一) —— 基礎語法
Kotlin知識歸納(二) —— 讓函數更好調用
Kotlin知識歸納(三) —— 頂層成員與擴展
Kotlin知識歸納(四) —— 接口和類
前序
????????在19年的Google I/O大會上,Kotlin 成為 Android 開發首選語言。而著名的OkHttp 已經開始用 Kotlin 進行重寫工作。是時候通過寫博客歸納來鞏固Kotlin基礎知識。
(一)、語法上的變更
- 創建對象不需要new關鍵字
- 語句不需要;結尾,加;也無所謂
- 變量類型后置,即變量名在前,變量類型在后。例如 str:String
- 使用 println() 替代 System.out.println()
(二)、定義變量
????????Kotlin中使用val關鍵字聲明常量(即變量初始化之后不可再次賦值),var關鍵字聲明變量。
變量定義時可以不顯示指定類型,編譯器會根據其初始化器的類型進行推斷。
//自動推斷出 `Int` 類型 var daqi = 1 //可以顯式地指定變量的類型 val a :String = "daqi" //如果變量沒有初始化器,需要顯式地指定它的類型 val c: Int c = 3 復制代碼當編譯器能確保val變量只有唯一一條初始化語句會被執行,可以根據條件對它初始化不同的值。
val daqi:String var isChange = true if (isChange){daqi = "1" }else{daqi = "2" } 復制代碼val變量的引用自身是不可變的,但是它指向的對象是可變的。
val languages = arrayListOf("Java") languages.add("Kotlin") 復制代碼var 關鍵字允許變量改變自己的值,但不能改變自己的類型。
var daqi = 1 //編譯不通過 daqi = "" 復制代碼(三)、定義函數 Kotlin 中使用 fun 關鍵字聲明函數。 完整的函數定義:
修飾符(默認public)+ fun + 方法名 + (參數列表) :返回值 {函數體 } 復制代碼 public fun daqi(name:String):String { } 復制代碼表達式函數體
????????當單個表達式構成完整的函數體時,可以直接去掉 {} 和 return 語句,函數的返回值類型編譯器也會自動推斷。這種函數就是表達式函數。
fun sum(a: Int, b: Int) = a + b 復制代碼語句和表達式的區別在于:
- 表達式有值,并且能作為另一個表達式的一部分使用;
- 語句總是包圍著它的代碼塊中的頂層元素,并且沒有自己的值。
????????在 Java 中,所有的控制結構都是語句。而在 Kotlin 中,除了循環( for, do 和 do/while )以外大多數控制結構都是表達式(例如:if、 when 以及 try 屬于表達式)
???????? 表達式函數不光用在些簡單的單行函數中 ,也可以用在對更復雜的單個表達式求值的函數中。
fun max(a: Int, b: Int ) = if (a > b) a else b 復制代碼無返回值的函數
類似Java的返回值類型為void的函數
fun daqi():Unit{ } 復制代碼可省略Unit類型
fun daqi(){ } 復制代碼(三)、字符串模板
在 Java 中,當需要打印變量描述和其值時,往往如下打印:
String str = "daqi"; System.out.println("str = " + str); 復制代碼????Kotlin支持字符串模板,可以在字符串中引用局部變量,但需要在變量名前加上$。表達式會進行靜態檢查, 如果$引用一個不存在的變量,代碼不會編譯通過。
val str = "daqi" printlin("str = $str") 復制代碼$不僅限于引用于簡單的變量名稱,還可以引用更復雜的表達式。
val daqi = intArrayOf(1,2,3) println("${daqi[0]}") 復制代碼在$引用的表達式內(即花括號{}中)可以直接嵌套雙引號
println("daqi的第一個元素: ${if(daqi.size > 0) daqi[0] else "null"}") 復制代碼當需要打印$符號時,可以對其進行轉義,或者利用表達式對其進行打印:
//打印結果為:$str val str = "daqi" println("\$str") println(${'$'}daqi) 復制代碼(四)、類和屬性
在java中定義一個簡單類:
public class Person{private final String name;public Person(String name){this.name = name;}public String getName(){return name;} } 復制代碼用Kotlin寫的Person類(默認public修飾)
class Person(val name:String) 復制代碼延伸:若想知道Kotlin對應的具體Java實現,可以通過idea的工具,對Kotlin文件進行反編譯:
????Tools ->Kotlin -> Show Kotlin Bytecode -> 右側彈出字節碼框 ->左上角 Decompile按鈕
整體基本和Java類相似,但是該類被定義為final類,即太監類,不可被繼承。setter 和 getter
????在Kotlin中,當你聲明屬性的時候,也就聲明了對應的訪問器(即get和set)
????val屬性只有一個getter,var屬性既有 getter 和 setter。 聲明一個屬性的完整語法:
var <propertyName>[: <PropertyType>] [= <property_initializer>][<getter>][<setter>] 復制代碼????其中,初始化器,getter 和 setter 都是可選的。如果類型可以從初始化器或者getter 返回值中推斷出來,也可以省略。 訪問器的默認實現非常簡單,即對對應變量的返回和更改。
當需要在值被訪問或修改時提供額外的邏輯,可以通過自定義getter和setter
自定義getter
在Kotlin中的實現
class Rectangle(val height:Int,val width:Int){val isSquare:Booleanget(){return height == width} } 復制代碼對應的Java實現:
自定義setter
在Kotlin中實現:
class Rectangle(val height:Int,val width:Int){var isSquare:Boolean = falseset(value) {field = value} } 復制代碼在setter方法中,使用特殊的標識符field來訪問支持字段(幕后字段)的值。具體幕后字段后面再說。
注意:
????Kolin中,名稱以is開頭的變量。轉換成對應的Java get 和 set 方法時,getter不會添加任何的前準,setter名稱中的is會被替換成set。
class Person(var isDaqi:Boolean = false ) 復制代碼該對象在Java中的訪問器為:
(五)、迭代
Kotlin中 while 和 do-while循環,其語法與Java的基本沒區別。
而for循環僅以一種形式存在,和for-each差不多。但用 in 取代了 :
fun iterationArray(args:Array<String>){for (str in args) {} } 復制代碼????for循環還可以遍歷區間。區間本質上是兩個值之間的間隔。使用..運算符表示區間。
????Kotlin中的區間是閉合區間,即結束值也是區間的一部分。而區間默認迭代步長為1。
val oneToTen = 1..10 復制代碼????可以通過step關鍵字修改步長。遍歷時,i變量其增長幅度將變為2,即每次迭代時都會自增2。
for(i in 0..100 step 2){ } 復制代碼如果想要一個半閉合區間,即結束值不屬于區間的一部分,可以使用until關鍵字,
val oneToNine = 1 until 10 復制代碼如果需要一個倒序的區間,可以使用downTo關鍵字
val tenToOne = 10 downTo 1 復制代碼此時,將從10一直遞減到1進行循環。downTo表示的區間也是一個閉合區間。
如果想實現普通for循環一樣,對數據索引進行循環,可以使用數組的indices變量
for (i in args.indices) {println(args[i]) } 復制代碼(六)、if表達式
在Kotlin中,if是一個表達式,即它會返回一個值。
if的分支為代碼塊時,最后的表達式將作為該代碼塊的值:
val max = if (a > b) {print("Choose a")a } else {print("Choose b")b } 復制代碼(七)、when表達式
Kotlin中的when,對應的是Java中的switch,但比起更加強大。
????when 將它的參數與所有的分支條件按順序比較,直到某個分支滿足條件,執行其分支對應的代碼。當多分支需要用相同的方式處理時,可以把其放在一起,用逗號分隔。
????當when作為表達式使用時,必須有 else 分支, 除非編譯器檢測出所有的可能情況都已經被覆蓋。(例如枚舉類)
when (x) {0, 1 -> print("x == 0 or x == 1")2 -> print("x == 2")else -> print("otherwise") } 復制代碼有沒有發現,沒有了那繁瑣的case和break!!
????when的參數可有可無,并且無限制類型!而且可以用任意表達式作為分支條件。(switch要求必須使用常量作為分支條件~)
????when作為表達式函數的的函數體,直接使用函數的參數,自身并無設置參數。并在條件語句中使用in或者!in 判斷一個變量是否在區間或者集合中。
fun daqi(num:Int,intArray: IntArray) = when{num in 1..10 -> "1~10"num !in intArray -> "no in Array"else -> "other" } 復制代碼when 也可以用來取代 if-else if鏈.
fun daqi(num:Int) = when{num < 0 -> "小于0"num >0 && num < 10 -> "1..10"else -> "other" } 復制代碼????is可以檢查一個變量是否是某種類型,再配合智能轉換(檢查過某個變量的類型后,不再需要再轉換它,直接可以把它當作檢查過的類型使用)可以很方便的對進行類型安全操作。
//Any類似于Java的Object fun daqi(num:Any) = when(num){is String -> {//此時num已經為String類型println("該變量類型為String,獲取其長度")println(num.length)}is Int -> {//此時num已經為Int類型println("該變量類型為Int,將其與10進行對比")num.rangeTo(10)}else -> "other" } 復制代碼(八)、Kotlin中的異常
????Kotlin的異常處理與Java類似。當拋出異常時,不需要使用new關鍵字創建異常實例。
var daqi:String? = null if (daqi == null){throw NullPointerException("daqi is null") } 復制代碼????try也可以作為表達式,將其賦值給變量。當代碼執行正常,則try代碼塊中最后一個表達式作為結果,如果捕獲到異常,對應catch代碼塊中最后一個表達式作為結果。finally 塊中的內容不會影響表達式的結果。
fun readNumber(reader:BufferedReader):Int? = try{Integer.parseInt(reader.readLine()) }catch(e:NumberFormatException){null }catch (e:NullPointerException){null }finally {reader.close() } 復制代碼可以有0到多個 catch 塊。finally 塊可以省略。 但是 catch 與 finally 塊至少應該存在一個。
(九)、枚舉
????kotlin中用兩個關鍵字enum和class聲明枚舉類。enum是一個軟關鍵字,只有當它出現在class前面時才有特殊的意義。
聲明普通枚舉類:
enum class Color{RED,BLUE } 復制代碼聲明帶屬性的枚舉類:
enum class Color(val r:Int,val g:Int,val b:Int){RED(255,0,0),BLUE(0,0,255);fun rgb = (r * 256 + g) * 256 + b } 復制代碼如果在枚舉類型中定義任何方法,需要使用分號;把枚舉常量列表和方法定義分開。
參考文獻:
- 《Kotlin實戰》
- Kotlin官網
轉載于:https://juejin.im/post/5cebe1526fb9a07f050a479d
總結
以上是生活随笔為你收集整理的Kotlin知识归纳(一) —— 基础语法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 100days githu
- 下一篇: 巨人史玉柱经典创业语录