Taiwan Kotlin User Group 的網站,在台灣推廣 Kotlin 程式語言,舉辦相關活動。如果對 Kotlin 有興趣,想要多瞭解一些,歡迎來我們的社群一起聚會!
下面列出一些常見的 Kotlin 慣用寫法
建立 DTO
(或稱 POJO,Plain Old Java Object)
data class Customer(val name: String, val email: String)
建立 Customer
類別
並包含下列函數:
var
會包含 setterequals()
hashCode()
toString()
copy()
component1()
、component2()
⋯⋯fun foo(a: Int = 0, b: String = "") { ... }
val positives = list.filter { x -> x > 0 }
更短的寫法
val positives = list.filter { it > 0 }
if ("john@example.com" in emailsList) { ... }
if ("jane@example.com" !in emailsList) { ... }
println("Name $name")
when (x) {
is Foo -> ...
is Bar -> ...
else -> ...
}
val list = listOf("a", "b", "c")
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
println(map["key"])
map["key"] = value
for ((k, v) in map) {
println("$k -> $v")
}
也可用來遍歷元素為 Pair
型態的 list
val list = listOf(
Pair("name", "Alice"),
Pair("age", 18)
)
for ((k, v) in list) {
println("$k -> $v")
}
k
和 v
都可以換成可讀性更高的名稱
像是 name
和 age
從 1 到 100
for (i in 1..100) { ... }
從 1 到 99,不包含 100
for (i in 1 until 100) { ... }
2 4 6 8 10
for (x in 2..10 step 2) { ... }
從 10 到 1
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }
val p: String by lazy {
// compute the string
}
可在原生型態上增添新函數
fun String.spaceToCamelCase() { ... }
"Convert this to camelcase".spaceToCamelCase()
建立單例(singleton)
object Resource {
val name = "Name"
}
abstract class MyAbstractClass {
abstract fun doSomething()
abstract fun sleep()
}
fun main() {
val myObject = object : MyAbstractClass() {
override fun doSomething() {
// ...
}
override fun sleep() { // ...
}
}
myObject.doSomething()
}
如果 files
不為 null
印出 files.size
println(files?.size)
如果 files
不為 null
印出 files.size
如果 files
為 null
印出 "empty"
println(files?.size ?: "empty")
null
執行特定行為如果 values["email"]
為 null
拋出例外 IllegalStateException("Email is missing!")
val email = values["email"]
?: throw IllegalStateException("Email is missing!")
emails
為 List<String>
如果集合為空,則取出預設物件(""
)
val mainEmail = emails.firstOrNull() ?: ""
null
時執行value?.let {
// 變數不為 null 時執行此段落
}
假設 value
型態是 Int?
mapped
轉換成 List<Int>
如果 value
是 null
把 mapped
設置為 listOf(0)
val mapped = value?.let { listOf(it) } ?: listOf(0)
fun transform(color: String): Int {
return when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else ->
throw IllegalArgumentException("Invalid color")
}
}
在 Kotlin try-catch
是表達式
回傳結果可以直接寫入變數
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
// Working with result
}
在 Kotlin if
是表達式
回傳結果可以直接寫入變數
fun foo(param: Int) {
val result = if (param == 1) {
"one"
} else if (param == 2) {
"two"
} else {
"three"
}
}
Unit
函數的生成器模式fill()
的回傳值是 Unit
(對等其他語言的回傳 void
)
下面建立大小為 size
全部值為 -1
的 IntArray
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
fun theAnswer() = 42
上面等同於
fun theAnswer(): Int {
return 42
}
單一表達式函數搭配上其他慣用寫法
可以寫出更簡潔的程式
例如搭配上 when
表達式
fun transform(color: String): Int = when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else ->
throw IllegalArgumentException("Invalid color")
}
利用 with()
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
val myTurtle = Turtle()
// 畫出大小 100 畫素的正方形
with(myTurtle) {
penDown()
for (i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
利用 apply()
val myRectangle = Rectangle().apply {
length = 4
breadth = 5
color = 0xFAFAFA
}
在處理沒有出現在建構子內的屬性時
非常方便的寫法
val stream = Files.newInputStream(
Paths.get("/some/file.txt")
)
stream.buffered().reader().use { reader ->
println(reader.readText())
}
假設 Gson
和 Gson.fromJson()
的宣告為
public final class Gson {
// ...
public <T> T fromJson(JsonElement json, Class<T> classOfT)
throws JsonSyntaxException {
// ...
使用時我們會需要 Class<T>
的資訊
利用 inline fun
和 reified
關鍵字
我們可以讓泛型函數內
取得泛型參數的類別資訊
inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T =
this.fromJson(json, T::class.java)
這邊 <T>
型態是 Any
可以放入任意類別
使用起來非常簡潔
Gson.fromJson<MyDataClass>(json)
null
的 Booleanval b: Boolean? = ...
if (b == true) {
...
} else {
// `b` 為 false 或 null
}
a = b.also { b = a }
利用 TODO()
函數
TODO()
執行時會拋出 NotImplementedError
中斷程式
TODO()
的回傳值是 Nothing
所以可以無視函數設定的回傳值
TODO()
內可以宣告理由
fun calcTaxes(): BigDecimal = TODO("等會計部門回需求")
IntelliJ IDEA 的 kotlin plugin 認得 TODO()
並會自動將內容放在 TODO 工具視窗內
想了解更多嗎?
可以看看 Kotlin 語法特色
或加入 kotlin.tips 的 Kotlin 讀書會 !