Kotlin基礎入門之必知必會,查漏補缺來一手~~~

追風少年瀟歌發表於2021-10-06

資料型別

Kotlin跟 java 相同,基本資料型別有八種 boolean,char,int,short,long,float,double,byte

型別 位寬 最小值 最大值
Short 16 -32768 32767
Int 32 (-2^31) (2^31-1)
Long 64 (-2^63) (2^63-1)
Byte 8 -128 127
Float 32 - -
Double 64 - -

根據資料型別,結合程式碼看下

    // 如果變數是數字,kotlin 的資料型別預設就是 Int 型別,如果超出了 Int 的取值範圍,編譯器就會自動推斷為 Long 型別
    //  根據 number 的取值範圍,推斷出 number 為 Int 型別
    val number = 100
    //  顯示宣告為 Int 型別
    val intNumber: Int = 100

    //  由於 number2 的取值範圍超出 Int 的範圍,編譯器推斷該變數升級成 long 型別
    val number2 = 9999999999
    //  顯示宣告為 long 型別
    val longNumber: Long = 100L

    // Kotlin 對小數的預設推斷是 Double 型別(如同Java)
    val number3 = 3.1415926535898
    //  顯示宣告為 Double 型別
    val doubleNumber: Double = 3.1415926535898

    // 如需要宣告 Float 型別,則只需在變數後面新增 F/f 即可
    val number4 = 3.1415926535898f
    //  顯示宣告為 Float 型別
	//  val floatNumber:Float = 3.1415926535898 // 這邊編譯會報錯,原因如下

    // 特別留意的是,kotlin 的 Float 型別十進位制位數規定了6位,所以如果超出了6位,則會出現精度丟失的情況
    println("number4: $number4") // 輸出結果為:number4: 3.1415927

    // 多說一句,Kotlin 與 Java 有一點不同的是,Kotlin 是不會像 Java 進行變數的隱形轉換的,舉個例子,
    // 你如果宣告瞭 Double 變數,就只能接受 Double 型別的值,不能接收 Float 、 Int或者其他基本型別。


    // 字串型別(引用型別)
    val str = "hello world"
    //  顯示宣告為 String 型別
    val strString: String = "hello world"
    //  可通過下標值來取
    val str1 = str[4] // 這裡取出的值是 o ,並且是 char 型別
    // 關於 Kotlin 的輸出方式可以通過模板模式來輸出,如下
    println("str is $str1") // str is o
    println("str length is ${str.length}") // str length is 11

    // 其他型別就不一一演示了,跟上面演示的都差不多了。


Kotlin 是通過呼叫 to+基本型別來實現型別之間的強制轉換

型別 強轉方法
Byte toByte()
Char toChar()
Short toShort()
Int toInt()
Long toLong()
Float toFloat()
Double toDouble()
Boolean -

擴充套件: 由於不同的表示方式,較小型別並不是較大型別的子型別,較小的型別不能隱式轉換為較大的型別。 這意味著在不進行顯式轉換的情況下我們不能把 Byte 型值賦給一個 Int 變數。(菜鳥教程)例如:val b: Byte = 1 // OK,字面值是靜態檢測的 val i; Int = b // 錯誤 val i: Int = b.toInt() // OK

陣列

陣列是一種初始化時指定容器大小,不可以動態調整其大小的容器。kotlin為陣列增加了一個Array類,為元素是基本型別的陣列增加了IntArray、Double類等其他基本型別。

下面介紹Kotlin常用的資料建立方式

    // 1.使用arrayOf建立陣列,必須指定陣列的元素,陣列中的元素可以是任意型別
    val arrayNumber = arrayOf(1, 2, 3, 4, 5)
    //  顯示宣告 Int 型別
    val arrayNumber2: Array<Int> = arrayOf(1, 2, 3, 4, 5)
    //  可通過下標值來賦值
    arrayNumber[4] = 6
    //  不顯示宣告型別時,可以是任意型別
    val arrayNumber3 = arrayOf(1, 2, "3", true, JSONObject())
    //  也可以宣告為 Any 型別,相當於 Java 的 Object
    val arrayNumber4: Array<Any> = arrayOf(1, 2, "3", true, JSONObject())

    //	2.使用arrayOfNulls建立一個指定大小且所有元素為空的陣列,必須指定集合中的元素型別以及長度
    val list = arrayOfNulls<String>(5)
    list[0] = "zhangsan"
    ...

    // 3.利用array的建構函式,動態建立陣列
    // 用接受陣列大小以及一個方法引數的 Array 構造方法,用作引數的方法能夠返回給定索引的每個元素初始值
    val array = Array(10) { it -> (it * it).toString() }
    
    // 普通的foreach方法,將陣列裡面的資料進行輸出
    array.forEach { it -> println(it) }

    // foreach增強版,會依次回撥給我們陣列中的索引和元素值
    array.forEachIndexed { index, item ->
        println("$index : $item")
    }

