Kotlin是一門務(wù)實、簡潔和安全的語言,專注于互操作性。
注:本文基于Kotlin 1.3編寫。
Hello world!
fun main() { // 1
println("Hello world!") // 2
}
1
支持定義 top-level 函數(shù),告別工具類。
fun關(guān)鍵字定義函數(shù),參數(shù)聲明格式是:name: Type。
main函數(shù)是程序執(zhí)行的主入口。
2
println是內(nèi)置top-level函數(shù),打印消息到標(biāo)準(zhǔn)輸出流并換行。
不需要;。
文檔注釋支持Markdown
/**
* 這是`文檔注釋`,它支持 **Markdown**。
*/
fun main() {
println("Hello world!")
}
變量
var定義可變變量,val定義只讀變量,初始化后不能再次被賦值。
fun main() {
var age: Int = 27
val name: String = "Belin Wu"
}
類型推導(dǎo)
可以不寫類型,編譯器會自動推導(dǎo)。
fun main() {
var age = 27 // age is Int
val name = "Belin Wu" // name is String
}
字符串模板
字符串里可以直接嵌套變量或表達(dá)式。
fun main() {
val name = "Kotlin"
println("The length of $name is ${name.length}") // The length of Kotlin is 6
}
原始字符串
用三引號"""定義的字符串里可以包含任意字符,不需要轉(zhuǎn)義。
fun main() {
val text = """
for (c in "foo")
print(c)
"""
print(text)
}
沒有new
直接調(diào)用構(gòu)造函數(shù)就可以創(chuàng)建實例。
fun main() {
val version = KotlinVersion(1, 1, 51)
}
屬性
不用定義setter和getter方法。
class User(var name: String)
fun main() {
val u = User("Belin")
u.name = "Belin Wu"
println("My name is ${u.name}")
}
定義對象
對象聲明將類的聲明和實例創(chuàng)建結(jié)合了起來,一步到位。Singleton同時也是一個單例。
object Singleton
fun main() {
println(Singleton) // Singleton@6e0be858
println(Singleton::class) // class Singleton
}
類型檢查與智能轉(zhuǎn)換
判斷對象是不是某個類型用is;判斷對象不是某個類型用!is
fun main() {
val obj: Any = "Kotlin"
println(obj is String) // true
println(obj !is String) // false
}
確定對象是期望的類型后就可以直接調(diào)用它的屬性或成員函數(shù),不需要強制類型轉(zhuǎn)換。
fun main() {
val obj: Any = "Kotlin"
if (obj is String) {
println(obj.length)
}
}
類型別名
為已有類型定義別名有縮短類型名稱、讓名字更符合使用場景、簡化范型或函數(shù)類型等好處。
typealias Age = Byte
typealias Hobby = Set<String>
typealias Predicate<T> = (T) -> Boolean
class Url {
inner class Builder
}
typealias UrlBuilder = Url.Builder
可空類型
Kotlin 類型分為:可空類型、不可空類型。null只允許將賦值給可空類型,否則會出現(xiàn)編譯錯誤。
fun main() {
val str: String? = null
val error: String = null // compile error
}
在類型的后面加上?就是該類型對應(yīng)的可空類型。
調(diào)用可空類型的屬性或成員函數(shù)有一種安全的操作符:?.,當(dāng)調(diào)用者是null時,調(diào)用結(jié)果也為null。當(dāng)在多個可空類型上做級聯(lián)調(diào)用時可以省去嵌套if判斷,代碼更加簡潔。
fun main() {
val str: String? = null
str?.length?.toString()?.length / / null
}
默認(rèn)參數(shù)值
有默認(rèn)值的函數(shù)可以減少重載、困惑。
fun joinToString(array: Array<String>, separator: String = ", "): String {
return array.joinToString(separator)
}
fun main() {
joinToString(args)
joinToString(args, " ")
}
數(shù)據(jù)類
當(dāng)使用data class定義數(shù)據(jù)類時,編譯器會自動生成toString(),equals(),hashCode(),copy()等成員函數(shù)的字節(jié)碼。
data class User(val name: String, var age: Int)
fun main() {
val user = User("Belin Wu", 27)
user.equals(user) // true
user.hashCode() // hash code
user.copy(age = 28) // copy the user to new user and modify the age property
println(user.toString()) // User(name=Belin Wu, age=27)
}
解構(gòu)聲明
將對象解構(gòu)可以一次性聲明并初始化多個變量。
data class User(var name: String, var age: Int = 1)
fun main() {
val u = User("Belin")
val (name, age) = u
print("name is $name, age is $age")
}
多返回值
使用解構(gòu)聲明可以實現(xiàn)返回多值的函數(shù)。
fun main() {
val (father, mother) = getParent()
println(father.name)
println(mother.name)
}
fun getParent(): Pair<Person, Person> {
return Pair(Person("Father"), Person("Mother"))
}
class Person(var name: String)
Pair<A, B>是一個內(nèi)置的數(shù)據(jù)類,它有component1和component2方法,Kotlin編譯器會按順序一一調(diào)用componentN方法并將結(jié)果分別賦值給father和mother變量。其中component1方法返回類聲明的第一個屬性,而component2方法返回第二個屬性,依此類推。
舉一反三,使用另一個內(nèi)置的數(shù)據(jù)類Triple<A, B, C>就可以實現(xiàn)三個返回值的函數(shù)。
要一定是數(shù)據(jù)類嗎?并不是,按照約定,在類中有定義N個componentN方法即可。
class MyPair<out A, out B>(val a: A, val b: B) {
operator fun component1() = a
operator fun component2() = b
}
不再需要中間變量,代碼更簡潔。
Delegation 機制
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main() {
val b = BaseImpl(10)
Derived(b).print()
}