Kotlin簡(jiǎn)介
Kotlin來(lái)源于一個(gè)島嶼的名字,全稱(chēng)是Kotlin Island,是英語(yǔ)【科特林島】之意酥郭,這個(gè)小島位于俄羅斯的圣彼得堡附近。之所以要命名為Kotlin愿吹,是因?yàn)镵otlin的主要開(kāi)發(fā)工作就是由位于圣彼得堡分公司團(tuán)隊(duì)完成的不从。Kotlin是由JetBrains公司開(kāi)發(fā)與設(shè)計(jì)的。
早在2011年犁跪,JetBrains就公布了Kotlin的第一個(gè)版本椿息,并在2012年將其開(kāi)源歹袁。
2016年,Kotlin發(fā)布了1.0的正式版本寝优,并在自家IDE開(kāi)發(fā)工具中加入了對(duì)Kotlin的支持条舔。
2017年,Google宣布Kotlin正式成為Android一級(jí)開(kāi)發(fā)語(yǔ)言乏矾,Android Studio也加入了對(duì)Kotlin的支持孟抗。
兩年之后,Google又在2019年的I/O大會(huì)上宣布钻心,Kotlin已經(jīng)成為Android的第一開(kāi)發(fā)語(yǔ)言凄硼。
在開(kāi)發(fā)Kotlin之前,JetBrains團(tuán)隊(duì)一直使用Java來(lái)創(chuàng)建他們的IDE以及使用Java進(jìn)行業(yè)務(wù)邏輯開(kāi)發(fā)捷沸。之所以開(kāi)發(fā)Kotlin摊沉,是因?yàn)镴etBrains 的工程師們?cè)谑褂肑ava開(kāi)發(fā)應(yīng)用程序的過(guò)程中,發(fā)現(xiàn)了大量的問(wèn)題亿胸。為了提升開(kāi)發(fā)效率以及解決使用Java開(kāi)發(fā)帶來(lái)的問(wèn)題坯钦,在借鑒了其他語(yǔ)言后,他們決定開(kāi)發(fā)一款致力于解決Java問(wèn)題的編程語(yǔ)言Kotlin侈玄。JetBrains深知開(kāi)發(fā)者的需求和痛處婉刀,在孜孜不倦地為開(kāi)發(fā)者提供最實(shí)用、最高效的IDE的同時(shí)序仙,也為開(kāi)發(fā)者提供全新的編程語(yǔ)言以解決目前的技術(shù)問(wèn)題突颊。
或許你會(huì)產(chǎn)生一些疑惑:Android操作系統(tǒng)明明是由Google開(kāi)發(fā)的,為什么JetBrains作為一個(gè)第三方公司潘悼,卻能夠自己設(shè)計(jì)出一門(mén)編程語(yǔ)言來(lái)開(kāi)發(fā)Android應(yīng)用程序呢律秃?
先大概熟悉一下Java語(yǔ)言的運(yùn)行機(jī)制。編程語(yǔ)言大致可以分為兩類(lèi):編譯型語(yǔ)言和解釋型語(yǔ)言治唤。編譯型語(yǔ)言的特點(diǎn)是編譯器會(huì)將我們編寫(xiě)的源代碼一次性地編譯成計(jì)算機(jī)可識(shí)別的二進(jìn)制文件棒动,然后計(jì)算機(jī)直接執(zhí)行,像C和C++都屬于編譯型語(yǔ)言宾添。
解釋型語(yǔ)言則完全不一樣船惨,它有一個(gè)解釋器,在程序運(yùn)行時(shí)缕陕,解釋器會(huì)一行行地讀取我們編寫(xiě)的源代碼粱锐,然后實(shí)時(shí)地將這些源代碼解釋成計(jì)算機(jī)可識(shí)別的二進(jìn)制數(shù)據(jù)后再執(zhí)行,因此解釋型語(yǔ)言通常效率會(huì)差一些扛邑,像Python和JavaScript都屬于解釋型語(yǔ)言怜浅。
那Java是屬于編譯型語(yǔ)言還是解釋型語(yǔ)言呢?
雖然Java代碼確實(shí)是要先編譯再運(yùn)行的蔬崩,但是Java代碼編譯之后生成的并不是計(jì)算機(jī)可識(shí)別的二進(jìn)制文件恶座,而是一種特殊的class文件搀暑,這種class文件只有Java虛擬機(jī)才能識(shí)別,而這個(gè)Java虛擬機(jī)擔(dān)當(dāng)?shù)钠鋵?shí)就是解釋器的角色奥裸,它會(huì)在程序運(yùn)行時(shí)將編譯后的class文件解釋成計(jì)算機(jī)可識(shí)別的二進(jìn)制數(shù)據(jù)
后再執(zhí)行险掀,因此,準(zhǔn)確來(lái)講湾宙,Java屬于解釋型語(yǔ)言樟氢。了解了Java語(yǔ)言的運(yùn)行機(jī)制之后,可以看出侠鳄,其實(shí)Java虛擬機(jī)并不直接和你編寫(xiě)的Java代碼打交道埠啃,而是和編譯之后生成的class文件打交道。那么如果開(kāi)發(fā)了一門(mén)新的編程語(yǔ)言伟恶,然后自己做了個(gè)編譯器碴开,讓它將這門(mén)新語(yǔ)言的代碼編譯成同樣規(guī)格的
class文件,Java虛擬機(jī)能不能識(shí)別呢博秫?沒(méi)錯(cuò)潦牛,這其實(shí)就是Kotlin的工作原理了。Java虛擬機(jī)不關(guān)心class文件是從Java編譯來(lái)的挡育,還是從Kotlin編譯來(lái)的巴碗,只要是符合規(guī)格的class文件,它都能識(shí)別即寒。也正是這個(gè)原因橡淆,JetBrains才能以一個(gè)第三方公司的身份設(shè)計(jì)出一門(mén)用來(lái)開(kāi)發(fā)Android應(yīng)用程序的編程語(yǔ)言。
下面數(shù)據(jù)是來(lái)對(duì)比kotlin和C++在不同的長(zhǎng)度運(yùn)算過(guò)程的耗時(shí)情況:
算式 | kotlin耗時(shí) | C++耗時(shí) |
---|---|---|
2組 【9個(gè)9】相乘 | 6ms | 1ms |
10組【9個(gè)9】相乘 | 17ms | 10ms |
100組 【9個(gè)9】相乘 | 288ms | 25ms |
1000組【9個(gè)9】相乘 | 95171ms | 237ms |
在此應(yīng)用場(chǎng)景下母赵,C++算法明顯優(yōu)于Kotlin逸爵,效率提升明顯。因?yàn)镃++是編譯型的凹嘲,直接將源碼編譯成機(jī)器代碼师倔,可以直接運(yùn)行;而Kotlin是解釋型周蹭,源碼被編譯成二進(jìn)制字節(jié)碼趋艘,但不是機(jī)器可以識(shí)別的語(yǔ)言,由虛擬機(jī)解釋才能執(zhí)行谷醉,效率會(huì)慢一些。
Kotlin的優(yōu)勢(shì)
Kotlin的語(yǔ)法簡(jiǎn)潔冈闭,同樣的功能俱尼,Kotlin開(kāi)發(fā)的代碼量可能會(huì)比Java少50%,可能更多萎攒。
Kotlin增加了很多高級(jí)語(yǔ)言的很特性遇八,大大的提高了開(kāi)發(fā)效率矛绘。
Kotlin和Java100%兼容,Kotlin可直接調(diào)用Java編寫(xiě)的代碼刃永,也可以無(wú)縫使用Java第三方的開(kāi)源庫(kù)货矮,使得Kotlin在加入新特性的同時(shí),繼承了Java的全部財(cái)富斯够。
Kotlin基礎(chǔ)語(yǔ)法
變量
val(value):不可變變量囚玫,它的值在初始化以后就無(wú)法再次修改,相當(dāng)于java中final變量
var(variable):可變變量读规,對(duì)應(yīng)java中的普通變量
基礎(chǔ)類(lèi)型
Type | Bit width | 備注 |
---|---|---|
Double | 64 | Kotlin沒(méi)有double |
Float | 32 | Kotlin沒(méi)有float |
Long | 64 | Kotlin沒(méi)有l(wèi)ong |
Int | 32 | kotlin沒(méi)有int/Integer |
Short | 16 | kotlin沒(méi)有short |
Char | 16 | Kotlin沒(méi)有char |
Byte | 8 | Kotlin沒(méi)有byte |
Boolean | 8 | Kotlin沒(méi)有boolean |
基礎(chǔ)類(lèi)型抓督,包含我們常見(jiàn)的數(shù)字類(lèi)型,布爾類(lèi)型束亏,字符類(lèi)型铃在,及這些類(lèi)型組成的數(shù)組,這些常遇到的概念碍遍,統(tǒng)一歸納為基礎(chǔ)類(lèi)型
從上圖也可以看出定铜,在Kotlin語(yǔ)言體系中,是沒(méi)有原始類(lèi)型這個(gè)概念的怕敬,這就意味著揣炕,在Kotlin中,一切都是對(duì)象赖捌。
對(duì)比后祝沸,從某種程度上講,Java的類(lèi)型系統(tǒng)并不是完全面向?qū)ο蟮脑奖樱驗(yàn)樗嬖谠碱?lèi)型罩锐,而原始類(lèi)型并不屬于對(duì)象,而Kotlin則不一樣卤唉,它從語(yǔ)言設(shè)計(jì)的層面就規(guī)避了這個(gè)問(wèn)題涩惑,類(lèi)型系統(tǒng)是完全面向?qū)ο蟮摹?/p>
空安全
Kotlin強(qiáng)制要求開(kāi)發(fā)者在定義變量的時(shí)候,就指定這個(gè)變量是否可能為null桑驱,對(duì)于可能為null的變量竭恬,我們需要在聲明的時(shí)候,在變量類(lèi)型后面加一個(gè)問(wèn)號(hào)“?”
val i: Double = null // 編譯器報(bào)錯(cuò)
val j: Double? = null // 編譯通過(guò)
數(shù)字類(lèi)型
val i = 1
val l = 1234567L
val d = 13.14
val f = 13.14F
val hex = 0xAF
val b = 0b01010101
整數(shù)默認(rèn)會(huì)被推導(dǎo)為“Int”類(lèi)型熬的;
Long 類(lèi)型痊硕,我們則需要使用“L”后綴;小
數(shù)默認(rèn)會(huì)被推導(dǎo)為“Double”押框,我們不需要使用“D”后綴岔绸;
Float 類(lèi)型,我們需要使用“F”后綴;
使用“0x”盒揉,來(lái)代表十六進(jìn)制字面量晋被;
使用“0b”,來(lái)代表二進(jìn)制字面量刚盈。
對(duì)于數(shù)字類(lèi)型的轉(zhuǎn)換羡洛,Kotlin與Java的轉(zhuǎn)換行為是不一樣的,Java可以隱式轉(zhuǎn)換數(shù)字類(lèi)型藕漱,而Kotlin更推崇顯示轉(zhuǎn)換欲侮,在一些嚴(yán)謹(jǐn)?shù)倪壿嬇袛嘀校龅揭恍┻吔鐥l件問(wèn)題谴分,隱式轉(zhuǎn)換會(huì)因存在精度問(wèn)題而導(dǎo)致的一些Bug不容易被排除出來(lái)锈麸。而在Kotlin中,提供了toLong()牺蹄,toByte()忘伞、toShort()、toInt()沙兰、toLong()氓奈、toFloat()、toDouble()鼎天、toChar()等舀奶,使得代碼可讀性更強(qiáng),也易維護(hù)斋射。
布爾類(lèi)型
兩種值育勺,true和false,布爾類(lèi)型是支持一些邏輯操作的罗岖,如下:
“&”代表“與運(yùn)算”涧至;
“|”代表“或運(yùn)算”;
“!”代表“非運(yùn)算”桑包;
“&&”和“||”分別代表它們對(duì)應(yīng)的“短路邏輯運(yùn)算”
val i = 1
val j = 2
val k = 3
val isTrue: Boolean = i < j && j < k
字符:Char
Char用于代表單個(gè)字符南蓬,‘A’、’B’哑了、’C’赘方、寫(xiě)法和Java類(lèi)似
字符串:String
val s = "Hello Kotlin!"
寫(xiě)法和Java類(lèi)似,但是Kotlin提供了非常簡(jiǎn)潔的字符串模板:
val name = "Kotlin"
print("Hello $name!")
/* ↑
直接在字符串中訪(fǎng)問(wèn)變量
*/
// 輸出結(jié)果:
Hello Kotlin!
當(dāng)然弱左,在Java中也能實(shí)現(xiàn)窄陡,但需要使用“+”進(jìn)行拼接,在字符串格式相對(duì)復(fù)雜的情況下啊拆火,代碼就會(huì)顯得很臃腫跳夭。
如果需要在字符串中引用更加復(fù)雜的變量鳖悠,則需要使用花括號(hào)括起來(lái):
val array = arrayOf("Java", "Kotlin")
print("Hello ${array.get(1)}!")
/* ↑
復(fù)雜的變量,使用${}
*/
// 輸出結(jié)果:
Hello Kotlin!
此外优妙,Kotlin還新增了原始字符串,是用三個(gè)引號(hào)來(lái)表示憎账,可用來(lái)存放復(fù)雜發(fā)多行文本套硼,打印格式和定義格式保持同步:
val s = """
原始字符串
所見(jiàn)即所得。 """
println(s)
數(shù)組
在Kotlin中胞皱,一般會(huì)使用arrayOf()來(lái)創(chuàng)建數(shù)組邪意,括號(hào)當(dāng)中可以用于傳遞數(shù)組元素進(jìn)行初始化,同時(shí)反砌,Kotlin編譯器也會(huì)根據(jù)傳入的參數(shù)進(jìn)行類(lèi)型推導(dǎo):
val arrayInt = arrayOf(1, 2, 3)
val arrayString = arrayOf("apple", "pear")
如上雾鬼,arrayInt的類(lèi)型會(huì)被推導(dǎo)為整形數(shù)組,arrayString會(huì)被推導(dǎo)為字符串?dāng)?shù)組宴树。
獲取數(shù)組長(zhǎng)度方式和一些操作和集合類(lèi)似:
val array = arrayOf("apple", "pear")
println("Size is ${array.size}")
println("First element is ${array[0]}")
// 輸出結(jié)果:
Size is 2
First element is apple
函數(shù)聲明
在Kotlin中策菜,函數(shù)的聲明和Java不太一樣:
/*
關(guān)鍵字 函數(shù)名 參數(shù)類(lèi)型 返回值類(lèi)型
↓ ↓ ↓ ↓ */
fun helloFunction(name: String): String {
return "Hello $name !"
}
/* ↑
花括號(hào)內(nèi)為:函數(shù)體
*/
1)使用了fun關(guān)鍵字來(lái)定義函數(shù)
2)函數(shù)名稱(chēng),駝峰命名規(guī)則
3)是以 (name: String) 這樣的形式傳遞的酒贬,這代表了參數(shù)類(lèi)型為 String 類(lèi)型
4)返回值類(lèi)型又憨,跟在參數(shù)后面
5)函數(shù)體(業(yè)務(wù)邏輯)
如果函數(shù)體只有一行代碼,這種情況下锭吨,其實(shí)可以省略函數(shù)體的花括號(hào)蠢莺,直接使用“=”來(lái)連接,將其變成一種類(lèi)似變量賦值函數(shù)的形式:
fun helloFunction(name: String): String = "Hello $name !"
這種寫(xiě)法零如,稱(chēng)之為 單一表達(dá)式函數(shù)躏将,其中“retuen”是需要去掉的
繼續(xù)簡(jiǎn)化,由于Kotlin是支持類(lèi)型推導(dǎo)的考蕾,返回值的類(lèi)型可省略:
fun helloFunction(name: String) = "Hello $name !"
代碼極其簡(jiǎn)潔祸憋,Kotlin的優(yōu)勢(shì)不僅僅體現(xiàn)在函數(shù)聲明上,在函數(shù)調(diào)用的地方辕翰,它也有很多獨(dú)到之處夺衍。
函數(shù)調(diào)用
代碼風(fēng)格基本和Java一致
helloFunction("Kotlin")
但Kotlin提供了一些新的特性,命名參數(shù)喜命」瞪常可以理解為:就是它允許我們?cè)谡{(diào)用函數(shù)的時(shí)候傳入“形參的名字”
helloFunction(name = "Kotlin")
fun createUser(
name: String,
age: Int,
gender: Int,
friendCount: Int,
feedCount: Int,
likeCount: Long,
commentCount: Int
) {
//..
}
// Java調(diào)用方式:
createUser("Tom", 30, 1, 78, 2093, 10937, 3285)
// Kotlin調(diào)用方式:
createUser(
name = "Tom",
age = 30,
gender = 1,
friendCount = 78,
feedCount = 2093,
likeCount = 10937,
commentCount = 3285
)
可以看到,把函數(shù)的形參加了進(jìn)來(lái)壁榕,形參和實(shí)參通過(guò)“=”連接矛紫,建立了兩者的對(duì)應(yīng)關(guān)系,其實(shí)這樣代碼的可讀性會(huì)更強(qiáng)牌里。
此外颊咬,Kotlin還支持參數(shù)默認(rèn)值:
fun createUser(
name: String,
age: Int,
gender: Int = 1,
friendCount: Int = 0,
feedCount: Int = 0,
likeCount: Long = 0L,
commentCount: Int = 0
) {
//..
}
createUser(
name = "Tom",
age = 30,
commentCount = 3285
)
以上方法調(diào)用時(shí)只傳了三個(gè)參數(shù)务甥,剩余的參數(shù)沒(méi)有傳,但是Kotlin編譯器會(huì)自動(dòng)幫忙填充默認(rèn)值
但在Java中喳篇,需要定義三個(gè)參數(shù)的重載方法敞临,才能實(shí)現(xiàn)。其實(shí)麸澜,在一些場(chǎng)景下還是提高了開(kāi)發(fā)效率的挺尿。
流程控制
在Kotlin中,流程控制主要有if炊邦,when编矾,for,white馁害,這些語(yǔ)句可以控制代碼的執(zhí)行流程窄俏,具體如下:
if
if 語(yǔ)句,在程序中主要用于邏輯判斷碘菜,和Java基本一致凹蜈,此外,還可以作為表達(dá)式來(lái)使用:
val i = 1
val message = if (i > 0) "Big" else "Small"
print(message)
//輸出結(jié)果:
Big
另外忍啸,在Kotlin中明確規(guī)定了類(lèi)型分為可空類(lèi)型和不可空類(lèi)型踪区,會(huì)遇到一些可空的變量,判斷是否為空:
fun getLength(text: String?): Int {
return if (text != null) text.length else 0
}
類(lèi)似這種邏輯判斷出現(xiàn)的很頻繁吊骤,為此缎岗,Kotlin提供了一種簡(jiǎn)寫(xiě),稱(chēng)之為Elvis表達(dá)式
fun getLength(text: String?): Int {
return text?.length ?: 0
}
when
when 語(yǔ)句白粉,在程序當(dāng)中也是主要用于邏輯判斷的传泊,當(dāng)代碼邏輯只有兩個(gè)分支的時(shí)候,一般用if/else鸭巴,而大于兩個(gè)邏輯分支的時(shí)候眷细,一般使用when:
val i: Int = 1
when(i) {
1 -> print("一")
2 -> print("二")
else -> print("i 不是一也不是二")
}
// 輸出結(jié)果:
一
when語(yǔ)句和Java中的switch case語(yǔ)句很像,不過(guò)Kotlin的when更加強(qiáng)大鹃祖,同時(shí)可以作為表達(dá)式溪椎,為變量賦值:
val i: Int = 1
val message = when(i) {
1 -> "一"
2 -> "二"
else -> "i 不是一也不是二" // 如果去掉這行,會(huì)報(bào)錯(cuò)
}
print(message)
循環(huán)遍歷 while恬口,for
while語(yǔ)法和Java類(lèi)似校读,不做過(guò)多講解
Kotlin在for循環(huán)做了大幅度調(diào)修改,Java中最常用的for-i循環(huán)在kotlin中直接被舍棄了祖能,而Java中另外一種for-each循環(huán)則被Kotlin進(jìn)行了加強(qiáng)歉秫,變成了for-in循環(huán)。
val array = arrayOf(1, 2, 3)
for (i in array) {
println(i)
}
此外养铸,Kotlin還支持迭代一個(gè)區(qū)間雁芙。
在Kotlin中用關(guān)鍵字 .. 來(lái)創(chuàng)建一個(gè)兩端閉區(qū)間轧膘,兩邊指定區(qū)間的左右端點(diǎn):
val range = 0..10 // 代表 [0, 10]
可通過(guò)for-in來(lái)遍歷這個(gè)區(qū)間:
for (i in range){
printIn(i)
}
在很多時(shí)候,需要?jiǎng)?chuàng)建單閉區(qū)間兔甘,可通過(guò)until關(guān)鍵字來(lái)創(chuàng)建一個(gè)左閉右開(kāi)的區(qū)間:
val range = 0 until 10 // 代表 [0, 10)
默認(rèn)情況下谎碍,for-in循環(huán)每次執(zhí)行循環(huán)時(shí)會(huì)在區(qū)間范圍內(nèi)遞增1,即i++的效果洞焙,如果想跳過(guò)某一些元素椿浓,可以使用step關(guān)鍵字:
for(i in range step 2){
printIn(i)
}
// 打印:0 2 4 6 8
相當(dāng)于在遍歷range區(qū)間時(shí)闽晦,每次遞增2,即可i=i+2的效果提岔。
不管是..仙蛉,還是until關(guān)鍵字都要求區(qū)間的左端小于等于區(qū)間的右端,即這兩個(gè)關(guān)鍵字創(chuàng)建的都是一個(gè)升序區(qū)間碱蒙,如果想創(chuàng)建一個(gè)降序區(qū)間荠瘪,可使用downTo關(guān)鍵字:
for (i in 6 downTo 0 step 2) {
println(i)
}
// 輸出結(jié)果:
6 4 2 0
類(lèi)與對(duì)象
在Kotlin中也是使用class關(guān)鍵字來(lái)聲明一個(gè)類(lèi)的,這一點(diǎn)和Java是保持一致的赛惩。
class Person{
var name = “”
var age = 0
fun eat(){
printIn(name + “is eating. He is ”+age +” years old.”)
}
}
對(duì)這個(gè)類(lèi)進(jìn)行實(shí)例化:
val p = Person()
Kotlin實(shí)例化一個(gè)類(lèi)的方式和Java基本類(lèi)似哀墓,只是去掉了new關(guān)鍵字。
繼承
我們先定義一個(gè)Student類(lèi):
class Student{
var sno =””
var grade = 0
}
怎么讓Student繼承Person呢喷兼?
在Kotlin中任何一個(gè)非抽象類(lèi)默認(rèn)是不可以被繼承的篮绰。相當(dāng)于Java中給類(lèi)聲明了final。之所以這么設(shè)計(jì)季惯,其實(shí)和val關(guān)鍵字的原因是差不多的吠各,類(lèi)和變量一樣,最好是不可變的勉抓。
如果需要被繼承贾漏,在Person類(lèi)前面加上open關(guān)鍵字即可:
open class Person{
}
加上open關(guān)鍵字之后,就是在主動(dòng)告知Kotlin編譯器藕筋,Person這個(gè)類(lèi)時(shí)專(zhuān)門(mén)為繼承而設(shè)計(jì)的纵散,它就會(huì)被允許繼承。
在Java中繼承的關(guān)鍵字是extends隐圾,而在Kotlin中變成了一個(gè)冒號(hào):
class Student : Person(){
var sno = “”
var grade = 0
}
接口
一般會(huì)在接口中定義一系列的抽象行為伍掀,然后由具體的類(lèi)去實(shí)現(xiàn)。
Java中實(shí)現(xiàn)接口使用的是關(guān)鍵字implements暇藏,而Kotlin中統(tǒng)一使用冒號(hào)硕盹,中間用逗號(hào)進(jìn)行分隔。
class Student(name:String,age int):Person(name,age),Study{
override fun doHomework(){
}
}
修飾符
Kotlin中也有四種叨咖,public瘩例,private啊胶,protected 和internal
區(qū)別在于:在Java中默認(rèn)的是default,而Kotlin中public是默認(rèn)修飾符垛贤。
權(quán)限跟Java稍微有出入:
protected: Java中表示對(duì)當(dāng)前類(lèi)焰坪,子類(lèi)和同一個(gè)包路徑下的類(lèi)可見(jiàn)。在Kotlin表示只對(duì)當(dāng)前類(lèi)和子類(lèi)可見(jiàn)聘惦。
internal:只對(duì)同一個(gè)模塊的類(lèi)可見(jiàn)某饰,。如:開(kāi)發(fā)了一個(gè)模塊給別人使用善绎,但一些函數(shù)只允許在模塊內(nèi)部調(diào)用黔漂,不想暴露在外部,可以用internal來(lái)聲明禀酱。
修飾 | Java | Kotlin |
---|---|---|
public | 所有類(lèi)可見(jiàn) | 所有類(lèi)可見(jiàn)(默認(rèn)) |
private | 當(dāng)前類(lèi)可見(jiàn) | 當(dāng)前類(lèi)可見(jiàn) |
protected | 當(dāng)前類(lèi)炬守,子類(lèi)和同一個(gè)包路徑下的類(lèi)可見(jiàn) | 只對(duì)當(dāng)前類(lèi)和子類(lèi)可見(jiàn) |
default | 同一個(gè)包路徑下面的類(lèi)可見(jiàn)(默認(rèn)) | 無(wú)) |
internal | 無(wú) | 同一個(gè)模塊中的類(lèi)可見(jiàn) |
數(shù)據(jù)類(lèi)和單列類(lèi)
數(shù)據(jù)類(lèi)通常需要重寫(xiě)equals(),hashCode().toStirng()這幾個(gè)方法,其中equals()用于判斷兩個(gè)數(shù)據(jù)類(lèi)是否相等剂跟,這些方法會(huì)讓代碼顯得比較臃腫减途,有些時(shí)候卻又不得不寫(xiě)。但在Kotlin中曹洽,這種情況就變得極其簡(jiǎn)單鳍置,可通過(guò)data關(guān)鍵字來(lái)聲明
data class CellPhone(val brand:String,val price:Double)
當(dāng)在一個(gè)類(lèi)的前面聲明了data關(guān)鍵字時(shí),就表明它是一個(gè)數(shù)據(jù)類(lèi)送淆,Kotlin會(huì)根據(jù)主構(gòu)造函數(shù)中的參數(shù)自動(dòng)生成equals()税产,hashCode(),toString()等固定方法偷崩,一定程度上減少了工作量砖第。
最后再講一個(gè)Kotlin中的單例類(lèi)
在java中寫(xiě)單例的常規(guī)寫(xiě)法,首先為了進(jìn)制外部創(chuàng)建Singleton的實(shí)例环凿,需要用private關(guān)鍵字將Singleton的構(gòu)造函數(shù)私有化梧兼,然后給外部提供一個(gè)getInstance()靜態(tài)方法用于獲取Singleton的實(shí)例。在getInstance()方法中判斷當(dāng)前緩存的Singleton實(shí)例為null智听,就創(chuàng)建一個(gè)新的實(shí)例羽杰,否則直接返回緩存的實(shí)例。
然而到推,在Kotlin中考赛,會(huì)將一些固定的,重復(fù)的邏輯實(shí)現(xiàn)了隱藏莉测,只暴露一個(gè)最簡(jiǎn)單的用法颜骤。在Kotlin中創(chuàng)建單例,只需要將class關(guān)鍵字改為object關(guān)鍵字即可捣卤。Kotlin會(huì)自動(dòng)一個(gè)Singleton實(shí)例忍抽,且會(huì)保證全局只會(huì)存在一個(gè)Singleton實(shí)例八孝。
小結(jié)
Kotlin 和 Java 的語(yǔ)法很像,但在一些細(xì)節(jié)之處鸠项,Kotlin 總會(huì)有一些新的東西干跛。熟悉完基礎(chǔ)語(yǔ)法之后,我們可以來(lái)看看 Kotlin 在這方面都做了以下改進(jìn):
支持類(lèi)型推導(dǎo)祟绊;
代碼末尾不需要分號(hào)楼入;
字符串模板;
原始字符串牧抽,支持復(fù)雜文本格式嘉熊;
單一表達(dá)式函數(shù),簡(jiǎn)潔且符合直覺(jué)扬舒;
函數(shù)參數(shù)支持默認(rèn)值阐肤,替代 Builder 模式的同時(shí),可讀性還很強(qiáng)呼巴;
if 和 when 可以作為表達(dá)式。
同時(shí)御蒲,JetBrains 也非常清楚開(kāi)發(fā)者在什么情況下容易出錯(cuò)衣赶,所以,它在語(yǔ)言層面也做了很多改進(jìn):
強(qiáng)制區(qū)分“可為空變量類(lèi)型”和“不可為空變量類(lèi)型”厚满,規(guī)避空指針異常府瞄;
推崇不可變性(val),對(duì)于沒(méi)有修改需求的變量碘箍,IDE 會(huì)智能提示開(kāi)發(fā)者將“var”改為“val”遵馆;
基礎(chǔ)類(lèi)型不支持隱式類(lèi)型轉(zhuǎn)換,這能避免很多隱藏的問(wèn)題丰榴;
數(shù)組訪(fǎng)問(wèn)行為與集合統(tǒng)一货邓,不會(huì)出現(xiàn) array.length、list.size 不統(tǒng)一的情況四濒;
函數(shù)調(diào)用支持命名參數(shù)换况,提高可讀性,在后續(xù)維護(hù)代碼的時(shí)候不易出錯(cuò)盗蟆;
when 表達(dá)式戈二,強(qiáng)制要求邏輯分支完整,盡可能的減少了邏輯上的漏洞