Kotlin學習筆記(1)

開始學習用Kotlin 來寫Android,因為已經有寫Java的經驗,Kotlin語法的部分只針對自己覺得比較特殊的部分做一個筆記記錄下來,方便未來查詢檢視。
主要是在 udemy 平台上學習Kotlin所記錄下的筆記,有興趣者可以參考這堂課程。


1 變數宣告:

var : 變數宣告

val : Immutable 變數宣告,以val 宣告的變數則不可重新指定新的值

型別宣告: Kotlin 會自動推斷一些變數型別,但也可以透過宣告方式來指定:

var age: Int = 24;

age = "string"  // <= throw error

宣告起始值為 null 之變數方法:

val age: Int = null; // <= Error here
val age: Int? = null; // Correct

2 Null Safety in Kotlin:

如果宣告一個變數初始值為 null ,在後續調用 function 時,會出現錯誤提示,原因是我們宣告的變數可能在runtime 時,內容仍為null,調用null的function 會導致 nullPointerException 錯誤

val name: String? = null;
val.length // <= error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?

解決方式有兩種

  1. 使用 !!

  2. 使用 ?

  3. 如果是Mutable變數,可以透過加入if 判斷的方式,Kotlin compiler 就不會報錯(該方式僅限於區域變數,若為全域變數,這方法無效)

val name: String = null
val name2: String? = "Kotlin"

println(name!!.length) // <= kotlin.KotlinNullPointerException
println(name?.length) // <= null

if(name2 != null){ // local variable only,若name2為全域變數則會報錯
 println(name2.length); // <= compiler 會知道進到這邊的情況下 name2 一定不會是 null
}

3 If Expression

If 用法與 Java等其他語言相同,這邊紀錄比較特別的部分:

val x: Int = 20

val y = if(x < 10){
    println("LT 10")
    "LT 10"
}else if(x >=10 && x<20) {
	println("GT 10 abd LT 20")
	"GT 10 abd LT 20"
}else {
	println("GTE 20")
	"GTE20"
}
println(y)

4 when Expression

類似switch,可以分為 when(expxression){statement} 或是 when {statement},後者與其他程式語言相同

val price:Int = 30

// 第一種用法
when(price){
    0,1 -> println("For free today") // 0或1
    in 2..19 -> println("On sale") // 在 2 - 19的區間;如果是不要再2-19的區間,可以改為 !in 2..19
    in 20..29 -> println("Normal price") // 在 20到 29 區間
    10+20 -> println("Slightly overpriced") // 左方可以是expression或function
    else -> println("Overpriced") // 等同default value
}

// 第二種用法,執行內容相同

when{
 price == 0 || price ==1 ->  // 0或1
 price in 2..19 -> println("On sale")
 price in 20..29 -> println("Normal price")
 price == 20+10 -> println("Slightly overpriced"
 else -> println("Overpriced")
}

// 與 if一樣的特殊用法:
val x = when(..)...

5 Collections

Kotlin的Collections 是建立在Java的Collections上,並再加入更實用的library functions,並且有Mutable與Immutable Collections的概念。


// Array
val array = arrayOf(1,2,3,4) //  一般陣列宣告
val intArray = intArrayOf(1,2,3,4) // Kotlin 提供了 primitive type array
val doubleArray = doubleArrayOf(1.0,2.0,3.0,4) // double array

// **下列collection 會區分為 Mutable與Immutable**
// List
val list = listOf(1,2,3,4) // Immutable list,無法針對內容再作修改
val mutableList = mutableListOf(1,2,3,4) // mutable list,可修改內容

list[0] = 1 // <= compile error
mutableList[0] = 99 // <= success

// 可以透過 joinToString 方法將collection 印出
list.joinToString() // 1,2,3,4
mutableList.joinToString() // 99,2,3,4

// Map
val map = mapOf(Pair(1, "Kotlin"), Pair(2, "Android"))

val mutableMap = mutableMapOf(Pair(1,"Kotlin"), Pair(2, "Android"))

// Map 提供一個更直覺地宣告方式,透過 to 來宣告,下列宣告方式與上方相同:
val mutableMap = mutableMapOf(1 to "Kotlin", 2 to "Android")  // 結果與前面宣告方式的結果相同

// Set
val set = setOf(1,2,1,2,3) // 僅可取內容,但不可修改內容

val mutableSet = mutableSetOf(1,2,1,2,3) // mutable set 才會提供add, remove之類的 function

從上面不難看出,除了陣列以外,其他的collection 類別都會區分為 mutable與immutable,宣告差異就在前面加上mutable與否來決定要以mutable還是immutable 方式來宣告。

6 For loop

直接看語法:

// range
for(i in 1..10){
	println("$i ") // print 1 to 10
}

// iterable
for(s in "Kotlin"){
	println("$s "); // K o t l i n
}

val list = listOf("a", "b", "c")
for(i in list){
	println("$i ") // a b c
}
 
// step
for(i in 1..10 step 2){
	println("$i ") // i add by 2.  1 3 5 7 9
}

// reverse
for(i in 10 downTo 1 step 2){
	println("$i ") // from 10 down to 1 10 8 6 4 2 
}

7 while loop

直接看程式吧

var i = 0
while(i <=10){
 println("$i ") // print 0 to 10
 i++;
}

var j =0
do{
 println("$j ")
 j++;
}while(j<=10)

8 function

fun permitEntrance(age: Int): Boolean{
 return age>=18
}

// 等同於

fun permitEntrance(age:Int):Boolean => age>=18

permitEntrance(20) // <= true


// vararg 宣告表示可傳入多個內容
fun permitEntrance(vararg ages: Int){
 // any表示在ages內每一個value
 return ages.any {age => age>=18}
}

permitEntrance(18, 19, 20) // true

9 named argument and default parameter value

在宣告function 時, 可以對參數宣告預設值,在呼叫時若未傳入任何內容,則會以使用預設值

concat(listOf("Android", "Kotlin")) // <= Android,Kotlin

fun concat(texts: List<string>, seperator:String = ",") = texts.joinToString(seperator)
</string>

在參數傳遞時,也可以下列方式傳遞,直接指定哪些內容要對應到哪些參數名稱:

concat(seperator = ";". values = listOf("Android", "Kotlin")) // <= Android,Kotlin

fun concat(texts: List<string>, seperator:String = ",") = texts.joinToString(seperator)

10 Exception

Exception 用法與Java差不多,但也多了與 if-else 相同的使用方式,這邊僅記錄較特別的部分:

fun main(args: Array<string>){
    var input = try {
        getExternalInput() //return value
    }catch(e:Exception){
        e.printStackTrace()
        "" // return value when exception caught
    }finally{
        println("Finished")
    }
    println(input)
}

fun getExternalInput():String{
    throw IOException("Could not read external input")
}