What
官網(wǎng)
Kotlin由JetBrains負(fù)責(zé)維護(hù), 在2011年宣布發(fā)布, 2012年正式發(fā)布第一個(gè)版本, 2016年發(fā)布1.0版本. 目前最新的版本是1.1.
而JetBrains是IntelliJ IDE的開(kāi)發(fā)商, Android Studio是基于IntelliJ的, 可以說(shuō)Kotlin就是親兒子, 有絕對(duì)好的IDE支持.
Why
趨勢(shì)
- Google 宣布官方支持 Kotlin, Android Announces Support for Kotlin
- Android Studio 3.0會(huì)內(nèi)置Kotlin, 在項(xiàng)目中使用Kotlin會(huì)非常方便, 而且可以預(yù)見(jiàn)未來(lái)會(huì)有越來(lái)越多的支持.
- 社區(qū), 從1.0到現(xiàn)在, Kotlin已經(jīng)形成了社區(qū), 雖然仍比不上Java, 但是已經(jīng)有非常多的資源, 現(xiàn)在更是有了Google的支持, 發(fā)展的勢(shì)頭只會(huì)越來(lái)越猛.
- 企業(yè), 已經(jīng)有Expedia, Flipboard, Pinterest, Square等公司在企業(yè)級(jí)應(yīng)用中使用了Kotlin, Kotlin for Android Case Studies中提到3個(gè)例子, 有大公司的帶頭踩坑, 相信能夠證明Kotlin可以勝任實(shí)際生產(chǎn)的使用.
完美兼容Java
完美兼容的意思是我們可以將Java代碼和Kotlin代碼混合在一起.
這意味著在Kotlin表現(xiàn)不好的地方, 我們可以保留Java的代碼, 在項(xiàng)目中只使用團(tuán)隊(duì)認(rèn)為合適的特性.
同樣, 這意味著我們可以局部接入Kotlin而不是一次性把整個(gè)項(xiàng)目改頭換面.
簡(jiǎn)潔
Kotlin有非常多的語(yǔ)法糖, 可能有些好用, 有些太過(guò)簡(jiǎn)潔, 但是不可否認(rèn), 使用Kotlin可以減少非常多的代碼量, 能夠提升日常開(kāi)發(fā)的效率, 盡管Java有各種各樣的IDE插件支持也能實(shí)現(xiàn)自動(dòng)生成代碼, 但是一個(gè)文件越少內(nèi)容閱讀起來(lái)越容易理解不是嗎?
功能
雖然Java能夠通過(guò)插件來(lái)避免手動(dòng)輸入代碼, 不過(guò)有些功能則是Kotlin有而Java沒(méi)有的.
不是說(shuō)所有這些新功能都很好, 但是合理使用這些功能特性確實(shí)可以簡(jiǎn)化代碼結(jié)構(gòu)和更加方便地實(shí)現(xiàn)某些特定需求.
How
資源
官方使用Kotlin開(kāi)發(fā)Android的說(shuō)明文檔
中文版Kolton文檔
Kotlin在線(xiàn)編輯器學(xué)習(xí)
官方書(shū)籍: Kotlin In Action, github上正在更新的翻譯項(xiàng)目
最吸引的特性
從寫(xiě)代碼的角度看, Kotlin比Java好在哪?
永別NPE(NullPointerException)
null
類(lèi)型在Java中被吐槽了很多年了, 空指針錯(cuò)誤也是項(xiàng)目中常見(jiàn)的造成崩潰的異常, Android中一般會(huì)使用注解庫(kù)的@Nullable
和@NonNull
來(lái)輔助檢查, 不過(guò)這依賴(lài)于開(kāi)發(fā)者的自覺(jué)性, 而這通常很不可靠.
在Kotlin中在語(yǔ)法上區(qū)分空和非空
在Java的一個(gè)普通方法里面我們要做非空檢查, 例如
@Override
public void showMovie(Movie movie) {
if(movie != null) {
mTextView.setText(movie.name);
}
}
而在Kotlin中
// Movie不可能為null
override fun showMovie(movie: Movie) {
mTextView.setText(movie.name)
}
// Movie可能為null
override fun showMovie(movie: Movie?) {
mTextView.setText(movie?.name)
}
在第一情況里面, Movie
不可能為空, 如果調(diào)用時(shí)傳空值, 會(huì)發(fā)生編譯錯(cuò)誤.
在第二種情況里面, 只要添加?
就可以傳空值, 但是同樣不用進(jìn)行空值判斷, 因?yàn)?code>movie?.name在空值的情況下是不會(huì)執(zhí)行.
實(shí)際的好處
- 省略了非常多的非空判斷
- 從根源上防止了NPE的發(fā)生
類(lèi)型檢查和轉(zhuǎn)換
在列表的Adapter里面經(jīng)常有下面的代碼
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
if(holder instanceof AHolder) {
((AHolder)holder).textView.setText(null);
((AHolder)holder).imageView.setSelected(true);
}
}
為什么已經(jīng)有了
instanceof
判斷后, 還需要強(qiáng)制轉(zhuǎn)換呢?
連續(xù)的強(qiáng)制類(lèi)型轉(zhuǎn)換會(huì)讓代碼非常長(zhǎng), 進(jìn)而影響閱讀性.
在Koltin中只要
if(holder is AHolder) {
holder.textView.setText(null);
holder.imageView.setSelected(true);
}
編譯器會(huì)自動(dòng)幫我們進(jìn)行轉(zhuǎn)換, 這只是其中一個(gè)例子, 在很多地方都可以省略強(qiáng)制類(lèi)型轉(zhuǎn)換, 使得代碼更簡(jiǎn)介.
命名參數(shù)和默認(rèn)參數(shù)
在需要輸入大量參數(shù)的時(shí)候我們一般使用Builder和鏈?zhǔn)秸{(diào)用, 例如:
new Request.Builder()
.setDomainName("baidu.com")
.setSecondDomainName("tieba")
.setApi("path")
.setFixed(true)
.setIsHttps(false);
當(dāng)要輸入的參數(shù)太多, 不可能使用構(gòu)造函數(shù), 因?yàn)椴荒艽_定哪些是用戶(hù)想自定義的, 使用Kotlin則只需要定義一個(gè)構(gòu)造函數(shù)包含所有參數(shù), 例如
constructor(port: Int = 8080,
api: String? = null,
secondDomainName: String? = null,
domainName: String? = null,
isHttps: Boolean = false,
isFixed: Boolean = false) {
// 省略賦值
}
// 只賦值部分參數(shù)
Request(api = "path", isFixed = true)
不再需要建造者模式, 不再需要鏈?zhǔn)秸{(diào)用的代碼, 同時(shí)命名參數(shù)指明了參數(shù)含義, 代碼的可讀性沒(méi)有受到影響.
擴(kuò)展函數(shù)
在我們的代碼中經(jīng)常需要增加工具類(lèi)來(lái)對(duì)某些類(lèi)進(jìn)行封裝方便使用, 例如獲取顏色的代碼
public static getColor(Context context, int resId) {
return context.getResources().getColor(resId);
}
在Kotlin我們可以選擇擴(kuò)展Int
類(lèi)型, 而不需要另外建一個(gè)工具類(lèi)
fun Int.toColor(context : Context) : Int = context.resources.getColor(this)
// 調(diào)用
R.color.ct_02.toColor(context)
這里的例子可能不是很合適, 但是合理使用擴(kuò)展函數(shù)可以
- 大量減少工具類(lèi),
- 讓具體的項(xiàng)目可以自行擴(kuò)展公共的基礎(chǔ)庫(kù)的類(lèi), 這樣當(dāng)基礎(chǔ)庫(kù)不能滿(mǎn)足項(xiàng)目需要時(shí), 不需要再新建一個(gè)名字類(lèi)似功能類(lèi)似的新類(lèi).
數(shù)據(jù)對(duì)象
項(xiàng)目中會(huì)包含非常多的Json映射類(lèi), 大量的getter/setter
, toString
方法, 現(xiàn)在Kotlin只需要一個(gè)data
關(guān)鍵字就能滿(mǎn)足幾個(gè)IDE插件做的事.
-
equals()
/hashCode()
函數(shù) -
toString()
函數(shù) -
copy()
函數(shù)
lambda和函數(shù)類(lèi)型
這兩個(gè)特性應(yīng)該不需要舉例了, 再也不需要在View#setOnClickedListener
的時(shí)候創(chuàng)建監(jiān)聽(tīng), 可以大幅減少代碼的行數(shù).
函數(shù)類(lèi)型可以減少不必要的接口定義.
其他
-
when
語(yǔ)法取代switch
, 再也不用擔(dān)心漏掉break
-
[]
可以同時(shí)在數(shù)組和列表中使用 -
in
表示范圍, 不再需要a > 0 && a < 10
, 只要a in 0..10
這里只是一篇小小的總結(jié)文章, 還有更多我不熟悉和還沒(méi)發(fā)掘到特性等待你去嘗試.
當(dāng)然, Kotlin也肯定有他不好的地方, 或者有人覺(jué)得太過(guò)簡(jiǎn)潔反而不好, 有人覺(jué)得Kotlin還太年輕可能到處是坑, 也需要一段時(shí)間的學(xué)習(xí)和適應(yīng), 陣痛是肯定會(huì)有的, 但是身為程序猿不就是應(yīng)該為了追求更好更高效率而去踩坑么, 現(xiàn)在有更好的放在你面前, 為什么不試試呢? 畢竟老大們都上了 :D