從 Java 到 Scala,再到 Kotlin

在 Java 以後,JVM 平臺上出現了一些其餘的編程語言,Scala 和 Kotlin 能夠算是其中的佼佼者。Scala 已成爲大數據領域的明星,Kotlin 在 2017 年 Google IO 大會以後,儼然也成爲了安卓平臺潛力巨大的官方支持語言。他們都被冠以「更好的Java」而稱道,然而它們採用的是兩種不一樣的設計理念。前端

本文咱們會經過對比 Java、Scala、Kotlin 這三門語言各自的發展路線,來認識 Kotlin 的設計哲學。java

Java的發展

不得不說,Java是當今最成功的編程語言之一。自1996年Java問世,它始終霸佔着編程語言生態中很大的一塊。它的優點主要體如今:android

  • 多平臺與強大的社區支持。不管是在Web開發仍是移動設備,Java都是最主流的編程語言之一;
  • 尊重標準,有着嚴格的語言規範以及向後兼容性。所以Java很是適合開發團隊之間的協做,即便組織變更,新人一樣能夠在相同的規範下快速推動項目。

然而,隨着計算平臺的快速發展,平臺和業務自己對編程語言提出了更大的挑戰。Java的發展也受到環境變化所帶來的影響。如多核時代與大數據的到來,使得古老的函數式編程又從新變得「時髦」,Scala、Clojure這種多範式的編程語言開始受到愈來愈多開發人員的關注和喜好。另外一方面,Java的嚴格規範也經常被吐槽乏味。程序員

所以,Java必須開始改變。編程

Java 8的探索

若是說Java 5引入泛型是Java發展歷史上重大的進步,那麼Java 8的發佈也一樣意義深遠,它是Java對其將來發展一次嶄新的探索。Java 8引入了不少全新的語言特性,如:設計模式

  • 高階函數和Lambda。首次突破了只有類做爲頭等公民的設計,支持將函數做爲參數來進行傳遞,同時結合Lambda語法,改變了現有的程序設計模式;
  • Stream API。流的引入簡化了平常開發中的集合操做,並賦予了更強大的業務表達能力,並加強了代碼的可讀性;
  • Optional類。爲消除null引用所帶來的NullPointerException問題在類型層面提供了一種解決思路。 這一次的發佈在Java社區引來了不一樣尋常的反響,由於Java程序員開始感覺到另一種編程範式所帶來的全新體驗—也就是所謂的函數式編程。擁抱函數式也爲Java的發展指引了一個很好的方向。

Java將來會是什麼樣子

2016年11月在歐洲最大的Java峯會上,Oracle的Java語言架構師—Brian Goetz分享了關於Java這門語言將來發展的演講。本次會議最大的收穫,就是探索了將來Java可能支持的語言特性,它們包含了:安全

  • 數據類
  • 值類
  • 泛型特化
  • 更強大的類型推導
  • 模式匹配

以上的語言特性,對於初嘗函數式編程甜頭的Java開發者而言,是十分值得期待的。它們能夠進一步解放Java,讓開發工做變得更加高效和靈活。好比,一旦Java支持了數據類,咱們就能夠用很是簡短的語法來表示一個常見的數據對象類,就像這樣子:架構

public class User(String firstName, String lastName, DateTime birthday) 複製代碼

而用現在的JavaBean,則意味着好幾倍的代碼量,這一切都讓人火燒眉毛。與此同時,或許早有Java程序員開始了JVM平臺上另外一種語言的研究。這門語言已支持了全部這些新的特性,並在設計的一開始,就集成了面向對象和函數式兩大特徵,它就是Scala。編程語言

Scala的百寶箱

Scala是洛桑聯邦理工大學的馬丁(Martin Odersky)教授創造的一門語言。他也參與了Java語言發展的研究工做,Java 5引入泛型就是他的傑做。事實上,在Java剛發佈的時候,馬丁教授就開始了Java的改良工做—他在JVM平臺探索函數式編程,發佈了一個名爲Pizza的語言,那時就支持了泛型、高階函數和模式匹配。函數式編程

然而,在隨後的探索過程當中,他漸漸發現Java是一門具備硬性約束的語言,在某些時候不能採用最優的方式來實施設計方案。所以,他和他的研究夥伴決定從新創造一門語言,既在學術上合理,同時也具有實用價值,這就是Scala的由來。

學術和工業的平衡

Scala是一門很是強大的編程語言,正如它名字(Scalable—可拓展)自己,用Scala編程就像擁有了哆啦A夢的口袋,裏面裝滿了各類編程語言特性,如面向對象、函數式、宏。

