為啥 Kotlin 是我下一個(gè)要掌握的語言
Kotlin 是 JetBrains 的一門新的編程語言,這個(gè)公司開發(fā)了世界上最好用的 IDE。經(jīng)過一段時(shí)間的研究,我決定將其作為今后5到10年的時(shí)間里用到的一門編程語言。
我 很喜歡 Kotlin,它肯定會成為一個(gè)成功的項(xiàng)目。有人看到我在我的開源項(xiàng)目里用了這門語言,就讓我說點(diǎn)什么,那么在這篇文章里我就來說一說為什么我覺得 Kotlin 好了。接下來我還會說一下,如果你現(xiàn)在就開始用這門語言,會遇到的問題。最后我會告訴你 Kotlin需要用到 JVM,這個(gè)你需要考慮一下(因?yàn)槟阋苍S正在用 Go 或者 Node),但是我認(rèn)為這不是問題。
請注意 Kotlin 目前還是 beta 版:1.0正式版有望在2015年底發(fā)布,會提供穩(wěn)定的語言特性和標(biāo)準(zhǔn)庫。
Kotlin好在哪里
本文一開始似乎有點(diǎn)奇怪:通常鼓吹某個(gè)編程語言的文章一上來都會列出新語言都有哪些酷的特性。不過本文不是這樣,哪些我們稍后一些再聊。
我們先了解一下其他方面,因?yàn)獒槍﹂_發(fā)人員評估編程語言,一個(gè)2013年的研究表名,編程語言的特性相對于語言的生態(tài)來說,重要程度相對要低一些,這也跟我的經(jīng)驗(yàn)相符。那么,下面就是我們需要先介紹的:
Kotlin 會編譯成 JVM 字節(jié)碼或者 JavaScript。它不需要新寫一個(gè)編程語言內(nèi)核。Java 開發(fā)者肯定會很感興趣這門語言,不過對于其他所有使用帶有垃圾收集機(jī)制的語言的開發(fā)者來說,同樣值得關(guān)注,這些語言包括 Scala, Go, Python, Ruby 和 JavaScript。
Kotlin 源自產(chǎn)業(yè)界, 而非學(xué)院。它解決了當(dāng)前程序設(shè)計(jì)所面臨的實(shí)際問題。例如,類型系統(tǒng)可以避免空指針異常的問題。
使用 Kotlin 不需要費(fèi)用! 它是開源的, 但這不是我要說的,我要說的是它有一個(gè)高質(zhì)量的,Java 到Kotlin 轉(zhuǎn)換工具,非常關(guān)注 Java 二進(jìn)制的兼容性。你可以將一個(gè) Java 工程全部轉(zhuǎn)換,一次只能轉(zhuǎn)換一個(gè)文件。甚至上百萬行的復(fù)雜程序。這就是我為什么使用 Kotlin 的原因,我期待所有的開發(fā)者都使用它。
上面已經(jīng)顯示,Kotlin 程序可以使用已經(jīng)存在的 Java 框架和類庫,甚至依籟注解處理的高級框架?;ゲ僮魇菬o縫的,而且不需要包裝器和適配層。它可以集成Maven,Gradle或者其他的編譯系統(tǒng)。
它很容易上手,簡單地閱讀一下參考手冊幾個(gè)小時(shí)就可以學(xué). 語法精益而直觀。Kotlin 有點(diǎn)像 Scala, 但它更簡單。語言平衡了簡潔和可讀性。
它沒有強(qiáng)制的編程哲學(xué),像過度函數(shù)編程和面向?qū)ο箫L(fēng)格。
它沒有運(yùn)行時(shí)開銷, 標(biāo)準(zhǔn)庫小而緊湊,它主要包括 Java 標(biāo)準(zhǔn)庫的擴(kuò)展。大量使用內(nèi)聯(lián)編譯時(shí)間的功能性結(jié)構(gòu)類似 map/filter/reduce 管道。
與 Anko 和 Kovenant 這樣的框架結(jié)合,輕量的資源意味著 Kotlin 開始在 Android 開發(fā)者中流行如果你在做 Android 開發(fā),你很快就會獲得好的工作單位。你可以閱讀 a report written by a developer at Square,分享了他們使用 Kotlin 和 Android 的經(jīng)驗(yàn),Kotlin 代碼就像 Java 一樣。完全支持調(diào)試,單元測試,分析等等。
除 Android 之外, 我認(rèn)為 Kotlin 特別適合于處理商業(yè) Java 業(yè)務(wù)。如果你在一個(gè)很大的公司整天面對著一個(gè)龐大的 Java 代碼庫,那么你應(yīng)該趕快著手研究 Kotlin 了:
-
Kotlin 有著知名公司提供的強(qiáng)有力的商業(yè)支持。JetBrains 承諾:有一個(gè)高效出色的大型團(tuán)隊(duì)正在致力于 Kotlin 的開發(fā)工作,而且對 Kotlin 運(yùn)用穩(wěn)定的商業(yè)模式,甚至正在將自己的部分旗艦產(chǎn)品轉(zhuǎn)換成用于使用 Kotlin。于是 Kotlin 不太可能會在短期內(nèi)被拋棄。
-
采用 Kotlin 是低風(fēng)險(xiǎn)的:可以在你代碼庫的一小部分里,通過一兩個(gè)熱衷于此的團(tuán)隊(duì)成員在不影響項(xiàng)目其他代碼的前提下進(jìn)行試用。Kotlin 的類能夠?qū)胍粋€(gè) Java 的 API,使得這看起來就像正常的 Java 代碼
-
由于 Kotlin 專注于語法的可讀性,從而使得代碼的審查易于進(jìn)行:即便不熟悉 Kotlin 語言的團(tuán)隊(duì)成員也同樣可以完成.
-
Kotlin以Java 6 為目標(biāo),所以即使在部署新版本 JVM 遇到困難的情況,你也仍然能夠使用Kotlin。
今年的早些時(shí)候我曾向一家大型保險(xiǎn)公司,瑞士再保公司(Swiss Re)的一個(gè)以 Java 和 .NET 作為架構(gòu)的團(tuán)隊(duì)展示過 Kotlin. 我以這樣的方式開始,用 Java 定義了一個(gè)類,這個(gè)類帶有一些字段,和 toString, equals, hassCode 諸如此類的方法等等。這大約用了 50 行代碼。當(dāng)我將其轉(zhuǎn)化為 Kotlin 的時(shí)候(基本上是自動完成的),這個(gè)類縮小到了只剩一行代碼。然后我又演示了其他可以節(jié)省敲代碼時(shí)間的特性??吹竭@些他們都很激動,并將 Kotlin 視為他們項(xiàng)目的潛在競爭者。
我想 Kotlin 為商用 Java 開發(fā)提供了一個(gè)恰當(dāng)?shù)臅r(shí)機(jī),所以盡管 Kotlin 可以免費(fèi)使用,不過隨著商業(yè)版本 IDE 銷售額的增加,我預(yù)計(jì) JetBrains 定會大賺一筆. 而這也將刺激他們依照廣大客戶的意愿來不斷提升自身的產(chǎn)品.
與此相比,那些從與現(xiàn)有IDE不相關(guān)的產(chǎn)品中得到資助的其他語言開發(fā)者們,他們則很少會因?yàn)橛脩舻男枨笈c自身產(chǎn)品先入為主的理念不一致,就做出相應(yīng)的調(diào)整。
功能特性
Kotlin 因其對生態(tài)系統(tǒng)上的關(guān)注而從海量新興編程語言中脫引而出: JetBrains 了解到生產(chǎn)力的來源不只是在于更方便的語法。
盡管如此,Kotlin 還是有許多有用的功能特性,它們讓編寫代碼的人樂在其中:
-
我們已經(jīng)提起過 空指針安全 (這是可選的一項(xiàng)功能),它會讓編譯器系統(tǒng)性的將潛在的空指針標(biāo)識為無效的。不想某些語言那樣,這并不會涉及到一個(gè)可選類型且因此是零開銷的 。其它的語言特性確保了它不會是不方便的。
-
精益的語法: 類型推斷在任何地方都能起作用,單行方法只用一行就行了,簡單的結(jié)構(gòu)體或者JavaBean也可以用一行就能被聲明出來。 Real 屬性 會在幕后為 Java 互操作生成 getFoo/setFoo 方法。函數(shù)可以存在于類的外部。
-
異常是未經(jīng)檢查的。
-
向一個(gè)類添加 data 注解會觸發(fā)樣板程序的自動生成,像是 equals, hashCode, toString, copy 方法還有對可變擴(kuò)展的支持。無需構(gòu)建器你就很方便的擁有了不可變的類。
-
而如果你確實(shí)需要構(gòu)建復(fù)雜的結(jié)構(gòu),有一種靈巧的語言特性的組合能使得 構(gòu)建器 條理清晰且類型安全(讀是可自動完成的)。如果你是使用的 Google Protocol Buffers 來存儲結(jié)構(gòu)性的數(shù)據(jù),那也會更加的容器。
-
對函數(shù)式編程的支持 使用了 零開銷的 lambda 以及在 Java 集合上做映射和折疊的能力。Kotlin 的類型系統(tǒng)能在集合上做可變和不可變視圖的區(qū)分。
-
擴(kuò)展函數(shù) 讓你可以給類添加方法,而無需修改他們的源代碼。這在初次看起來像是一個(gè)用來避免 FooUtils 風(fēng)格的類的語法糖。到后來你會發(fā)現(xiàn)這樣做讓你可以很容易的通過自動補(bǔ)全功能來發(fā)現(xiàn)新的方法,使你可以構(gòu)建出強(qiáng)大的語言擴(kuò)展并讓你可以將現(xiàn)有的 Java API 同 Kotlin 的特性集成。這些特性有 …
-
操作符重載。而這個(gè)確實(shí)不錯(cuò):這里沒有 Scala / Perl 風(fēng)格的行搗亂了。操作符映射到特定的方法名稱,如此就能重載現(xiàn)有操作符的行為了(包括函數(shù)的調(diào)用), 但是你不能定義一個(gè)完全是新的操作符。這樣就達(dá)到了能力和可讀性之間的一個(gè)平衡。
-
Kotlin 并沒有宏或者其它方式來對語言進(jìn)行重新定義,但是有一些小心設(shè)計(jì)出來的特性,使得那些庫表現(xiàn)得更像語言擴(kuò)展,而不是對象的集合。
-
你會喜歡使用 fiber, actor, 和 Go風(fēng)格的 channel 嗎? 一個(gè)叫做 Quasar 的庫為你涵蓋到了這些。
-
使用 Markdown 而不是 HTML 來制作你的 API 文檔。這使得編寫 JavaDoc 令人高興了許多。
-
更好的 generics。如果你在放入一個(gè)類型變量時(shí),超類和擴(kuò)展究竟有什么意義從未得到完全認(rèn)真的處理, 別擔(dān)心:這不是你的問題。Java 的 generics 確實(shí)有點(diǎn)令人困惑。Kotlin 解決了這個(gè)問題。
-
派發(fā) (轉(zhuǎn)發(fā)方法) 是自動的。
-
== 操作符真正做了你實(shí)際期望的事情。
-
你喜歡快速和方便的異步編程嗎? 你當(dāng)然會喜歡的。
-
字符串插值“works like ${this.example}!”
-
函數(shù)參數(shù)可以被命名、可選而且類型可變。
-
許多許多其它的調(diào)整和改進(jìn)。如果 Java 的有些東西讓你不爽的話,我感覺其中一半的不爽在 Kotlin 中都不會有。
現(xiàn)在就來試一下!
跟很多現(xiàn)代編程語言一樣,Kotlin 可以通過瀏覽器來進(jìn)行實(shí)驗(yàn)性的使用。不過跟其他語言不一樣的是,Kotlin 的實(shí)驗(yàn)網(wǎng)站展現(xiàn)給你的是一個(gè)完全成熟的 IDE,包括響應(yīng)很快的自動完成,實(shí)時(shí)的背景編譯,甚至還有在線的靜態(tài)分析!
來試試吧
繼續(xù)嘗試一下。然后回來我們繼續(xù)。
有啥問題不?
生活中沒有十全十美,Kotlin 也如此。這里是我試用這門編程語言時(shí)遇到的一些問題。
最大的問題是不成熟。Kotlin 是一個(gè)未到 1.0 版本的語言。 這意味著:
-
語言本身,ABI 和 標(biāo)準(zhǔn)庫會在每個(gè)發(fā)行版中發(fā)生變化。好消息是,這些變化往往都比較小,而且 Intellij 可以經(jīng)常為你升級你的代碼。所以這沒有聽起來那么痛苦。
-
Java-to-Kotlin 轉(zhuǎn)換器 (J2K) 還未開發(fā)完成。它有時(shí)會胡亂的格式化并且會默默的刪除 Java 8 lambda 表達(dá)式(2015 年 10 月修改:用于 M13 版的轉(zhuǎn)換器目前已經(jīng)可以正確的處理 Java 8 的特性)。而且它產(chǎn)生的代碼也不總是最佳的編寫方式。但是 JetBrains 公司正在為這個(gè)工具投入顯著的精力,而且這已經(jīng)是我用過的同類產(chǎn)品之中最好的了。所以我并不太擔(dān)心這一點(diǎn):它將很快的越來越完善。
-
你將遇到編譯器 bug。我的程序并不大,但我經(jīng)常遇到應(yīng)該編譯的代碼沒有被編譯,或者(更糟糕的情況)代碼被編譯成了錯(cuò)誤的東西。診斷這些問題并不是太困難,但這會給我們帶來不好的體驗(yàn)。
-
你將遇到內(nèi)部 IDE 錯(cuò)誤。 當(dāng)發(fā)生這種情況時(shí)你會看到一個(gè)提示氣泡以及一個(gè)匯報(bào)給 JetBrains 公司的選項(xiàng)。IDE 不會關(guān)閉,大多數(shù)錯(cuò)誤似乎沒有太大的問題。但無論如何,這是很煩人的。
-
文檔有時(shí)會參考未實(shí)現(xiàn)的特性(修改:在 M14 版本中我相信這已經(jīng)不再是一個(gè)問題了)。
現(xiàn)在 JetBrains 公司正在專注于 1.0 版本的完善而不是添加新特性,我希望這些問題都已經(jīng)得到解決。
我遇到的第二大的問題,就是有時(shí)候其與 Java 的交互有一些局限。
一個(gè)典型的 bug 就是 Java 的類型系統(tǒng)無法保證你不改變 map 中 key 的類型。按照常理來說,如果你這樣做將會導(dǎo)致編譯錯(cuò)誤,比如說,使用錯(cuò)誤類型的 key 來刪除元素。但是當(dāng) JDK 集合使用了泛型,其中有些重要的方法的參數(shù)是 Object 的話,編譯器就不會報(bào)錯(cuò)。在 Intellij 中編寫 Java 代碼時(shí)這種情況可以被標(biāo)記成黃色的靜態(tài)分析警告,但到目前為止 Kotlin 編輯器還沒有這種功能(某些時(shí)候)。因?yàn)?Kotlin 沒有定義任何自己的集合類庫,這將導(dǎo)致一些類型安全性方面的一些問題,我已經(jīng)遇到過好幾次了。
另一個(gè)例子是,當(dāng)調(diào)用或使用 Java 代碼時(shí),Kotlin 的 null 的安全特性是被禁用的(可以使用注解來彌補(bǔ))。因?yàn)樽鰹?Kotlin 初學(xué)者你可能會寫很多調(diào)用 Java 類庫的代碼,但是這個(gè)功能沒有你希望的那么有用。這只能等到 Kotlin 占有量增長來改善了。JetBrains 公司已經(jīng)在嘗試解決與 Java 交互時(shí) null 的安全特性的問題了:他們的想法是好的,但是有時(shí)卻未能發(fā)現(xiàn)問題。他們想要這么做來修復(fù) null 的安全特性與 Java 交互的問題。(修改:在 M13 版中他們使用 Java @NotNull 注解來解決)
另一方面,這也能讓你更流暢的使用 Java API,我認(rèn)為這種折衷是值得的。但是需要多加注意。
其他需要考慮的問題:
-
社區(qū)比較小。雖然出色的與 Java 交互性意味著你并不真的需要 Kotlin 庫,不過有總比沒有強(qiáng),然而目前并不多。
-
如果你喜歡通過看書來學(xué)習(xí),你將不得不等到今年晚些時(shí)候, Manning 將會出版一本。在此之前并沒有任何網(wǎng)站或其他東西。
-
函數(shù)式編程(FP)的死忠可能會覺得類型系統(tǒng)缺乏類似 Scala 或 Haskell 中的一些高級的功能。如果你是比較在乎類型系統(tǒng)的人,Kotlin 可能并不適合你。
-
雖然它可以向下編譯成 JavaScript,但這種模式似乎與 JVM 后臺相比不太好用,你可能會遇到更多的問題,需要說明的是我也沒有使用它的經(jīng)驗(yàn),這只是在逛論壇時(shí)我留下的印象(修改:為了更快的推出 Kotlin 1.0 版,JS 后臺已經(jīng)是非優(yōu)先的了,當(dāng)在 JVM 上穩(wěn)定之后 JetBrains 才會繼續(xù)做這項(xiàng)工作)。
-
沒有標(biāo)準(zhǔn)風(fēng)格的指南,而且有時(shí) Kotlin 會提供好幾種語法讓你選擇。不同程序員寫的 Kotlin 代碼可能看起來是不一樣的。這是對于 Go 語言的硬性強(qiáng)制風(fēng)格來說的。(修改:在 M14 版本中去掉了一些語法的靈活性,所以操作者必須明確的標(biāo)示。)
-
Kotlin 的編譯速度比 Java 稍微慢一點(diǎn),而且 Intellij 編輯器更慢。但并不是很嚴(yán)重,而且二者都比 Scala 要快。
-
有一個(gè) Kotlin 的 Eclipse 插件,但自然它的完善度要比 Intellij 支持的少得多。Kotlin 在你的團(tuán)隊(duì)規(guī)定使用 Intellij 開發(fā)時(shí)才能工作在最佳狀態(tài)。
-
Kotlin 比 Java 更挑剔。它不會自動將整型轉(zhuǎn)換成長整型,你必須明確的顯式轉(zhuǎn)換。這是因?yàn)樵撜Z言更看重正確性,而且嘗試修復(fù)在“Java 解惑”一書中發(fā)現(xiàn)的一些著名的問題。JetBrains 公司聲稱他們修正了其中的一半。
-
因?yàn)?Kotlin 是基于 Java 6 的,它只包含該運(yùn)行時(shí)具有的功能。雖然他可以在很多領(lǐng)域中趕上或超過 C#,但它缺乏還不是 Java 平臺的一部分的類似值類型的特性。
為什么你真的需要對 JVM 做一些考慮
最近一段時(shí)間我遇到了很多使用動態(tài)腳本語言(如JavaScript,Go)的創(chuàng)業(yè)公司。
我在比特幣工作的時(shí)候,使用動態(tài)語言是非常痛苦的事情。在這些工具里沒有安全性的類型導(dǎo)致了巨大的貨幣損失。Go 出錯(cuò)少點(diǎn),但是仍然在基礎(chǔ)的東西上體驗(yàn)很差,比如說缺少好的調(diào)試工具,快速 GC,穩(wěn)健的管理器還有可靠的分析工具。
過去15年或更長時(shí)間,Java 變得越愛越長,并且被過分使用--在很大程度上源于它的聲譽(yù)。企業(yè)級 Java 的類的名字類似于 PathVariableMapMethodArgumentResolver 那么長。很長一段時(shí)間,我不考慮 JVM,我確信這種環(huán)境不是給我設(shè)計(jì)的。
最終我因?yàn)橐?Android 而不得不轉(zhuǎn)向 Java。結(jié)果發(fā)現(xiàn)已經(jīng)變了樣。雖然 XML 比起我們根據(jù)潮流所做的預(yù)期來,仍舊更加頻繁的被派上用場,而基礎(chǔ)設(shè)施的能力已經(jīng)非常令人印象深刻了。IntelliJ 比起 Eclipse 來要快很多也更加的直觀。Maven,盡管一開始的時(shí)候勢不可擋,結(jié)果卻是大量在其它構(gòu)建/依賴管理系統(tǒng)中有的功能特性才是我想要的。較新的像 Ninja 和 Play 這些 web 框架從諸如 Ruby on Rails 這樣的項(xiàng)目那里學(xué)到了敏捷的方法。還有大量的庫。硬件已經(jīng)變得更好了,JVM 也變得更有效率。諸如此類,不一而足。
一個(gè)比較大的,還并沒有真的發(fā)生改變的東西就是語言本身。Java 的代碼寫起來仍然是冗長而令人痛苦和乏味的。
如今有了 Kotlin,傳統(tǒng)中同 Java 生態(tài)系統(tǒng)有關(guān)的最后一個(gè)痛點(diǎn)也成了過去式。你可以編寫更具表達(dá)能力,而且甚至比一種腳本語言更簡潔的代碼,然而 bug 更少,性能也更好。你可用上所有這些很棒的工具:只要嘗試一下捆綁的 VisualVM 程序,來體味一下在這個(gè)生態(tài)系統(tǒng)中那些可以免費(fèi)試用的東西,或者如果你愿意花些錢,就可以上 Chronon 時(shí)間旅行調(diào)試器 網(wǎng)站看看你可以得到些什么。
如果你喜歡 JavaScript,可以嘗試 Kotlin 的后端JS?;蛘咴?Nashorn JS 引擎里運(yùn)行你現(xiàn)有的代碼。
最后,如果你喜歡 GO 語言是因?yàn)樗鼤瑟?dú)立的程序,看看 javapackager 的工具。Kotlin 在本地為每個(gè)平臺創(chuàng)建了捆綁包,這意味著在 linux 上不需要 JRE 的依賴就可以獨(dú)立自主的獲取 DEBs(linux 的安裝包)或者壓縮包。當(dāng)然,從部署的角度來看,它拆開之后不是單個(gè)文件,而是不難運(yùn)作的單個(gè)目錄。
簡而言之:如果你之前因?yàn)?JVM 的生態(tài)不流行而忽略了它,你可以再看看 Kotlin 或者把握住它。