當然,Kotlin中同樣也會提供專門的原生型別陣列:

原生型別陣列 解釋
ByteArray 位元組型陣列
ShortArray 短整型陣列
IntArray 整型陣列
LongArray 長整型陣列
BooleanArray 布林型陣列
CharArray 字元型陣列
FloatArray 浮點型陣列
DoubleArray 雙精度浮點型陣列

由於原生陣列跟普通的陣列定義一樣,具體怎麼使用,就不一一展示了

擴充套件: 因為在Kotlin陣列型別不屬於集合的一種,雖然用法跟集合很相似,陣列和集合之間可以互相轉換,初始化集合的時候可以傳入陣列

集合

集合在Kotlin中應用非常廣泛,例如普通的變數集,物件集,封裝json型別的請求引數集合等等。集合與陣列最明顯的特點就是集合可以動態改變自己的長度,陣列不可以。

  • List:有序集合,可以通過索引下標來訪問元素。允許資料重複
  • Set:無序且唯一的集合,set中的元素順序不會按照插入的順序一樣,並且不允許出現重複元素
  • Map:也稱字典,是一種以鍵值對存在的集合,鍵是唯一的,每個鍵對應著特定的值,且值允許重複
建立方式 範例 說明 是否可變
arrayListOf() mutableListOf () arrayListOf(1,2,3) mutableListOf() 必須指定元素型別
listOf() listOf(1,2,3) 必須指定元素型別和初始化資料元素
arraySetOf() mutableSetOf () arraySetOf(1,2,3)) mutableSetOf() 集合內元素會自動去重
setOf() setOf(1,2,3) 必須指定元素型別,自動去重
arrayMapOf< K,V >() mutableListOf < K,V >() arrayMapOf(Pair("key","value")) mutableMapOf() 初始元素使用Pair包裝
mapOf() mapOf(Pair("key","value")) 必須指定初始元素,使用Pair包裝

mutableListOf的常用Api如下

  • example.reverse() // 集合反轉(倒序輸出)
  • example.shuffle() // 隨機排列元素(隨機輸出)
  • example.sort() // 順序輸出(按a-z的順序) sortDescending 則相反

方法

下面將Kotlin的方法分為下面三個模組進行講解

  • 方法宣告
  • 方法引數
  • 方法用法

方法宣告

Kotlin有三種宣告方法的方式,分別為

  • 普通類的方法
  • 靜態類的方法
  • companion object 伴生類的方法

普通類的方法

class Person {
    fun test() {
        println("成員方法")
    }
}

fun main() {
	//	普通類的成員方法宣告與呼叫
	//	需要先構建例項物件,才能訪問成員方法
    Person().test()
}

靜態類的方法

如果想要實現一個工具類的話,可以通過關鍵字object來建立一個靜態類


object commonUtil {
    fun add(x: Int, y: Int): Int {
        return x + 2
    }
}

fun main() {
    //	靜態類裡面的方法,都是屬於靜態方法
    //	不需要構建例項物件,可以通過類名來訪問靜態方法
    commonUtil.add()
}


companion object伴生類的方法

雖然Kotlin中沒有static關鍵字,但是我們可以通過companion object來實現類靜態方法的目的

class Person {
    fun test() {
        println("成員方法")
    }
    companion object{
        fun test2() {
            println("靜態方法")
        }
    }
}

fun main() {
	//	普通類的成員方法宣告與呼叫
	//	需要先構建例項物件,才能訪問成員方法
    Person().test()
    //	可通過類名來呼叫方法
    Person.test()
}

方法引數

  • 預設引數
  • 具名引數
  • 可變數量的引數

預設引數

方法中的引數可以有預設值,可以通過型別後面的=來設定預設值

fun add(x: Int = 0, y: Int) {}

具名引數

如果一個預設引數在一個無預設值的引數之前,那麼無預設值的引數,只能通過使用具名引數來呼叫該方法來使用

fun add(x: Int = 0, y: Int) {}

add( y = 1) //	僅通過給 y 賦值,而 x 使用預設值 0

如果最後一個引數是方法,那麼它既可以作為具名引數在括號內傳入,也可以在括號外傳入

fun add(x: Int = 0, y: Int, action:() -> Unit) {}

