605 lines
20 KiB
Markdown
605 lines
20 KiB
Markdown
### 1. Kotlin應用開發初體驗
|
||
- 安裝[IntelliJ IDEA](https://www.jetbrains.com/idea/)
|
||
- 在.kt檔案寫一個`main()`,旁邊會出現小箭頭,就可以直接執行。
|
||
![[Pasted image 20201225114228.png]]
|
||
|
||
- 註解
|
||
- `//`: 以兩個斜線(`/`)開頭就是註解,會被編譯器忽略
|
||
- `/* 這行文字是註解 */`: 這是另一種註解,被`/*`與`*/`包圍起來的區段都是註解,這種方可以跨行註解,但是注意,`/* */`裡面不可以再有另一個`/* */`方式的註解。
|
||
|
||
### 2. 變數、常數和類型
|
||
#### 定義一個「可變」變數
|
||
```Kotlin
|
||
var experiencePoints: Int = 5
|
||
--- --- -
|
||
^ ^ ^
|
||
| | |
|
||
| | Assign value
|
||
| Type
|
||
Keyword
|
||
```
|
||
使用`var`所定義的變數可以再度被改變,例如:
|
||
```
|
||
experiencePoints = 10
|
||
```
|
||
就會把`experiencePoints`的值變為10。
|
||
|
||
#### 定義一個「唯讀」變數
|
||
使用`val`所定義的變數不可以再被改變,例如,定義一個名叫`myLuckyNumber`的「唯讀」變數:
|
||
```Kotlin
|
||
val myLuckyNumber: Int = 7
|
||
|
||
myLuckyNumber = 10 <-- ERROR!
|
||
```
|
||
|
||
#### 要用哪一種方式來定義?
|
||
應該優先使用`val`來定義變數,遇到變數需要改變的時候再來把`val`換成`var`。這總比有人寫出了bug,不小心改動了變數而造成玲成錯誤來的好。明確的錯誤總是比較容易解決。
|
||
|
||
#### 類型推斷
|
||
Kotlin是一個強型別的語言,每一個變數都要有一個明確的「類型」。但Kotlin也有類型推斷的能力。例如:
|
||
```
|
||
val myLuckyNumber: Int = 7
|
||
```
|
||
因為很明確的`myLuckyNumber`要指定為7,7是一個整數(`Int`),所以`Int`可以忽略,如下:
|
||
```
|
||
val myLuckyNumber = 7
|
||
```
|
||
在IntellJ中,把游標停在變數上,按下`Ctrl + Shift + P`你會看到它推斷出來的類型:
|
||
![[Pasted image 20201225120335.png]]
|
||
|
||
#### 常數
|
||
用`const val`來定一一個常數(不會變的)
|
||
```
|
||
const val MAX_SCORE = 100
|
||
```
|
||
`const val`是編譯時就定義好的,不同於`val`是執行時期才設定的。
|
||
|
||
#### 深入學習
|
||
Java中有兩種類型:「參照類型」(reference types)與「基礎類型」(primitive types)
|
||
參照類型有對應的code,大都是一個class。基礎類型則沒有,由keyword表示。
|
||
Java的「參照類型」都是大寫開頭,例如:
|
||
```
|
||
Integer point = 5;
|
||
```
|
||
基礎類型則是
|
||
```
|
||
int point = 5;
|
||
```
|
||
|
||
但在Kotlin中只有「參照類型」,也就是說基礎類別都是大寫,像是`Int`、`String`、`Double`、`Boolean`...等等。
|
||
雖然說Compiler會有條件的把參照類型轉為基礎類型來增加效率,但對於開發者來說大都是不需在意的。
|
||
|
||
### 3. 條件運算式
|
||
#### if/else
|
||
語法
|
||
```kotlin
|
||
if (<condition>) {
|
||
// code block if <condition> is true
|
||
} else {
|
||
// code block if <condition> is false
|
||
}
|
||
```
|
||
當`<condition>`為`true`的時候,`if`區塊裡面的code就會被執行
|
||
|
||
##### 多重條件
|
||
當有多個condition的時候,可以用`else if`來增加條件,如下:
|
||
```kotlin
|
||
if (<condition_1>) {
|
||
// code block if <condition_1> is true
|
||
} else if (<condition_2>) {
|
||
// code block if <condition_2> is true
|
||
} else if (<condition_3>) {
|
||
// code block if <condition_3> is true
|
||
else {
|
||
// code block if doesn't match any conditions.
|
||
}
|
||
```
|
||
|
||
##### 比較運算子
|
||
Kotlin使用的比較運算子如下
|
||
- `<`: 左側值是否「小於」右側值
|
||
- `<=`: 左側值是否「小於等於」右側值
|
||
- `>`: 左側值是否「大於」右側值
|
||
- `>=`: 左側值是否「大於等於」右側值
|
||
- `==`: 左側值是否「等於」右側值
|
||
- `!=`: 左側值是否「不等於」右側值
|
||
- `===`: 左側的reference是否「等於」右側的reference
|
||
- `!==`: 左側的reference是否「不等於」右側的reference
|
||
|
||
##### 邏輯運算子
|
||
- `&&`: AND
|
||
- `||`: OR
|
||
- `!`: NOT
|
||
|
||
##### 條件運算式
|
||
`if/else`運算式可以直接指派給一個變數,區塊內的最後一行會被當成回傳值設定給變數,例如:
|
||
```
|
||
val color = if (type == "tree") {
|
||
println("type is tree")
|
||
"GREEN" // <- 最後一行會是return value
|
||
} else {
|
||
println("type is not tree")
|
||
"WHITE" // <- 最後一行會是return value
|
||
}
|
||
```
|
||
|
||
|
||
#### range
|
||
Kotlin使用`..`來代表一個範圍,例如`1..5`會等於`1, 2, 3, 4, 5`。
|
||
在`if/else`裡面可以用來代替`>`, `<`之類的邏輯運算,例如:
|
||
```
|
||
if (score in 90..100) {
|
||
println("A")
|
||
} else if (score in 80..89) {
|
||
println("B")
|
||
} else {
|
||
println("C")
|
||
}
|
||
```
|
||
|
||
`..`必須左邊小於右邊,若是要由大到小必須使用`downTo`:
|
||
```
|
||
3 downTo 1 // 3, 2, 1
|
||
```
|
||
另外,跟`..`類似的`until`,差異是`until`不包含右邊的值:
|
||
```
|
||
1 until 3 // 1, 2
|
||
1..3 // 1, 2, 3
|
||
```
|
||
|
||
上述操作也可以轉成list,呼叫`.toList()`即可:
|
||
```
|
||
(1..3).toList() // [1, 2, 3]
|
||
(3 downTo 1).toList() // [3, 2, 1]
|
||
```
|
||
|
||
#### when
|
||
`when`類似C語言的`switch`,但是`when`更加靈活。先看一個例子:
|
||
```
|
||
val comment = when (score) {
|
||
100 -> "Excellent"
|
||
in 90..99 -> "A"
|
||
in 80..89 -> "B"
|
||
else -> "C"
|
||
}
|
||
```
|
||
`when`會將score與`->`左邊的值做比較,要是成立就執行`->`右邊的區塊,跟`if/else`的條件運算一樣,執行區塊內的最後一行會被return並指派給變數:
|
||
```
|
||
val score = 99
|
||
val name = "Bond"
|
||
val comment = when (score) {
|
||
100 -> {
|
||
val message = "$name, you're Excellent
|
||
message // <- 最後一行會是return value
|
||
}
|
||
in 90..99 -> {
|
||
val message = "$name, you got A"
|
||
message // <- 最後一行會是return value
|
||
}
|
||
in 80..89 -> {
|
||
val message = "$name, you got B"
|
||
message // <- 最後一行會是return value
|
||
}
|
||
else -> {
|
||
val message = "$name, you got C"
|
||
message // <- 最後一行會是return value
|
||
}
|
||
}
|
||
```
|
||
|
||
#### String範本
|
||
用`$`開頭可以將變數的值帶入字串之中,例如:
|
||
```
|
||
val score = 100
|
||
println("My score is $score") // -> 印出"My score is 100"
|
||
```
|
||
另外,若用`${}`,Kotlin會先將`{}`區塊求值,如此一來就可以很方便地在字串內做一些簡單處理或運算:
|
||
```
|
||
val a = 5
|
||
val b = 6
|
||
val result = "Result = ${a + b}"
|
||
```
|
||
|
||
|
||
### 4. 函數
|
||
#### 函數的結構
|
||
一個函數的結構如下
|
||
```kotlin
|
||
private fun functionName(arg1: String, arg2: Int): String {
|
||
// function body
|
||
}
|
||
```
|
||
- `private`是「可見性修飾符」,若是在檔案中,則這個function只有在檔案中是可見的。
|
||
- `fun functionName`是「函數名稱宣告」,宣告一個函數的開始,其中functionName可以自己命名。
|
||
- `(arg1: String, arg2: Int)`: 參數。每一組參數由`,`隔開。開頭是參數的名稱,`:`後面是參數的類型。以此例來說,有2組參數,第一組的參數叫做`arg1`,類型是`String`。第二組的參數叫做`arg2`,類型是`Int`。
|
||
- `{ }`裡面是是函數運算本體。
|
||
|
||
#### 預設引數
|
||
參數可以有一個預設值。例如下例:
|
||
```
|
||
fun sayHello(name: String): String {
|
||
return "Hello $name!"
|
||
}
|
||
```
|
||
一定要傳入一個名字,我們可以預設讓它接受一個空字串,讓他單純說聲"Hello"就好。
|
||
```
|
||
fun sayHello(name: String=""): String {
|
||
return "Hello $name!"
|
||
}
|
||
```
|
||
如此一來,使用者可以直接呼叫`sayHello()`就可以得到字串了。
|
||
|
||
#### 單運算式函數
|
||
對於單純只有一行的函數,我們可以簡化函數的寫法,把大括號省略掉。以上面`sayHello()`的例子來說,可以簡略如下:
|
||
```
|
||
fun sayHello(name: String=""): String = "Hello $name!"
|
||
```
|
||
|
||
#### Unit函數
|
||
對於沒有返回值的函數,其返回值不是`void`,而是`Unit`。這類函數叫做「Unit函數」。
|
||
|
||
#### 具名函數引數
|
||
呼叫函數時,一定要按照函數所定義的參數順序來填寫,否則會出錯,假設有一個函數定義如下:
|
||
```
|
||
fun getDiscountPrice(price: float, discount: float): float {
|
||
return price * (1.0 - discount)
|
||
}
|
||
```
|
||
價錢與折數的順序要是錯位就會造成錯誤,這時候,呼叫函數時明確寫出參數名字可以避免這個情形:
|
||
```
|
||
val newPrice = getDiscountPrice(price = 1000.0,
|
||
discount = 0.3)
|
||
```
|
||
一旦使用具名引數,順序不對也沒有關係,像下面這樣寫也是可以的:
|
||
```
|
||
val newPrice = getDiscountPrice(discount = 0.3,
|
||
price = 1000.0)
|
||
```
|
||
|
||
#### Nothing類型
|
||
`Nothing`表示不可能執行成功。Kotlin標準程式庫的`TODO()`可以給一個經典的用法:
|
||
```
|
||
public inline fun TODO(): Nothing = throw NotImplementedError()
|
||
```
|
||
我們可以把TODO()用在還沒完成的函數上,例如:
|
||
```
|
||
fun notOkFunc(arg1: Int): Int {
|
||
TODO("Someone finsih this")
|
||
println("I don't want to implemnt this...") // <- This line is unreachable
|
||
}
|
||
```
|
||
因為某種原因`notOkFunc()`沒有實作完成,它也沒有返回一個`Int`的結果。但因為TODO()返回Nothing的關係,所以編譯器就忽略了這個檢查,反正它會執行失敗。
|
||
|
||
#### 奇怪的函數名
|
||
一般來說函數的名字並不可以有空白或是一些特殊符號,但是Kotlin支援用「反引號」來定義有特殊名字的函數。例如:
|
||
```
|
||
fun `** Click to login **`(): Int {
|
||
...
|
||
}
|
||
```
|
||
呼叫時就變成:
|
||
```
|
||
val loginResult = `** Click to login **`()
|
||
```
|
||
但支援這種語法的主要原因是為了可以呼叫Java的API,例如,Java有一個叫做`is()`的函數,但是`is`是Kotlin的保留字(用來檢查類型),所以在Kotlin裡面要呼叫Java的`is()`就必須使用這個方法,例如:
|
||
```
|
||
fun callJavaIsInKotlin() {
|
||
`is`() // <- Invokes is() function from Java
|
||
}
|
||
```
|
||
|
||
### 5. 匿名函數與函數類型
|
||
#### 匿名函數
|
||
在`{}`裡面,沒有名字的就是匿名函數,定義一個簡單的匿名函數:
|
||
```
|
||
{
|
||
println("Hello")
|
||
}
|
||
```
|
||
呼叫這個匿名函數:
|
||
```
|
||
{
|
||
println("Hello")
|
||
}()
|
||
```
|
||
其實就跟呼叫一般函數一樣,只是`()`之前是一個函數本體,而不是函數名稱。
|
||
匿名函數在Kotlin叫做lambda,以後都用lambda來稱呼匿名函數。
|
||
|
||
#### 隱式返回
|
||
lambda預設會返回「最後一行」,而且**不能呼叫**`return`。這是因為編譯器不知道返回資料是來自於lambda或是lambda的呼叫者。
|
||
下面這個無聊的lambda會返回一個字串:
|
||
```
|
||
{
|
||
"Hello"
|
||
}
|
||
```
|
||
|
||
#### lambda類型
|
||
lambda本身是一個類型(type),所以lambda也可以指定給變數。如以下例子:
|
||
```kotlin
|
||
val get5 = {
|
||
val a = 2
|
||
val b = 3
|
||
a + b // 最後一行為返回值
|
||
}
|
||
|
||
// 呼叫lambda
|
||
val number = get5()
|
||
```
|
||
lambda類型是由lambda的輸入參數、輸出類型所定義的。
|
||
|
||
#### lambda的參數與返回值
|
||
方法1:將參數類型與返回值定義在變數裡
|
||
```kotlin
|
||
val addResult: (a: Int, b: Int) -> Int = {
|
||
a + b
|
||
}
|
||
```
|
||
上面的例子定義了`addResult`這個lambda,輸入參數有`a`、`b`兩個,兩個的類型都是`Int`,返回值也是`Int`。`{}`內則是實作。
|
||
|
||
方法二:將參數類型與返回值定義在變數裡,參數命名則在函數本體裡
|
||
```kotlin
|
||
val addResult: (Int, Int) -> Int = {a, b ->
|
||
a + b
|
||
}
|
||
```
|
||
上面的例子定義了`addResult`這個lambda,輸入是兩個類型為Int的參數,返回類型也是Int,參數名稱`a`、`b`則定義在`{}`,這也表示參數名稱可以由lamdba提供者隨意修改。
|
||
|
||
#### lambda的類型推斷
|
||
如同編譯器可以自東推斷變數的類型,lambda的類型也可以自動推斷,例如:
|
||
```kotlin
|
||
val returnHello: () -> String = {
|
||
"Hello"
|
||
}
|
||
```
|
||
可以簡化成:
|
||
```kotlin
|
||
val returnHello = {
|
||
"Hello"
|
||
}
|
||
```
|
||
很顯然的,這一個沒有輸入參數,回傳值String的lambda。
|
||
對於有多個參數的lambda,則需要清楚的把參數的名字與類型都寫出來,例如:
|
||
```kotlin
|
||
val sayHello = { name: String, age: Int
|
||
"Hello, I'm $name, $age years old."
|
||
}
|
||
```
|
||
`sayHello()`的推斷類型是:輸入有兩個參數,一個是型別為String的name,另一個是型別為Int的age,然後根據[[20201218 - Kotlin權威2.0#隱式返回]],最後一行是回傳值,所以返回值是String型別。這寫法跟下面的寫法同意:
|
||
```kotlin
|
||
val sayHello: (String, Int) -> String = { name, age
|
||
"Hello, I'm $name, $age years old."
|
||
}
|
||
```
|
||
|
||
#### `it`關鍵字
|
||
當lambda只有一個參數的時候,可以用it來當參數的名字,例如:
|
||
```kotlin
|
||
val add5: (Int) -> Int = {
|
||
it + 5
|
||
}
|
||
```
|
||
使用it雖然方便但是對可讀性卻沒有比較好,這點自己權衡使用。
|
||
|
||
#### 將lambda當作參數
|
||
lambda可以當作參數傳給函數,只要在函數內定義好lambda的類型即可。例如,我們可以設計一個函數,接收不同「打招呼lamdba」來產生打招呼字串,我們先定義3個打招呼lambda:
|
||
1.
|
||
```kotlin
|
||
val sayHi = { name: String,
|
||
"Hi $name"
|
||
}
|
||
```
|
||
2.
|
||
```kotlin
|
||
val sayHello = { name: String,
|
||
"Hello $name"
|
||
}
|
||
```
|
||
3.
|
||
```kotlin
|
||
val sayGoodMornig = { name: String,
|
||
"Good mornig, $name"
|
||
}
|
||
```
|
||
這三個lambda都有同樣的型別,型別都是 (String) -> String,也就是輸入參數是一個String,返回值也是String。
|
||
接下來,定義我們要使用的函數:
|
||
```kotlin
|
||
fun greet(name: String, greetFunc: (String) -> String): String {
|
||
return greetFunc(name)
|
||
}
|
||
```
|
||
然後我們就可以這樣用:
|
||
```kotlin
|
||
val greetString1 = greet("John", sayHi)
|
||
val greetString2 = greet("John", sayHello)
|
||
val greetString3 = greet("John", sayGoodMornig)
|
||
```
|
||
|
||
#### 將lambda當作參數的簡略語法
|
||
如果lambda參數是函數的最後一個參數,那麼便可以使用簡略語法,我們用上面的例子一步一步來看。例如我們直接將`sayHi` lambda寫在`greet()`裡面:
|
||
```kotlin
|
||
val greetString1 = greet("John", { name: String ->
|
||
"Hi $name"
|
||
})
|
||
```
|
||
因為lambda是最後一個,所以可以將lambda移到外面來:
|
||
```kotlin
|
||
val greetString1 = greet("John") { name: String ->
|
||
"Hi $name"
|
||
}
|
||
```
|
||
又因為這個lambda只有一個參數,所以可以用`it`來簡化它,變成:
|
||
```kotlin
|
||
val greetString1 = greet("John") {
|
||
"Hi $it"
|
||
}
|
||
```
|
||
|
||
#### inline function
|
||
若想要避免lambda產生記憶體開銷,就可以使用`inline`關鍵字,`inline`關鍵字會函數在使用的地方展開,例如剛剛的sayHi例子,我們將使用lambda的`greet()`函數加上inline,變成:
|
||
```kotlin
|
||
inline fun greet(name: String, greetFunc: (String) -> String): String {
|
||
return greetFunc(name)
|
||
}
|
||
```
|
||
那麼`greet()`就會在呼叫處直接展開,就好像:
|
||
```kotlin
|
||
{
|
||
val result = "Hi $name"
|
||
return result
|
||
}
|
||
```
|
||
|
||
#### 將函數當作參數
|
||
用fun定義的函數也可以像lambda一樣當作參數,只是要在呼叫的時候在函數名前面加上`::`,例如:
|
||
```kotlin
|
||
fun sayHi(name: String): String {
|
||
return "Hi $name"
|
||
}
|
||
|
||
fun greet(name, greetFunc: (String) -> String): String {
|
||
val greetString = greetFunc(name)
|
||
return greetString
|
||
}
|
||
|
||
// 呼叫
|
||
greet("John", ::sayHi)
|
||
```
|
||
|
||
#### 在函數裡返回一個函數
|
||
若是將函數的返回值定義為相對應的函數類型,即可以返回函數,例如,我們可以設計一個函數,這個函數接受1、2、3三種數字,當使用者輸入1的時候,我們返回`sayHi`來讓使用呼叫,當使用者輸入2的時候,我們返回`sayHelllo`來讓使用呼叫,當使用者輸入2的時候,我們返回`sayGoodMornig`來讓使用呼叫:
|
||
```kotlin
|
||
fun selectGreet(number: Int): (String) -> String {
|
||
when (number) {
|
||
1 -> sayHi,
|
||
2 -> sayHello,
|
||
3 -> sayGoodMornig
|
||
}
|
||
}
|
||
```
|
||
可以看到`selectGreet`的回傳值是`(String) -> String`,接下來我們可以這樣用:
|
||
```kotlin
|
||
val greetFunc = selectGreet(2)
|
||
val greetString = greetFunc("John") // greetString會是"Hi John"
|
||
```
|
||
|
||
#### lambda也是closure
|
||
若是在函數裡面回傳一個lambda的時候,回傳的那個lambda在被呼叫的時候還是可以使用當初函數所在位置的變數,這便是closure。例如:
|
||
```kotlin
|
||
fun countGreet(): (String) -> String {
|
||
var count = 0
|
||
|
||
return { name ->
|
||
count = count + 1
|
||
"[$count] Hi $name"
|
||
}
|
||
}
|
||
```
|
||
當我們呼叫它的時候:
|
||
```kotlin
|
||
val greetFunc = countGreet()
|
||
val countString1 = greetFunc("John") // countString會等於"[1] Hi Jhon"
|
||
val countString2 = greetFunc("John") // countString會等於"[2] Hi Jhon"
|
||
val countString3 = greetFunc("John") // countString會等於"[3] Hi Jhon"
|
||
```
|
||
雖然`count`是`countGreet()`內的區域變數,但是`greetFunc()`還是能繼續取用它。
|
||
能夠接受函數(或是lambda)當參數或是返回函數的函數又叫做**高階函數**。
|
||
|
||
### 6. Nullability
|
||
Kotlin預設是型別都不可以是null。如果有一個型別是`String`的變數,把它設為null的話,compiler就會報錯。
|
||
```kotlin
|
||
var name = "John"
|
||
name = null <-- Error!
|
||
```
|
||
|
||
如果一定要設為null,那麼必須在宣告的時候,用`?`符號告訴compiler說這個變數必須是「可以null的」。
|
||
```kotlin
|
||
var name: String? = "John"
|
||
name = null <-- OK
|
||
```
|
||
|
||
`?`也可以用來判斷函數的回傳值,例如有一個函數它會回傳一個字串,或一個null:
|
||
```kotlin
|
||
fun getString(number: Int): String? {
|
||
if (number > 90) {
|
||
return "good"
|
||
} else {
|
||
return null
|
||
}
|
||
}
|
||
```
|
||
那我們在呼叫這個函數之後,可以方便的用`?`來串接下一個步驟:
|
||
```kotlin
|
||
val status = getString(50)?.capitialize()
|
||
```
|
||
上面例子是我們在得到"good"字串後,呼叫`String.capitialize()`來把字串的第一個字元變成大寫。`?`符號可以幫我們判斷`getString()`回傳的是不是null,如果不是,就接著呼叫`capitialize()`,如果是null,`capitialize()`就不會被呼叫,status將會是null。上面例子跟下面的程式是一樣的效果,但是明顯簡短的多:
|
||
```kotlin
|
||
val status = getString(50)
|
||
var statusCapital: String? = null
|
||
if (status) {
|
||
statusCapital = status.capitialize()
|
||
}
|
||
```
|
||
|
||
如果串接函數很多個的時候,更能看出效果:
|
||
```kotlin
|
||
val number = funcA()?.funcB()?.funcC()?.funcD()
|
||
```
|
||
|
||
#### `!!` operator
|
||
`!!`,[not-null assertion](https://kotlinlang.org/docs/reference/null-safety.html#the--operator) 用來讓compiler忽略null的檢查,例如:
|
||
```kotlin
|
||
var name: String? = null
|
||
name.capitialize() <-- 會報錯
|
||
name!!.capitialize() <-- 不會報錯,但是runtime會錯
|
||
```
|
||
|
||
#### `?:` Elvis operator
|
||
`?:` 就是「要是左邊為false就執行右邊」,`?:`可以很方便的用來設定變數的預設值,例如前面舉過的例子:
|
||
```kotlin
|
||
val number = funcA()?.funcB()?.funcC()?.funcD()
|
||
```
|
||
要是`funcA()`、`funcB()`、`funcC()`中任何一個的回傳是null,那麼number都會因為無法求值而被設為null,我們可以用`?:`來給它一個預設值:
|
||
```kotlin
|
||
val number = funcA()?.funcB()?.funcC()?.funcD() ?: "Default value"
|
||
```
|
||
|
||
#### 異常(Exception)
|
||
用`throw`來拋出一個異常,例如:
|
||
```kotlin
|
||
throw IllegalStateException("Oh! Oh!")
|
||
```
|
||
|
||
#### 自訂異常
|
||
可以用繼承來建立自己的異常:
|
||
```kotlin
|
||
class MyIllegalException(): IllegalStateException("I like new Exception")
|
||
```
|
||
|
||
#### 處理異常
|
||
用`try/catch`來處理異常:
|
||
```kotlin
|
||
var name: String? = null
|
||
|
||
name = somefunctionCall()
|
||
|
||
try: {
|
||
val newName = name.capitialize()
|
||
}
|
||
catch (e: Exception) {
|
||
println(e)
|
||
}
|
||
```
|
||
|
||
#### 先決條件
|
||
類似C++中的`assert()`,在符合判斷的條件下發出Exception。Kotlin內建5個先決條件函數:
|
||
|
||
| Funtion | Description |
|
||
| ------------------ | ---------------------------------------------------------------------------------------|
|
||
| `checkNotNull()` | `checkNotNull(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||
| `require()` | `require(condition, String)`,如果condition是`false`,就發出`IllegalStateException` |
|
||
| `requireNotNull()` | `requireNotNull(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||
| `error` | `error(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||
| `assert` | `assert(condition, String)`,如果condition是`false`,就發出`AssertError` |
|
||
|