android鞏固-kotlin第一篇
摘要:
前言
開發工具
android sutdio
IntelliJ IDEA 2018.3.3 x64
基礎部分使用Intellij IDEA
資料
image
kotlin官網教程
官方語法
...
前言
開發工具
- android sutdio
- IntelliJ IDEA 2018.3.3 x64
基礎部分使用Intellij IDEA
資料

image
kotlin官網教程
官方語法

image
[菜鳥課程](http://www.runoob.com/kotlin/kotlin-basic-syntax.html ]
github地址
視訊教程
資料
基礎示例
// 類的定義(構造方法的引數) class Greeter(val name: String) { // 函式的定義 fun greet() { println("Greeter Hello,$name") } } //包級的可見函式,接受一個字串陣列作為引數 fun main(args: Array<String>) { println("Hello World!") // 物件的建立,不需要使用new關鍵字 Greeter("World!").greet() }
函式
//包級可見函式 test fun test() { println("main.test method run ...") } // 包級可見物件 Runnob class Runnob { fun tech(name: String) { println("上課,學習 $name") } } /* -------------- 函式定義 -------------- */ // fun(引數:引數型別):返回值型別 fun sum(a: Int, b: Int): Int { return a + b } // 表示式作為函式體:返回型別自動判斷 fun add(a: Int, b: Int) = a + b // public 方法必須寫出返回型別 public fun update(a: Int, b: Int): Int = a + b // public 方法必須寫出返回型別,不寫不會報錯,可以正常執行 public fun update2(a: Int, b: Int) = a + b //無返回值的函式(類似java的void) fun printSum(a: Int, b: Int): Unit { println("result = ${a + b}") } // 如果返回的是Unit型別,則可以省略(對於public也可以這樣) public fun printSum2(a: Int, b: Int) { println("result2 = ${a + b}") } /* -------------- 函式定義 -------------- */ /* -------------- 可變長度函式 -------------- */ //函式的可變長度使用vararg進行標識 fun fetch_add(vararg v: Int) { val sb = StringBuilder() sb.append("[ ") v.forEach { sb.append(it).append(",") } // 刪除所在位置的字串 sb.deleteCharAt(sb.length - 1) sb.append(" ]") println("引數: ${sb.toString()}") } /* -------------- 可變長度函式 -------------- */ /* -------------- lambda(匿名函式) -------------- */ fun m_lambda(x: Int, y: Int): Int { // 定義lambda函式 val sumLambda: (Int, Int) -> Int = { m, n -> m + n } // 使用 return sumLambda(x, y) } /* -------------- lambda(匿名函式) -------------- */ fun main(args: Array<String>) { println("hello sample01") test() Runnob().tech("英文") Runnob().tech("數學") Runnob().tech("化學") // 表示式: $val 引用變數 // 表示式: ${} 引用函式或其它公式 println("求合: ${sum(12, 55)}") println("表示式使用${12 + 15 * 3}") println("求合: ${add(100, 110)}") printSum(12, 35) printSum2(100, 199) // 可變長度函式 fetch_add(1, 2, 3, 4, 5) println("lambda(匿名函式): ${m_lambda(175, 33)}") }
變數和常量
/* -------------- 變數和常量 -------------- */ /* 可變變數: var 關鍵字 var 識別符號:型別 = 初始化值 不可變變數:val(相當於java中的final修飾的變數) val 識別符號:型別 = 初始化值 常量與變數都可以沒有初始化值,但是在引用前必須初始化 */ /* -------------- 變數和常量 -------------- */ /* -------------- 註釋 -------------- */ // 單行註釋 /* 多行註釋 */ /* -------------- 註釋 -------------- */ /* -------------- 字串模板 -------------- */ /* * $ 表示一個變數名或變數值 * $ varName 表示變數值 * $varName.fun() 表示變數的方法返回值 */ /* -------------- 字串模板 -------------- */ fun str_templete() { var a = 1 // 模板中的簡單名稱 val s1 = "a is $a" println("s1 is $s1") a = 2 // 模板中的任意表達式 val s2 = "${s1.replace("is", "was")},but now is $a" println("s2 is $s2") } /* -------------- 字串模板 -------------- */ /* -------------- NULL檢查機制 -------------- */ /* * kotlin的空安全設計對於宣告可為空的引數,在使用時要進行空判斷處理,有兩種處理方式 *欄位!! 像java一樣丟擲空異常 *欄位? 可不做處理返回值為null或配合?:做空判斷處理 */ // 空檢查機制 fun nul_check_mechanism() { // 表示ageStr可以為空 var ageStr: String? = "23" println("ageStr = $ageStr") ageStr = null println("ageStr = $ageStr") // 不做處理時,這裡會丟擲空指標的異常 val ageI = ageStr!!.toInt() println("ageI = $ageI") // Exception in thread "main" kotlin.KotlinNullPointerException //at Sample03_常量與變數Kt.nul_check_mechanism(sample03-常量與變數.kt:51) //at Sample03_常量與變數Kt.main(sample03-常量與變數.kt:87) val ageI2 = ageStr?.toInt() println("ageI2 = $ageI2") // 判斷ageStr是否為空如果為空則返回-1 val ageI3 = ageStr?.toInt() ?: -1 println("ageI3 = $ageI3") var addStr: String? = null var addStr2: String? = null println("addStr = $addStr , addrStr2 = $addStr2") } // 當str中的字串不是一個整數時,則返回null fun parseInt(str: String): Int? { //return Integer.parseInt(str) return str.toInt() } // Exception in thread "main" java.lang.NumberFormatException: For input string: "單價135" //fun parseInt2(str: String): Int? = Integer.parseInt(str) fun parseInt2(str: String): Int? { try { //return Integer.parseInt(str) return str.toInt() } catch (e: Exception) { return -1 } } /* -------------- NULL檢查機制 -------------- */ /* -------------- 型別檢測及自動型別轉換 -------------- */ // 可以使用is運算子判斷一個表示式是否是某型別的一個例項(類似於java的instanceof) fun getStrLength(obj: Any): Int? { if (obj is String) { // 做過型別判以後,obj會被系統自動轉換為String型別 return obj.length } // 這裡的obj仍然是Any型別的引用 return null } fun getStrLength_2(obj: Any): Int? { if (obj !is String) { return null } // 在這裡個分支,obj的型別自動轉換為String return obj.length } fun getStrLength_3(obj: Any): Int? { // && 運算子的右側,obj的型別會被自動轉換為String if (obj is String && obj.length > 0) { return obj.length } return null } /* -------------- 型別檢測及自動型別轉換 -------------- */ /* -------------- 區間 -------------- */ /* * 區間表示式由具有操作符形式..的rangeTo函式以in和!in形成 * 區間是為任何可比較型別定義的,但對於整形原生型別,它有一個優化的實現 */ fun t_range_t_01() { // 只能正向遍歷不能反向遍歷 for (i in 1..4) print(i) println() // 不會有任何輸出 for (j in 4..1) print(" $j , ") var k = 5 if (k in 1..10) { println(k) } // step指定步長值 // 正向操作 for (l in 1..4 step 2) { // 從1開始輸出,跳過2個。所以輸出的是1,+2 = 3 println(l) } // 反向操作 for (m in 4 downTo 1 step 2) { // 從4開始輸出,跳過2個。所以輸出的是4,-2 = 2 println(" $m , ") } // 使用until函式排除結束元素 for (n in 1 until 10) { // 排除10 print(" $n , ") } } /* -------------- 區間 -------------- */ fun main(args: Array<String>) { // 變數與常量 val a: Int = 1 // 系統自動判斷變數型別為Int val b = 1 //如果不在宣告時初始化則必須提供變數型別 val c: Int // 明確賦值 c = 5 println("常量 a = $a, b = $b, c = $c") var x = 5 // 系統自動判斷變數型別為Int x += 1 // Val cannot be reassigned //c+=2 //var z: Int // Error:(33, 30) Kotlin: Variable 'z' must be initialized //z = 10 // 變數宣告必須要初始化,不初始化會報錯 var z = 10 println("變數 x = $x, z = $z") // 字串模板 str_templete() //nul_check_mechanism() println("型別轉換: ${parseInt("135")}") println("型別轉換: ${parseInt2("單價135")}") println("getStrLength -> ${getStrLength("www.baidu.com")}") println("getStrLength_2 -> ${getStrLength_2(123)}") println("getStrLength_3 -> ${getStrLength_3('a')}") t_range_t_01() }
基本資料型別
/* -------------- 基本數值型別 -------------- */ /* 基本數值型別包括Byte,Short,Int,Long,Float,Double 字元不屬於數值型別,是一個獨立的資料型別 型別位寬度 Double64 Float32 Long64 Int32 Short16 Byte8 字面常量: 十進位制:123 長整型以大寫的L結尾:123L 十六進位制:以0x開頭:0x0F 二進位制:以0b開頭:0b00001011 不支援八進位制 Double:123.5 123.50 FLoat: f或F結尾:123.5f */ fun basic_data_type() { var age: Int = 23 var phoneNum: Long = 13244105539L var unit_price: Float = 31.5f var quantity: Double = 15000.5 var start_num: Short = 80 var mac_notebook: Byte = 0b00001011 println("age = $age") println("phoneNum = $phoneNum") println("unit_price = $unit_price") println("quantity = $quantity") println("start_num = $start_num") println("mac_notebook = $mac_notebook") var hexBytes = 0xFF_EC_DE_5E println("hexBytes = $hexBytes") // 十六進位制 println("十六進位制: 0X${Integer.toHexString(128)}") // 二進位制 println("二進位制: 0B${Integer.toBinaryString(128)}") // 8進位制 println("八進位制: 0${Integer.toOctalString(128)}") } /* -------------- 基本數值型別 -------------- */ /* -------------- 比較兩個數字 -------------- */ // === 比較物件地址,==比較兩個值大小 fun comare_num() { val a: Int = 10000 // 判斷值是否相等,物件地址是否相等 println(a === a) val b: Int = 10000 println(a === b) // 裝箱,建立兩個不同的物件,基本資料轉換為引用型別 // 值相等,地址不一樣 val boxedA: Int? = a val boxedB: Int? = b // 兩個物件的地址不一樣 // boxedA:@633 boxedB:@634 println(boxedA === boxedB) println(boxedA == boxedB) } /* -------------- 比較兩個數字 -------------- */ /* -------------- 型別轉換 -------------- */ /*較小型別並不是較大型別的子型別,較小的型別不能隱式轉換為較大的型別。 這意味著不進行顯示轉換的情況下,我們不能把一個Byte型值賦值給一個Int變數*/ //fun cast_type_00() { //val b: Byte = 1 //val i: Int = b //} fun cast_type_01() { val b: Byte = 1 val i: Int = b.toInt() } /* 每種資料型別都有下面轉換為其它型別的方法 toByte():Byte toShort():Short toInt():Int toLong():Long toFloat():Float toDouble():Double toChar():Char */ // 自動型別轉換,前提是可以根據上下文環境推斷出正確的資料型別而且數學操作符會做相應的過載。 //例: val l = 1L + 3 /* -------------- 型別轉換 -------------- */ /* -------------- 位操作符 -------------- */ // 對於Int和Long型別,位操作符可以使用 /* shl(bits) - 左移位(<<) shr(bits) - 右移位(>>) ushr(bits) - 無符號右移位(>>>) and(bits) - 與 or(bits) - 或 xor(bits) - 非 inv() - 反向 */ fun bit_opt() { println("4 左移 ${4.shl(1)}") println("4 右移 ${4.shr(1)}") println("-4 無符號右移位 ${-4.ushr(1)}") println("-4 反向 ${-4.inv()}") println("4 反向 ${4.inv()}") } /* -------------- 位操作符 -------------- */ /* -------------- 字元 -------------- */ /*kotlin中的char不能直接和數字操作,Char必須是''包含起來的 字元字面值用''括起來 特殊字元可以使用轉義,支援\t,\b,\n,\r,\',\",\\,\$ 編碼其它字元要用Unicode轉義 \uFF0 */ fun decimalDigitValue(c: Char): Int { if (c !in '0'..'9') throw IllegalArgumentException("Out of range") // 顯示轉換為數字 return c.toInt() - '0'.toInt() } /* -------------- 字元 -------------- */ /* -------------- 布林 -------------- */ /* 布林用 Boolean 型別表示,它有兩個值:true 和 false。 若需要可空引用布林會被裝箱。 &&(與) ||(或) !(非) */ fun t_bool() { var a: Int = 100 var b: Int = 35 println("${(a > 50) && (b < 100)}") a = -1 b = 10 println("${(a > 10) || (b > 0)}") println("${!((a != 0) || (b < 100))}") } /* -------------- 布林 -------------- */ /* -------------- 陣列 -------------- */ /* 陣列用類 Array 實現,並且還有一個 size 屬性及 get 和 set 方法,由於使用 [] 過載了 get 和 set 方法,所以我們可以通過下標很方便的獲取或者設定陣列對應位置的值。 陣列的建立兩種方式:一種是使用函式arrayOf();另外一種是使用工廠函式 [] 代表呼叫成員函式get()和set() Kotlin中的陣列是不可變型別的 除了Array,還有ByteArray,ShortArray,IntArray,用來表示各個型別的陣列,省去了裝箱的操作 */ fun t_arr() { val a = arrayOf(1, 2, 3) val b = Array(3, { i -> (i * 2) }) printIntArr(a) printIntArr(b) val x: IntArray = intArrayOf(1, 2, 3, 4) x[0] = x[1] + x[2] println("x[0] = ${x[0]}") } // 列印陣列中的內容(int) private fun printIntArr(b: Array<Int>) { print("[") val _last_item: Int = b[b.size - 1] for (i in b) { if (i != _last_item) print("$i,") else print("$i") } println("]") } /* -------------- 陣列 -------------- */ /* -------------- 字串 -------------- */ /*String是不可變的,[]可以很方便獲取字串中的某個字元,也可以通過for迴圈來遍歷*/ fun t_str() { val s_arr: String = "www.qq.com" val _last_str = s_arr[s_arr.length - 1] print("[") for (c in s_arr) { // 這裡使用==,===都可以,使用equals比較正則 if (_last_str.equals(c)) { print(" $c ") } else { print(" $c , ") } } println("]") } //kotlin支援""""""字串,支援多行字串 fun t_str2() { val txt_wel_world = """ Today I shed my old skin, which has too long suffered the bruises of failure and the wounds of mediocrity. Today I am born anew and my birthplace is a vineyard where there is fruit for all. """ println(txt_wel_world) // trimMargin 刪除多餘的空白,預設使用|用作邊界字首,可以使用其它字元並作為引數傳入trimMargin(">") val txt_wel_world2 = """ Today I shed my old skin, which has too long suffered the bruises of failure and the wounds of mediocrity. Today I am born anew and my birthplace is a vineyard where there is fruit for all. """.trimMargin() println(txt_wel_world2) } /* -------------- 字串 -------------- */ /* -------------- 字串模板 -------------- */ /* 字串可以包含模板表示式,會求值並把結果合併到字串中,模板表示式以$開頭,由一個簡單的名字構成 或使用{}起來的任意表達式 */ fun t_str_template() { val i = 10 val s = "i = $i" println(s) val weather_code = 10 // java中的三元運算子這裡不支援只能使用if...else進行轉換操作 println("今天天氣怎麼樣${if (weather_code > 0) "晴" else "陰"}") val s1 = "runoob" // runoob.length is 6 val str = "$s1.length is ${s1.length}" println(str) // 原生字串和轉義字串內部都支援模板。 如果你需要在原生字串中表示字面值 $ 字元(它不支援反斜槓轉義) val price = """ ${'$'}9.99 """.trimIndent() println(price) } /* -------------- 字串模板 -------------- */ fun main(args: Array<String>) { println("基本資料型別") basic_data_type() comare_num() println("l = $l") bit_opt() println("字元操作 ${decimalDigitValue('8')}") t_bool() t_arr() t_str() t_str2() t_str_template() }
條件控制
/* -------------- if表示式 -------------- */ /*一個if語句包含一個布林表示式或多條語句*/ fun t_if() { var a = 10 var b = 5 // 傳統用法 var max = a if (a < b) max = b println("傳統用法 max = $max") // 使用else if (a > b) { max = a } else { max = b } println("使用else max = $max") // 使用表示式 max = if (a > b) a else b println("使用表示式 max = $max") val _is_max = if (a > b) { print("choose a") a // 將a賦值給_is_max } else { print("choose b") b // 將b賦值給_is_max } println("使用表示式 _is_max = $_is_max") // java 的三元操作符,val c = if(condition) a else b } fun t_if_sample() { var x = 0 if (x > 0) { println("x 大於 0") } else if (x < 0) { println("x 小於 0") } else { println("x 等於 0") } var a = 1 var b = 2 var c = if (a >= b) a else b println("c 的值為 $c") } fun t_arange() { var x = 5 var y = 9 if (x in 1..8) { println("x 在區間內") } } /* -------------- if表示式 -------------- */ /* -------------- when表示式 -------------- */ /* when將它的引數和所有的分支條件順序比較,直到某個分支滿足條件 when 即可以被當做表示式使用也可以當做語句使用。如果它被當做表示式, 符合條件的分支值就是整個表示式的值,如果當做語句使用,則忽略個別分支的值 when 類似其它語言的switch */ fun t_when() { val x = 3 when (x) { 1 -> println("x==1") 2 -> println("x==2") else -> { println("x 不是 1, 也不是 2") } } } /* 在when中,else同switch 的default,如果其它分支都不滿足條件將會求else分支 如果很多分支需要用相同的方式處理,則可以把多個分支條件放在一起,用,分隔 */ fun t_when2() { val x = 2 when (x) { 1, 2 -> println("x == 1 or x == 2") else -> println("other wise") } } /*我們也可以檢測 一個值在(in)或不在(!in)一個區間或集合中*/ fun t_when3() { var x = 5 val validNumbers = arrayOf(2, 3, 5) when (x) { in 1..10 -> println("x is in the range") in validNumbers -> println(" x is valid") !in 10..20 -> println(" x is outside the range") else -> println("none of the above") } } /*另一種可能性是檢測一個值是(is)或不是(!is)一個特定型別的值。注意: 由於智慧轉換,你可以訪問該型別的方法和屬性而無需任何額外的檢測*/ fun hasPrefix(x: Any): Boolean { // 如果是字串返回pr var x1 = when (x) { is String -> { x.startsWith("prefiex") true } else -> { false } } return x1 } fun hasPrefix2(x: Any) { // 如果是字串返回pr when (x) { is String -> { x.startsWith("prefiex") } else -> { false } } } fun t_when4() { println("${hasPrefix(15)}") println("${hasPrefix("中國人的天下")}") println("${hasPrefix2(15)}") println("${hasPrefix2("中國人的天下")}") } // when 也可以用來取代 if-else if鏈。 如果不提供引數,所有的分支條件都是簡單的布林表示式,而當一個分支的條件為真時則執行該分支 fun t_when5() { val x = 15 when { //x.isOdd() -> println(" x is odd") //x.isEvent() -> println(" x is event") else -> { println("x is funny") } } } fun t_when_sample() { var x = 0 when (x) { 0, 1 -> println("x==0 or x==1") else -> println("otherwise") } when (x) { 1 -> println("x == 1") 2 -> println("x == 2") else -> println("x 不是1 也不是2") } when (x) { in 0..10 -> println("x在該區間範圍內") else -> println("x不在該區間範圍內") } } fun t_when_sample2() { val items = setOf("apple", "banna", "kiwi") when { "orange" in items -> println("juicy") "apple" in items -> println("apple if fine too") } } /* -------------- when表示式 -------------- */ fun main(args: Array<String>) { t_if() t_if_sample() t_arange() t_when() t_when2() t_when3() t_when4() t_when_sample() t_when_sample2() }
迴圈控制
/* -------------- For 迴圈 -------------- */ // for 迴圈可以對任何迭代器(iterator)的物件進行遍歷 for (item in collection) print(item) fun t_for_1() { val ages = arrayOf(22, 34, 55, 52, 51) for (age in ages) { println(age) } // 通過索引遍歷一個數組或者list for (index in ages.indices) { println("_index $index value = ${ages[index]}") } for ((index, value) in ages.withIndex()) { println("item at $index value is $value") } } fun t_for_sample() { val items = listOf("apple", "banana", "kiwi") for (item in items) { println(item) } for (index in items.indices) { println("item at $index value is ${items[index]}") } } /* -------------- For 迴圈 -------------- */ /* -------------- while 與 do...while 迴圈 -------------- */ /* while最基本的迴圈 while(a){ // 迴圈內容 } do..while迴圈對於while,如果不滿足條件,則不會進行迴圈,即使條件不滿足,do也會執行一次 do..while至少會執行一次 do{ }while(a) */ fun t_do_while() { println("t_do_while run ...") var x = 5 while (x > 0) println(x--) var y = 5 do { println(y--) } while (y > 0) y = -1 do { println(y--) } while (y > 0) } /* -------------- while 與 do...while 迴圈 -------------- */ /* -------------- 返回和跳轉 -------------- */ /* *return 跳出函式和迴圈 *break 終止迴圈 *continue 繼續下一次迴圈 */ fun t_r_b_c() { println("t_r_b_c run ...") val i = 7 for (i in 1..10) { // 繼續下一次迴圈 if (i == 3) continue println(i) // 退出迴圈 if (i > 5) break } } /*break&continue * 在 Kotlin 中任何表示式都可以用標籤(label)來標記。 標籤的格式為識別符號後跟 @ 符號,例如:abc@、fooBar@都是有效的標籤。 * 要為一個表示式加標籤,我們只要在其前加標籤即可。 * * 巢狀迴圈可以使用 * 標籤限制的 break 跳轉到剛好位於該標籤指定的迴圈後面的執行點。 * continue 繼續標籤指定的迴圈的下一次迭代。 */ fun t_b_c() { println("t_b_c run ...") val i = 7 loop@ for (i in 1..100) { // 繼續下一次迴圈 if (i == 3) continue println(i) // 退出迴圈 if (i > 5) break@loop } } /* -------------- 返回和跳轉 -------------- */ /* -------------- 標籤處返回 -------------- */ /* Kotlin 有函式字面量、區域性函式和物件表示式。因此 Kotlin 的函式可以被巢狀。 標籤限制的 return 允許我們從外層函式返回。 最重要的一個用途就是從 lambda 表示式中返回。回想一下我們這麼寫的時候: fun foo() { ints.forEach { if (it == 0) return print(it) } } 這個 return 表示式從最直接包圍它的函式即 foo 中返回。 (注意,這種非區域性的返回只支援傳給行內函數的 lambda 表示式。) 如果我們需要從 lambda 表示式中返回,我們必須給它加標籤並用以限制 return。 fun foo() { ints.forEach lit@ { if (it == 0) return@lit print(it) } } 現在,它只會從 lambda 表示式中返回。通常情況下使用隱式標籤更方便。 該標籤與接受該 lambda 的函式同名。 fun foo() { ints.forEach { if (it == 0) return@forEach print(it) } } 或者,我們用一個匿名函式替代 lambda 表示式。 匿名函式內部的 return 語句將從該匿名函式自身返回 fun foo() { ints.forEach(fun(value: Int) { if (value == 0) return print(value) }) } 當要返一個回值的時候,解析器優先選用標籤限制的 return,即 return@a 1 意為"從標籤 @a 返回 1",而不是"返回一個標籤標註的表示式 (@a 1)"。 */ fun t_nest_loop() { val nums = arrayOf(3, 1, 15, 44, 22, 8, 79) // 正序 for (i in nums.indices) { for (j in nums.indices) { if (nums[i] < nums[j]) { var tmp = nums[i] nums[i] = nums[j] nums[j] = tmp } } } print("[ ") for ((index, value) in nums.withIndex()) { if (index != nums.size - 1) { print("$value , ") } else { println("$value ]") } } // 倒序 for (i in nums.indices) { for (j in nums.indices) { if (nums[i] > nums[j]) { var tmp = nums[i] nums[i] = nums[j] nums[j] = tmp } } } print("[ ") for ((index, value) in nums.withIndex()) { if (index != nums.size - 1) { print("$value , ") } else { println("$value ]") } } } /* -------------- 標籤處返回 -------------- */ fun main(args: Array<String>) { println("main run ...") t_for_1() t_for_sample() t_do_while() t_r_b_c() t_b_c() t_nest_loop() }