Scala不只在面向對象方面進行了諸多的改良,並且完全擁抱了函數式。所以Scala也吸引了函數式編程社區不少厲害的程序員,他們將函數式編程的思想注入到了Scala社區,如此將使用Scala進行函數式編程提升到了新的高度。

因爲Scala設計者學院派的背景,以及它某些看似「不一樣尋常」的語法,它在發展早期(甚至如今)常常被描述爲「過於學院派」,以致於馬丁教授在某次Scala大會的演講時,自嘲「Scala真正的做用是將人引向了Haskell」。

然而,真實的Scala倒是在不斷地探索學術和實用價值兩方面的平衡。不能否認的是:

  • Scala已經成爲大數據領域的熱門語言,明星項目Spark就是用Scala開發,還有不少其餘知名的項目如Akka、Kafka;
  • 愈來愈多的商業公司如Twitter、PayPal、Salesforce都在大量使用這門語言。

另外一方面,Scala也確實是一門有着較陡的學習曲線的語言,由於它強大且靈活,正如馬丁教授本身所言,Scala相信程序員的聰明才智,開發人員能夠用它來靈活選擇語言特性。但學術和工業的平衡始終是一個難題,與Java嚴格標準相比,Scala的多重選擇也經常讓人吐槽它複雜。

複合但不復雜

那麼,Scala真的複雜嗎?咱們不知聽了多少次相似這樣的抱怨。在搞明白這個問題以前,咱們須要先弄清楚到底什麼是「複雜」。在英文中,複雜一詞能夠聯想到兩個單詞—complex和complicated。實際上它們的含義大相徑庭,更準確地說,complex更好的翻譯是「具備複合性」。 Nicolas Perony曾在Ted上發表過一次關於「複合性理論」的演講。

什麼是複合性?複合並非複雜。一件複雜的事物是由不少小部分所組成的,每一部分都各不相同,並且每一部分都在這個體系中有其自身的確切做用。與之相反,一個複合的系統,由不少相似的部分所組成,並且(就是由於)它們之間的相互影響,才造成了一種宏觀上一致的行爲。複合系統含有不少相互動的元素,它們根據簡單的、個體的規則行動,如此致使新特徵的出現。

馬丁教授一樣發表過一篇名爲《簡單仍是複雜》的文章,表達過相似的觀點。若是對搭積木這件事情進行思考,摩比世界提供固定的方案,而樂高提供了無窮的選擇。然而,前者的零件種類數量比後者要多得的。相似的道理,編程語言能夠依靠功能累加來構建所謂的語法,一樣也能夠經過簡單完備的理論來發展語言特性,在馬丁教授看來,Scala顯然屬於後者,它並不複雜,並且很是簡單。

簡單卻不容易

事實上,函數式編程最明顯的特徵就是具有複合性。函數式開發作的最多的事情,就是對所須要處理的事物進行組合。若是說面向對象是概括法,側重於對事物特徵的提取及歸納;函數式中的組合思想則更像是演繹法,近似數學中的推導。

然而,「簡單」的哲學也帶來了相應的代價:

  • 這是一種更加抽象的編程範式,諸如高階類型、Typeclass等高級的函數式特性雖然提供了無比強大的抽象能力,但學習成本更高;
  • 創建了另外一種與採用Java面向對象編程大相徑庭的思惟模式。這種思惟方式上的巨大差別,顯然是一個極高的門檻,同時也是形成Scala使人望而卻步的緣由之一。

Scala在選擇完全擁抱函數式的同時,也意味着它不是一門容易的語言,它沒法成爲一門像Java那樣主流的編程語言。事實上,即便不少人採用Scala來進行開發,也仍是採用相似Java的思惟模式來編程,換句話說,Scala依舊是被當作是更好的Java來使用,但這確實是當今主流編程界最大的訴求。

在這種背景下,Kotlin做爲一門JVM平臺上新興的編程語言,悄悄打開了一扇一樣廣闊的大門。

Kotlin—改良的Java

2010年JetBrains開始了創造Kotlin的想法。關於大名鼎鼎的JetBrains,想必是家喻戶曉,知名的IntelliJ IDEA就是他們的產品之一。擁有爲各類語言構建開發工具經驗的JetBrains,天然是對編程語言設計領域最熟悉的一羣人。當時,一方面他們看到了C#在.NET平臺上大放異彩,另外一方面,Java相比新語言在某種程度上的滯後,讓他們意識到了改良Java這門主流語言的必要性。

