1. 標識符
特定標識符field和it。在Kotlin語言中有兩個由編譯器定義的特定標識符,它們只能在特定場景中使用有特定的作用,而在其他的場景中可以做標識符使用。
提示:field標識符用於屬性訪問器中,訪問屬性支持字段;it標識符用於Lambda表達式中,在省略參數列表時作爲隱式參數,即不需要聲明就可以使用的參數。
// 創建一個字符串數組
var arrays = arrayListOf("A", "B", "C")
// 遍歷
arrays.forEach { println(it) }
2. 關鍵字
Kotlin語言中有70多個關鍵字,全部是小寫英文字母,以及!和?等字符構成。分爲3個大類:
硬關鍵字(Hard Keywords),硬關鍵字任何情況下都不能作爲標識符,具體包括如下關鍵字。
as、as?、break、class、continue、do、else、false、for、fun、if、in、!in、interface、is、!is、null、object、package、 return、super、this、throw、true、try、typealias、val、var、when和while。
軟關鍵字(Soft Keywords),是在它適用場景中不能作爲標識符,而其他場景中可以作爲標識符,具體包括如下關鍵字。
by、catch、constructor、delegate、dynamic、field、file、finally、get、import、init、param、property、receiver、set、
setparam和where。
修飾符關鍵字(Modifier Keywords),修飾符關鍵字是一種特殊的軟關鍵字,它們用來修飾函數、類、接口、參數和屬性等內容,在此場景中不能作爲標識符。而其他場景中可以作爲標識符,具體包括如下關鍵字。
abstract、annotation、companion、const、crossinline、data、enum、external、final、infix、inner、internal、lateinit、
noinline、open、operator、out、override、private、protected、public、reified、sealed、suspend、tailrec和vararg。
3. 變量和常量
1. 變量
在Kotlin中聲明變量,就是在標識符的前面加上關鍵字var。
var str = "kotlin"
var i = 0
var price: Float = 10.08f
2. 常量和只讀變量
常量和只讀變量一旦初始化後就不能再被修改。在Kotlin聲明常量是在標識符的前面加上val或const val關鍵字.
它們的區別如下。
val聲明的是運行期常量,常量是在運行時初始化的。
const val聲明的是編譯期常量,常量是在編譯時初始化,只能用於頂層常量聲明或聲明對象中的常量聲明,而且只能是String 或基本數據類型(整數、浮點等)。
提示: 編譯期常量(const val)相當於Java中public final static所修飾的常量。而運行期常量(val)相當於Java中final所修飾的 常量。
const val str = "compile kotlin" // 申明頂層常量
//聲明對象
object UserDAO {
const val MAX_COUNT = 100 // 對象中的聲明常量
}
fun main(args: Array<String>) {
val price: Float = 0.0f
val y = 20
}
約定: 常量其實就是隻讀變量,編譯期常量(const val)是更爲徹底的常量,一旦編譯之後就不能再修改了。而運行期常(val)還可以根據程序的運行情況初始化。
使用var還是val?
原則: 如果兩種方式都能滿足需求情況下,原則上優先考慮使用val聲明。因爲一方面val聲明的變量是隻讀,一旦初始化後不 能修改,這可以避免程序運行過程中錯誤地修改變量內容;另一方面在聲明引用類型使用val,對象的引用不會被修改,但是
引用內容可以修改,這樣會更加安全,也符合函數式編程的技術要求。
4. 表達式
val score = 80
// if控制結構表達式
val result = if (score < 60) "不及格" else "及格"
//try表達式
val score = try {
//TODO
} catch (e: Exception) {
return
}
5. 類的聲明
data class Order(var id: Long, var date: Date)
6. Unit
如果一個函數的返回類型是Unit,則需要省略。Kotlin的Unit關鍵字相當於Java中的void,表示返回空的數據,用於函數的返回 類型聲明.
7. 基本數據類型
整數類型:Byte、Short、Int和Long,Int是默認類型。
浮點類型:Float和Double,Double是默認類型。
字符類型:Char。
布爾類型:Boolean。
8. 非空類型和可空類型
Kotlin語言,默認情況下所有的數據類型都是非空類型(Non-Null),聲明的變量都是不能接收空值(null)的。
var n: Int = 10
n = null //發生編譯錯誤
Kotlin爲每一種非空類型提供對應的可空類型(Nullable),就是在非空類型後面加上問號(?)表示可空類型。
var n: Int? = 10
n = null //可以接收空值(null)
可空類型在具體使用時會有一些限制:
不能直接調用可空類型對象的函數或屬性。
不能把可空類型數據賦值給非空類型變量。
不能把可空類型數據傳遞給非空類型參數的函數。
爲了“突破”這些限制,Kotlin提供瞭如下運算符:
安全調用運算符:?.
可空類型變量使用安全調用運算符(?.)可以調用非空類型的函數或屬性。安全調用運算符(?.)會判斷可空類型變量是否爲空,如果是則不會調用函數或屬性,直接返回空值;否則返回調用結果。
fun main(args: Array<String>) {
val divNumber1 = divide(100, 0)
val result1 = divNumber1?.plus(100) //divNumber1+100,結果null
println(result1)
val divNumber2 = divide(100, 10)
val result2 = divNumber2?.plus(100) //divNumber2+100,結果110.0
println(result2)
}
//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
if (n2 == 0) {//判斷分母是否爲0
return null
}
return n1.toDouble() / n2
}
安全轉換運算符:as?
Elvis運算符:?:
有的時候在可空類型表達式中,當表達式爲空值時,並不希望返回默認的空值,而是其他數值。此時可以使用Elvis運算符 (?:),也稱爲空值合併運算符,Elvis運算符有兩個操作數,假設有表達式:A ?: B,如果A不爲空值則結果爲A;否則結 果爲B。
fun main(args: Array<String>) {
val divNumber1 = divide(100, 0)
val result1 = divNumber1?.plus(100) ?: 0 //divNumber1+100,結果0
println(result1)
val divNumber2 = divide(100, 10)
val result2 = divNumber2?.plus(100) ?: 0 //divNumber2+100,結果110.0
println(result2)
}
//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
if (n2 == 0) {//判斷分母是否爲0
return null
}
return n1.toDouble() / n2
}
非空斷言:!!
可空類型變量可以使用非空斷言運算符(!!)調用非空類型的函數或屬性。非空斷言運算符(!!)顧名思義就是斷言可空類 型變量不會爲空,調用過程是存在風險的,如果可空類型變量真的爲空,則會拋出空指針異常;如果非則可以正常調用函 數或屬性。
fun main(args: Array<String>) {
val divNumber1 = divide(100, 10)
val result1 = divNumber1!!.plus(100) //divNumber1+100,結果110.0
println(result1)
val divNumber2 = divide(100, 0)
val result2 = divNumber2!!.plus(100) //divNumber2+100,結果拋出異常
println(result2)
}
//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
if (n2 == 0) {//判斷分母是否爲0
return null
}
return n1.toDouble() / n2
}
此外,還一個let函數幫助處理可空類型數據。
9. 字符串模板
字符串模板是以$開頭,語法如下:
$變量或常量
${表達式} //任何表達式,也可以是單個變量或常量
val age = 18
val s1 = "她的年齡是${age}歲。" //使用表達式形式模板
println(s1) //她的年齡是18歲。
val score = 'A'
val s2 = "她的英語成績是$score" //使用變量形式模板
println(s2) //她的英語成績是A
val now = java.util.Date()
val s3 = "今天是:${now.year + 1900}年${now.month}月${now.day}日" ③
println(s3)
10 . 其它運算符
冒號(:)。用於變量或常量類型聲明,以及聲明繼承父類和實現接口。
小括號。起到改變表達式運算順序的作用,它的優先級最高。
中括號([])。索引訪問運算符號。
引用號(.)。調用函數或屬性運算符。
賦值號(=)。賦值是用等號運算符(=)進行的。
可空符(?)。標識一個可空類型。
安全調用運算符(?.)。調用非空類型的函數或屬性。
Elvis運算符(?:)。空值合併運算符。
非空斷言(!!)。斷言可空表達式爲非空。
雙冒號(::)。引用類、屬性或函數。
區間(..)。表示一個範圍區間。
箭頭(->)。用來聲明Lambda表達式。
展開運算符(*)。將數組傳遞給可變參數時使用
運算符優先級大體順序,從高到低是:算術運算符→位運算符→關係運算符→邏輯運算符→賦值運算符。
11. 程序流程控制
分支結構:if和when
循環結構:while、do-while和for
跳轉結構:break、continue和return
when多分支結構:
1. when結構當做語句使用
when (表達式) {
分支條件表達式1 -> {
語句組1
}
分支條件表達式2 -> {
語句組2
}
...
分支條件表達式n -> {
語句組n
}
else -> {
語句組n+1
}
}
fun main(args: Array<String>) {
val testScore = 75 //設定一個數值用來測試
when (testScore / 10) {
9 -> {
println('優')
}
8 -> println('良')
7, 6 -> println('中')
else -> println('差')
}
val level = "優" //設定一個數值用來測試
var desc = "" //接收返回值
when (level) {
"優" -> desc = "90分以上"
"良" -> desc = "80分~90分"
"中" -> desc = "70分~80分"
"差" -> desc = "低於60分"
}
println("說明 = " + desc)
}
break 配合標籤使用
label1@ for (x in 0..4) {
for (y in 5 downTo 1) {
if (y == x) {
// 跳轉到label1指向的外循環
break@label1
}
println("(x,y) = ($x,$y)")
}
}
println("Game Over!")
Kotlin核心庫中有三個閉區間類:IntRange、LongRange和CharRange
區間中的元素只能是整數或字符,不能是浮點、字符串等其他數據類型。
在Kotlin語言中閉區間採用區間運算符(..)表示,而半開區間則需要使用中綴運算符until表示。
fun main(args: Array<String>) {
for (x in 0..5) { //定義閉區間包含0和5
print("$x,")
}
println()
for (x in 0 until 5) { //定義半開區間包含0,不包含5
print("$x,")
}
println()
for (x in 'A'..'E') { //定義閉區間包含'A'和'E'
print("$x,")
}
println()
for (x in 'A' until 'E') { //定義半開區間包含'A',不包含'E'
print("$x,")
}
}
12. 使用in和!in關鍵字
判斷一個數值是否在區間中可以使用in關鍵字。而!in關鍵字,則是判斷一個值不在區間中。此外,這兩個關鍵字(in和!in)還 可以判斷一個數值是否集合或數組中。
fun main(args: Array<String>) {
var testscore = 80 //設置一個分數用於測試
var grade = when (testscore) {
in 90..100 -> "優"
in 80 until 90 -> "良"
in 60 until 80 -> "中"
in 0 until 60 -> "差"
else -> "無"
}
println("Grade = " + grade)
if (testscore !in 60..100) { //使用!in關鍵字
println("不及格")
}
val strArray = arrayOf("劉備", "關羽", "張飛")
val name = "趙雲"
if (name !in strArray) {
println(name + "不在隊伍中")
}
}
13. 函數
fun 函數名(參數列表) : 返回值類型 {
函數體
return 返回值
}
無返回數據與Unit類型
有的函數只是爲了處理某個過程,不需要返回具體數據,例如println函數。此時可以將函數返回類型聲明爲Unit,相當於Java 中的void類型,即表示沒有實際意義的數據。
fun printArea2(width: Double, height: Double) { //省略Unit
val area = width * height
println("$width x $height 長方形的面積:$area")
//省略return
}
永遠不會正常返回數據與Nothing類型
Kotlin中提供一種特殊的數據類型Nothing,Nothing只用於函數返回類型聲明,不能用於變量聲明。Nothing聲明的函數永遠不 會正常的返回,只會拋出異常。
fun readDate(): Nothing {
throw IOException()
}
提示: 使用Nothing的目的何在?有些框架,例如Junit單元測試框架,在測試失敗時會調用Nothing返回類型的函數,通過它拋出異常使當前測試用例失敗。
注意 Unit與Nothing區別?Unit表示數據沒有實際意義,它可以聲明函數返回類型,也可以聲明變量類型,聲明函數時函數可以正常返回,只是返回數據沒有實際意義。Nothing只能聲明函數返回類型,說明函數永遠不會正常返回,Nothing不能聲
明變量。
可變參數
Kotlin中函數的參數個數可以變化,它可以接受不確定數量的輸入類型參數(這些參數具有相同的類型),有點像是傳遞一個數組。可以通過在參數名前面加vararg關鍵字的方式來表示這是可變參數。
fun sum(vararg numbers: Double, multiple: Int = 1): Double {
var total = 0.0
for (number in numbers) {
total += number
}
return total * multiple
}
表達式函數體
fun rectangleArea(width: Double, height: Double) = width * height
Kotlin中的類成員包括:
構造函數
初始化代碼塊
成員函數
屬性
內部類和嵌套類
對象表達式聲明
// 員工類
class Employee {
var no: Int = 0 // 員工編號屬性
var job: String? = null // 工作屬性
var firstName: String = "Tony"
var lastName: String = "Guan"
var fullName: String //全名
get() {
return firstName + "." + lastName
}
set (value) {
val name = value.split(".")
firstName = name[0]
lastName = name[1]
}
var salary: Double = 0.0 // 薪資屬性
set(value) {
if (value >= 0.0) field = value
}
}
提示: 屬性本身並不真正的保存數據,數據被保存到支持字段中,支持字段一般是不可見的,支持字段只能應用在屬性訪問器中,通過系統定義好的field變量訪問。
提示: 並不是所有的屬性都有支持字段的,例如上述代碼中的fullName屬性是通過另外屬性計算而來,它沒有支持字段,聲明時不需要初始值。這種屬性有點像是一個函數。這種屬性在Swift語言中稱爲計算屬性。