從Java到Kotlin有多遠(yuǎn)廷臼?
相對于Java來說蝗柔,Kotlin真的是太簡潔了.
Kotlin新鮮的地方
1、去掉了分號(如無必要情龄,勿增實體)迄汛,看起來非常的neat
2、聽說再也不會空指針了(只要不用'V枋印鞍爱!')(下面會解釋)
3、所有一切皆為對象(好像JS)
Java與Kotlin的一些區(qū)別
類的聲明
上一篇文章专酗,我們看到了Kotlin聲明的一個類睹逃,是這樣的
class MainActivity : AppCompatActivity() {
...
}
這里我們到了繼承的方式使用冒號來表示,并且還可以在聲明中添加一個主構(gòu)造祷肯。另外權(quán)限修飾符也變成默認(rèn)了沉填,在Kotlin中默認(rèn)是public
而Java默認(rèn)是default(同包下可以訪問),下面就是Kotlin的修飾符代表的含義佑笋。
構(gòu)造:
//在 Kotlin 中的一個類可以有一個主構(gòu)造函數(shù)和一個或多個次構(gòu)造函數(shù)翼闹。主構(gòu)造函數(shù)是類頭的一部分:它跟在類名(和可選的類型參數(shù))后。沒有修飾可以省略
class Person constructor(firstName: String) {
}
//主構(gòu)造函數(shù)不能包含任何的代碼蒋纬。初始化的代碼可以放到以 init 關(guān)鍵字作為前綴的初始化塊(initializer blocks)中:
class Customer(name: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}
//類也可以聲明前綴有 constructor的次構(gòu)造函數(shù):
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
//如果類有一個主構(gòu)造函數(shù)猎荠,每個次構(gòu)造函數(shù)需要委托給主構(gòu)造函數(shù), 可以直接委托或者通過別的次構(gòu)造函數(shù)間接委托蜀备。委托到同一個類的另一個構(gòu)造函數(shù)用 this 關(guān)鍵字即可:
class Person(val name: String) {
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
基本類型
Java有byte, short, int, long, float, double, boolean, char八種基本類型关摇,對于Kotlin來說可以說沒有基本類型,因為所有的類型都是對象碾阁,可以說與一般的引用類型無異了拒垃。但Kotlin對與數(shù)字和字符來說,當(dāng)需要可空引用時瓷蛙,數(shù)字和字符會被裝箱悼瓮。裝箱操作不會保留同一性(不是同一個對象)。
fun main(args: Array<String>) {
val a: Int = 10000
println(a === a) // 輸出“true”
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA == anotherBoxedA)//輸出true
println(boxedA === anotherBoxedA)//輸出false
}
上述的例子==比較的是值艰猬,===比較的是對象地址横堡,與Java有些不太一樣。不過對于Int來說Kotin會內(nèi)置-128到127這些Int對象冠桃,這些范圍內(nèi)的裝箱還是同一個對象命贴,與Java是一樣的。對布爾值來說食听,封箱操作會保留同一性胸蛛,因為系統(tǒng)會內(nèi)置兩個Boolean對象。
另外Kotlin的數(shù)組使用的Array<T>來表示樱报,還有IntArray葬项,ByteArray等可以直接拿來用。
對于字符串來說還有這種操作迹蛤?
//原生字符串 使用三個引號(""")分界符括起來民珍,內(nèi)部沒有轉(zhuǎn)義并且
//可以包含換行和任何其他字符:
//你可以通過 trimMargin() 函數(shù)去除前導(dǎo)空格:
//默認(rèn) | 用作邊界前綴,但你可以選擇其他字符并作為參數(shù)傳入盗飒,比//如 trimMargin(">")嚷量。
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
變量與屬性
對于變量的定義,java是先聲明變量的類型逆趣,然后變量的名稱蝶溶,還可以有各種修飾符。而Kotlin只有兩種宣渗,val和var抖所。val用于聲明不變量(類似于java的final變量,只能賦值一次)落包,var聲明可變量可以多次賦值部蛇。變量類型甚至可以省略,自動判斷咐蝇。
//一次賦值(只讀)的局部變量
val a: Int = 1 // 立即賦值
val b = 2 // 自動推斷出 `Int` 類型
val c: Int // 如果沒有初始值類型不能省略
c = 3 // 明確賦值
//可變變量
var x = 5 // 自動推斷出 `Int` 類型
x += 1
聲明一個屬性的完整語法是
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
中括號包含的可以沒有涯鲁,會使用默認(rèn)的。如果不想讓外部賦值有序,則可以這樣抹腿。這樣外部只能拿到值但是不能改變值了。
var i: Int = 1
private set
函數(shù)
Java使用void或者返回類型來定義函數(shù)旭寿,Kotlin使用關(guān)鍵詞fun來定義警绩,而且可以用=來直接返回結(jié)果,甚至省略返回類型盅称。特別像JavaScript肩祥。
//帶返回參數(shù)類型
fun sum(a: Int, b: Int): Int {
return a + b
}
//或者不帶返回參數(shù)類型后室,自動推斷函數(shù)返回類型
fun sum(a: Int, b: Int) = a + b
//函數(shù)不返回值
fun printSum(a: Int, b: Int): Unit{
XXX
}
//或者省略Unit
fun printSum(a: Int, b: Int) {
XXX
}
Java中有靜態(tài)函數(shù),而Kotlin卻沒有混狠,不過Kotlin提供了類的擴(kuò)展函數(shù)岸霹,類似于Java的靜態(tài)函數(shù),不過這個擴(kuò)展函數(shù)也是通過這個類的對象調(diào)用的将饺。同理靜態(tài)變量也通過這種方法來擴(kuò)展贡避。
class Test {
}
fun Test.test() {
//擴(kuò)展函數(shù)
}
var i: Int = 1 //通過Test().i調(diào)用,所有對象的i值相同
流程控制
- if
Kotlin中if條件可以放到方法中外予弧,還可以寫成表達(dá)式刮吧,如果代碼簡單還可以省略大括號
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
// 作為表達(dá)式
val max = if (a > b) a else b
- when
類似于Java的switch語句,一個例子概括
when (x) {
0, 1 -> print("x == 0 or x == 1")
2 -> print("x==2")
else -> print("otherwise")
}
- 循環(huán)
Kotlin在循環(huán)中經(jīng)常使用到關(guān)鍵詞in
//一行代碼省略大括號
for (item in collection) print(item)
//代碼塊
for (item: Int in ints) {
// ……
}
//索引遍歷
for (i in array.indices) {
print(array[i])
}
非空判斷
在Kotlin中當(dāng)某個變量的值可以為 null 的時候掖蛤,必須在聲明處的類型后添加 ? 來標(biāo)識該引用可為空杀捻。如果如果標(biāo)識了程序就會返回null,不會執(zhí)行空后的語句坠七。
如果不標(biāo)識那么就編譯不過水醋,當(dāng)然也可以使用!!來放過這個可能的null,這樣就會拋出一個空指針了彪置。
a?.length()//如果a為null拄踪,就不會執(zhí)行l(wèi)ength()了
a!!.length()//可能會拋出空指針
位運(yùn)算
位運(yùn)算的效率毋庸置疑,但是開發(fā)中卻很少人用拳魁,要想程序運(yùn)行的快惶桐,善用位運(yùn)算還是很重要的,成為高級開發(fā)工程師必不可缺的一步潘懊。
這是完整的位運(yùn)算列表(只用于 Int 和 Long):
? shl(bits) – 有符號左移 (Java 的 <<)
? shr(bits) – 有符號右移 (Java 的 >>)
? ushr(bits) – 無符號右移 (Java 的 >>>)
? and(bits) – 位與
? or(bits) – 位或
? xor(bits) – 位異或
? inv() – 位非
其他一些關(guān)鍵字
- range
Kotlin提供了很實用區(qū)間工具姚糊,滿足我們對數(shù)字區(qū)間條件的各種判斷。
for (i in 1..4) print(i) // 輸出“1234”
for (i in 4..1) print(i) // 什么都不輸出(默認(rèn)正序)
for (i in 4 downTo 1) print(i) // 輸出“4321”
for (i in 1..4 step 2) print(i) // 輸出“13” 可以+2跳
for (i in 4 downTo 1 step 2) print(i) // 輸出“42”
for (i in 1 until 10) { // i in [1, 10) 排除了 10(區(qū)間邊界)
println(i)
}
- ${}
在字符串中把表達(dá)式放到大括號中就可以替換字符串中了授舟,讓字符串更加靈活救恨。 - companion
伴生對象,只能通過類名作為限定符來調(diào)用释树,很像Java的靜態(tài)方法肠槽,在運(yùn)行時他們?nèi)匀皇钦鎸崒ο蟮膶嵗蓡T,而且奢啥,例如還可以實現(xiàn)接口:
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
- 數(shù)據(jù)類:data關(guān)鍵字標(biāo)記秸仙,data class XX
- 跳轉(zhuǎn)標(biāo)簽
Java可以在循環(huán)分支前寫 XXX:來標(biāo)記這個循環(huán),而Kotlin使用@符號來標(biāo)記桩盲。例如:
loop@ for (i in 1..100) {
for (j in 1..100) {
if (……) break@loop
}
}
Kotlin的一些默認(rèn)規(guī)范
命名來說寂纪,與Java的命名規(guī)范是一樣的。Kotlin語言有自己的很多習(xí)慣用法,可以讓代碼變得很短捞蛋,可讀性很強(qiáng)孝冒。善用Kotlin提供的一些好用的特性。
然后還有就是冒號和空格之類的注意一下拟杉,最好和官方推薦的一致迈倍。
另外,對于Kotlin來說捣域,函數(shù)可以獲取值,所以我們也可以通過函數(shù)來取值宴合。但是底層算法優(yōu)先使用的屬性而不是函數(shù)焕梅,因此我們還是盡量使用屬性來滿足自己的需求。
還需要多用才能熟練
官方文檔是大家入門的最好的資料卦洽,而且還有中文版https://www.kotlincn.net/docs/reference/