JetBrain團隊設計Kotlin所要面臨的第一個問題,就是必須兼容他們所擁有的數百萬行Java代碼庫,這也彷佛正好表明了Kotlin基於整個Java社區所承載的使命之一,即須要與現有的Java代碼徹底兼容。這個背景也決定了Kotlin的核心目標,就是爲Java程序員提供一門更好的編程語言。

Kotlin的實用主義

Kotlin經常被認爲是一門很是近似Scala的語言。的確,它們的誕生都源於Java語言的改良,同時都在面向對象和函數式之間創建起了多範式的橋樑。不能否認的是,Kotlin確實從Scala身上借鑑了許多,就連它的創做團隊也表示過:「若是你Scala用的很開心,那麼你並不須要Kotlin。」

然而,Kotlin與Scala的設計哲學又十分不一樣。Kotlin並無像Scala那樣熱衷於編程語言自己的研究和探索。相反,它在解放Java的同時,又在語言特性的選擇上表現得至關剋制。

咱們說過,Scala旨在成爲一門程序員夢想中的語言,它包含了全部你想擁有的語言特性。而Kotlin更加立足現實,它現階段仍沒有宏,也拒絕了不少所謂的高級函數式語言特性。但它在Java 的基礎上發展了不少改善生產力的語言特性,如數據類、when表達式(必定程度上的模式匹配)、擴展函數(和屬性)、可空類型等等,並且它彷佛偏好語法糖,好比Smart Casts,由於這可讓編程人員在工程中的開發變得更加容易。

能夠看出,Kotlin的自我定位很是清晰—它的目標就是在應用領域成爲一門實用且高效的編程語言。若是說Scala的設計理念是more than Java(不只僅是Java),那麼Kotlin纔是一門真正意義上的better Java(更好的Java)。

更好的Java

若是你用Kotlin開發過業務,很快就會意識到它相較於Java的語法,顯得更加簡潔、高效,好比Kotlin作了這些改良:

  • 極大程度上實現了類型推導,而Java在SE 10才支持了局部變量的推導;
  • 放棄了static關鍵字,但又引入了object,咱們能夠直接用它來聲明一個單例,做爲比較Java則必須依靠構建所謂的「單例模式」才能等效地表達;
  • 引入了一些在Java中沒有的「特殊類」,好比Data Classes(數據類)、Sealed Classes(密封類),咱們能夠構建更深程度上的代數數據類型,結合when表達式來使用。

但可能你會問,以上Kotlin的特性,Scala也有,可否能夠說前者只是後者的一個子集。這種表述實際上是不恰當的。其實,Kotlin在致力於成爲更好的Java的道路上,不只僅是依靠這些新增的語言特性,它在兼容Java方面的設計,作了大量的工做,比Scala走的更遠。

首先,從語言命名上就能夠看出Kotlin在嚴格遵循Java的先例,它們都採用了島嶼的名字。

Java的名字來源於印度尼西亞瓜哇島的英文名稱,而Kotlin是俄羅斯聖彼得堡附近的一個島嶼。

其次,雖然都是兼容Java,Scala(最近的幾個版本)必需要求Java 8,而Kotlin則能夠跟Java 6一塊兒工做,這也是後者在Android上更加流行的緣由之一。

另外,Kotlin並無像Scala那樣在語法的探索上表現得「爲所欲爲」,Java程序員在學習Kotlin新語法特性的同時,依舊能夠保留更多原有的習慣。舉個例子,在Scala中,一切皆有類型。因此大部分時間,咱們都用等號來定義一個Scala的函數。函數體最後一個表達式的值就是這個函數的返回類型。

def foo(x: Int) = {
    val y = x + 2
    x + y
}
複製代碼

沒錯,Scala捨棄了return關鍵字。在Kotlin中,它也引入了使用單行表達式來定義函數的語法,不須要用return來返回結果值。

fun foo(x: Int) = x * 2 + 2
複製代碼

然而,大部分狀況下,咱們仍是能夠採用相似Java的方式來定義一個函數,如:

fun foo(x: Int): Int {
    val y = x * 2
    return y + 2
}
複製代碼

因爲Kotlin比Scala更加兼容Java的生態和語法,Java程序員能夠更加容易地掌握它。另外一方面,Kotlin很是注重語法的簡潔表達。若是你瞭解Scala中的implicit,可能曾被這個Scala的語法驚嚇到,由於它很是強大。然而,正如咱們提到的「簡單靈活」的另外一面,則意味着抽象和晦澀。Kotlin注重的是工程的實用性,因此它創造了擴展的語法,雖然相比implicit在功能上有損,但顯得更加的具體直觀,且依舊很是強大,知足了平常開發中絕大多數的需求。值得一提的是,Android則依靠這個Java所沒有的特性,推出了擴展庫android-ktx。