read(y = 1){println("hello")} // 括號外傳入

read(y = 1, action = {println("hello")}) // 括號內傳入

可變數量的引數

方法的引數(通常是最後一個)可以用vararg修飾符標記

fun append(vararg str: Char): String {
    val result = StringBuffer()
    for (char in str){
        result.append(char)
    }
    return result.toString()
}

傳遞可變數量的引數

append('k','o','t','l','i','n')

if表示式

帶返回值 if 表示式

在kotlin當中,由於if是一個表示式所以它會返回一個值,表示式的值為表示式作用域內最後一行的值。

fun max(a: Int, b: Int): Int {
    return if ( a > b ) a else b
}

多級 if 表示式

fun eval(number: Number) {
    if (number is Int) {
        println("this is int number")
    } else if (number is Double) {
        println("this is double number")
    }else if (number is Long) {
        println("this is long number")
    }
    ...
}

fun main() {
    eval(100)
}

when表示式

fun eval(number: Number): String = when (number) {
    is Int -> this is int number
    is Double -> this is double number
    is Long -> this is long number
    ...
}

fun main() {
    eval(100)
}

迴圈控制

for迴圈

for迴圈可以對任何提供迭代器iterator的物件進行遍歷,寫法為 for item in elements,最常用的應用就是迭代集合

val items = listOf("kotlin","java","python")

for (item in items) {println(item)}

除此之外,擴充套件一下,for迴圈還有兩種其他遍歷方式

val items = listOf("kotlin","java","python")

items.forEach {item -> println("forEach:${item}")}

items.forEachIndexed {index, item -> println("forEachIndexed:${index},${item}")}

do-while

//	當 condition 為 true時執行迴圈體
while(condition) {
    ...
}

//	迴圈體第一次會無條件地執行。之後,當condition為true時才執行
do {
   ... 
} while (condition)

迭代區間和數列

for 可以迴圈遍歷任何提供了迭代器的物件。即:有一個成員函式或者擴充套件函式 iterator(),它的返回型別,有一個成員函式或者擴充套件函式 next(),並且有一個成員函式或者擴充套件函式 hasNext()返回Boolean

for (i in 1..10) {
    //	遍歷區間,kotlin的區間的包含 [1,10]
    print("$i ") // 輸出結果為 : 1 2 3 4 5 6 7 8 9 10
}

for (i in 1 until 10) {
    //	until 不包含最後一個元素,左閉右開的區間 [1,10)
    print("$i ") // 輸出結果為 : 1 2 3 4 5 6 7 8 9
}

for (i in 10 downTo 1 step 2) {
    //	從 10 開始,每隔2個元素列印一次
    print("$i ") // 輸出結果為 : 10 8 6 4 2
}

break 和 continue

  • break:終止最外層的迴圈
  • continue:終止當前迴圈,開始下一次迴圈

泛型

泛型是一種語法糖,其實就是把型別引數化,它的引入給強型別程式語言加入了更強的靈活性。

好處

  • 將程式碼通用化,可應用到多個業務模組
  • 增強程式碼的健壯性,避免了ClassCastException類轉換異常
  • 方便造輪子,解決實際的問題

常見的泛型應用有:泛型類、泛型介面、泛型方法和泛型屬性

泛型介面/泛型類(泛型型別)

定義泛型型別,是在型別名之後、主建構函式之前用尖括號括起的大寫字母型別引數指定:

泛型介面

interface Person<T> {
    fun study(): T
    fun run(t: T)
}

class Student : Person<String> {
    override fun run(t:String) {
        print("run:${t}")
    }
}

fun main() {
    val student = Student()
    student.run("跑步")
}

泛型類

abstract class Color<T>(val t: T) {
    abstract fun printColor()
}

class BlueColor(val color: String) : Color<String>(color) {
    override fun printColor() {
        print("printColor:${color}")
    }
}

fun main() {
    val blueColor = BlueColor("藍色")
}

泛型欄位

定義泛型型別欄位,可以完整地寫明型別引數,如果編譯器可以自動推定型別引數,也可以省略型別引數

abstract class Color<T>(val t: T /*泛型欄位*/) {
    abstract fun printColor()
}

泛型方法

fun <T> fromJson(json: String, tClass: Class<T>): T? {
    val t: T? = tClass.newInstance()
    return r
}

fun main() {
    fromJson("{}", String::class.java)
}

至此,Kotlin的入門教程就告一段落了,後續要需要補充的再更新,感謝觀看 ✿✿ヽ(°▽°)ノ✿

相關文章