Taiwan Kotlin User Group 的網站,在台灣推廣 Kotlin 程式語言,舉辦相關活動。如果對 Kotlin 有興趣,想要多瞭解一些,歡迎來我們的社群一起聚會!
以下來分享一些我們認為 Kotlin 語法上值得關注的特色
用 data
宣告純資料物件(POJO,Plain Old Java Object)
看起來更加簡潔
data class Customer(
val name: String,
val email: String
)
比對 Java 寫法
public class Customer {
public String name;
public String email;
public Customer(String name, String email) {
this.name = name;
this.email = email;
}
public String name() {
return this.name;
}
public String email() {
return this.email;
}
// ...
}
用 val
宣告不可更改的值(value)
用 var
宣告可以更改的變數(variable)
讓意外更動常數的機會降低
val a = 1
var b = 2
b = 42
// 編譯錯誤 Val cannot be reassigned
a = 42
用 fun
關鍵字宣告函數
看起來更加簡潔
fun main() {
}
比對 Java 寫法
public static void main() {
}
類別宣告預設為 final
避免超長繼承鏈的出現
class Base(p: Int)
/*編譯錯誤
This type is final, so it cannot be inherited from
*/
class Derived(p: Int) : Base(p)
:
vs extends使用 :
宣告繼承
看起來更加簡潔
open class Base(p: Int)
class Derived(p: Int) : Base(p)
不用分號做結尾
看起來更簡潔
也避免常見的漏打分號錯誤
val a = 1
// IDE 提示 Redundant semicolon
val a = 1;
如果函數只有單行
可省略 {}
看起來更加簡潔
fun double(x: Int): Int = x * 2
/*
等同於
fun double(x: Int): Int {
return x * 2
}
*/
Kotlin 的 if
是表達式
可以直接用在變數賦值
val c = if (a > b) a else b
if
還可以直接放在函數回傳內
搭配上單行函數的寫法更加簡潔
fun bigger(a: Int, b: Int) = if (a > b) a else b
引入 when
表達式
比起 switch
更好看懂
並且避免常見的漏打 break;
錯誤
when (x) {
1 -> println("x == 1")
2 -> println("x == 2")
else -> {
println("x is neither 1 nor 2")
}
}
比對 Java 寫法
switch(x) {
case 1:
System.out.println("x == 1");
break;
case 2:
System.out.println("x == 2");
break;
default:
System.out.println("x is neither 1 nor 2");
}
when
和 if
一樣可以直接用在變數賦值
val state = when (x % 3) {
0 -> "is a multiple of 3"
1 -> "divided by 3 have remainder of 1"
2 -> "divided by 3 have remainder of 2"
else -> {
throw ArithmeticException("impossible!!")
}
}
也可以直接放在函數回傳內
fun getState(x: Int): String = when (x % 3) {
0 -> "is a multiple of 3"
1 -> "divided by 3 have remainder of 1"
2 -> "divided by 3 have remainder of 2"
else -> {
throw ArithmeticException("impossible!!")
}
}
用 object
關鍵字宣告單例物件
看起來更加簡潔
object ThisIsASingleton {
val name: String = "Taiwan Kotlin User Group"
}
比對 Java 寫法
public class ThisIsASingleton {
private static final ThisIsASingleton instance = new ThisIsASingleton();
private static final String name = "Taiwan Kotlin User Group";
private ThisIsASingleton(){}
public static ThisIsASingleton getInstance() {
return instance;
}
}
引入 ?.
和 ?:
讓程式可以寫得更簡潔
val b = a?.length ?: -1
// 等同 val b: Int = if (a != null) a.length else -1
Kotlin 可以在編譯時推理變數型態
讓程式不需宣告型態
寫法更加簡潔
val str = "hello"
// 等同 val str : String = "hello"
補充:
Java 在 JDK 10 以後
也支援 Type Inference
var str = "hello";
System.out.println(str); // hello
引入 typealias
關鍵字
讓程式語意更清晰
typealias CreditCardNumber = String
val aliceCardNumber: CreditCardNumber = "1234****"
可在呼叫函數時使用參數命名
讓程式的語意更清晰
並避免順序錯誤導致程式錯誤
fun reformat(
str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ',
) { /*...*/ }
reformat(
"String!",
normalizeCase = false,
upperCaseFirstLetter = false,
divideByCamelHumps = true,
wordSeparator = '_'
)
參數命名也讓我們可省略所有含預設值參數
只列出我們需要更動的參數
reformat("String!", upperCaseFirstLetter = false)
/*
等同
reformat(
"String!",
true,
false,
false,
' '
)
*/
編譯階段就避免 null
產生問題
減少 NullPointerException
出現
讓程式出錯的機會更少
var output: String
output = null // 無法通過編譯
val name: String? = null // 刻意宣告 name 可以為 null
println(name.length()) // 無法通過編譯
容易閱讀的 lambda 函數宣告法
讓程式邏輯易懂又好讀
val printInteger = fun Int.() { println(this) }
numbers.forEach { printInteger(it) }
比對 Java 寫法
import java.util.function.Consumer;
Consumer<Integer> printInteger = (n) -> { System.out.println(n); };
numbers.forEach( printInteger );
字串樣板讓程式在字串處理時更加易懂
且不容易出現空白錯誤
val bestLanguage = "Kotlin"
println("Taiwan $bestLanguage User Group")
比對 Java 寫法
String bestLanguage = "Kotlin";
System.out.println(
"Taiwan "
+ bestLanguage
+ " User Group"
);
除了函數可以多載
我們也可以用 operator
關鍵字對符號多載
讓我們的程式更好撰寫
data class Counter(val dayIndex: Int) {
operator fun plus(increment: Int): Counter {
return Counter(dayIndex + increment)
}
}
val counter = Counter(3)
println(counter + 4)
// Counter(dayIndex=7)
引入 infix
關鍵字
讓我們可以宣告更易懂的函數
infix fun Int.shouldEqualTo(actual: Int) {
assertEquals(this, actual)
}
add(2, 2) shouldEqualTo 4
// 等同 assertEquals(4, add(2, 2))
Kotlin 可以直接解構物件
讓程式邏輯更加簡潔
data class Customer(
val name: String,
val email: String
)
val (name, email) = customer
/*
等同
val name = customer.name
val email = customer.email
*/
也可以解構 Map
物件
val map = mapOf("Alice" to 21, "Bob" to 25)
for ((name, age) in map) {
println("$name is $age years old")
}
想了解更多 Kotlin 的語法特點嗎?
歡迎加入 kotlin.tips 的 Kotlin 讀書會 !
也可以參考 Kotlin 慣用寫法