此外,Kotlin還新增了一些Java、Scala中沒有的語法糖。若是你從事Android開發,那麼確定少不了在工程中寫過這樣子的Java代碼:

if(parentView instanceof ViewGroup){
    ((ViewGroup) parentView).addView(childView);
}
複製代碼

爲了類型安全咱們不得不寫兩遍ViewGroup,然而在Kotlin中咱們卻能夠直接這麼寫:

if(parentView is ViewGroup){
    parentView.addView(childView)
}
複製代碼

這依靠的是Kotlin中的Smart Casts特性,咱們不評價這種語法糖是否好壞,但它能夠在必定程度上改善咱們在工程中的開發體驗。

整體而言,Kotlin旨在成爲一門提高Java生產力的更好的編程語言,它擁有簡潔的表達能力、強大的工具支持,同時至今仍然保持着很是快速的編譯能力。相較而言,用Scala開發則經常受到編譯過慢而帶來的困擾。

強大的生態

如今,咱們已經瞭解了Kotlin總體的設計哲學,以及它相較Java、Scala的魅力所在。固然,本文彷佛並無任何關於語法細節的介紹,不着急,咱們會在後續的內容中深刻介紹Kotlin的語言特性,而且探索它具體的高級應用。

關於Kotlin,還有一個問題須要解答—咱們究竟能夠用它來作什麼。大機率上你是由於Kotlin成爲Android官方支持語言的新聞而知曉它的。事實上,Kotlin不只支持Android,它仍是一門通用語言,若是用一句話來總結,那就是「Targeting JVM / JavaScript and Native」。現階段的Kotlin咱們至少能夠用它作如下的事情:

  • Android開發

咱們不只能夠用Kotlin調用現成的Java庫,並且還有Google提供的Kotlin擴展庫。Kotlin的語法很是適合Android工程開發,例如咱們提到過的Smart Casts,用它還能夠改善findViewById的語法調用;

  • 服務端開發

這是JVM語言最大的一個應用領域,天然也是Kotlin發揮的舞臺。在Android支持Kotlin以後,Spring Framework 5也對它敞開了懷抱。基於Kotlin更天然的函數式特性,用Spring進行Web開發會在某些方面擁有比Java更好的體驗;

  • 前端開發

Kotlin還有兩個強大的特性—dynamic類型以及類型安全的構建器,前者實現其與JavaScript互通,後者能夠幫助開發者構建可靠的HTML頁面。你能夠嘗試使用Kotlin來構建UI。

  • 原生環境開發

由於Kotlin Native這個項目,Kotlin終於告別了Java,離開了JVM,直接編譯成機器碼供系統環境運行。雖然Kotlin Native尚處於早期階段,但後續的發展很是值得期待。若是你家裏有一個樹莓派,不妨能夠用它來試一試。

如你所見,Kotlin仍是一門很是開放、具備強大生態的編程語言。若是說與Java兼容能讓它運行在全部支持Java的地方,那麼它的革命創新使得它超越了Java,進入了更加廣闊的世界。

小結

咱們打算用一個比喻來結尾。這個生動形象的說法來自於Lutz Hühnken的博客,他把Java、Scala、Kotlin比做滑雪運動中的不一樣種類。

若是說JVM平臺是一個滑雪世界,那麼最先的Java語言就是你們最熟知的滑雪方式—雙腳各踏一個滑雪板來進行滑雪。Scala則更像將兩隻腳都站在一塊單板上來滑行的滑雪方式。那些用滑雪單板的高級運動員很是使人羨慕,由於他們能夠用更優雅的姿式得到更快的速度,並且最重要的是他們能夠作「深粉雪」滑行,這也就是所謂的函數式編程。

然而,對於用慣雙板滑雪的運動員而言,嘗試用單板來滑雪,就像是學習一種新的運動,會常常摔跤。其實,大部分人仍是更樂意用雙板來進行滑雪。這時候,刻滑板出現了,使用它,運動員徹底能夠保留原有雙板的習慣,但同時依舊能夠作某個程度上的深粉雪滑行。你猜的沒錯,它就是Kotlin。

對於滑雪這項運動而言,別忘了,還有一個世界性的賽事—Android開發,它暫時並無對單板開放,但對刻滑板則已經敞開了懷抱。

因此,若是你是想要尋找一種更好的Java語言的話,歡迎來到Kotlin的滑雪世界!

以上內容摘自《Kotlin核心編程》

相關文章
相關標籤/搜索