第1章 Kotlin是什麼java
當下互聯網大數據雲計算時代,數以百萬計的應用程序在服務器、移動手機端上運行,其中的開發語言有很大一部分是用流行軟件界20多年的、強大穩定的主力的編程語言Java編寫。git
若是咱們用一輛汽車來比喻編程語言的話,Java 擁有一個快速、可靠的發動機,但防抱死剎車系統,動力轉向系統卻不是那麼地徹底可控。駕駛起來得當心翼翼地檢查可能出現的空指針,處理檢查異常,重複生成冗長而單調的樣板代碼行等等。而編程語言的防危性(safety)和安全性(security)卻又是相當重要的。程序員
要是有一門語言,既能繼承Java的全部優勢特性及其背後強大完備的生態庫,又能更加簡單、安全可控,那真是再好不過了。github
咱們很高興地看到,Kotlin就是這樣一門語言。Kotlin是一門非研究性的語言,它是一門很是務實的工業級編程語言,它的使命就是幫助程序員們解決實際工程實踐中的問題。使用Kotlin 讓 Java程序員們的生活變得更好,Java中的那些空指針錯誤,浪費時間的冗長的樣板代碼,囉嗦的語法限制等等,在Kotlin中通通消失。Kotlin 簡單務實,語法簡潔而強大,安全且表達力強,極富生產力。算法
本章咱們先簡單介紹Kotlin語言的發展歷史和語言特性,而後簡述爲何要去學習Kotlin語言。最後,簡要介紹JVM語言家族。編程
首先,Kotlin是一種基於JVM的靜態類型編程語言。讓咱們從Hello World開始。與 C/C ++/Java 同樣,Kotlin 程序的入口點是一個名爲「main」的函數,它傳遞一個包含任何命令行參數的數組。windows
package com.easy.kotlin fun main(args: Array<String>) { println("Hello,World!") }
上面的代碼簡單說明以下:數組
1.Kotlin中的包package的使用跟Java基本相同。瀏覽器
2.Kotlin 變量聲明 args: Array<String> 相似於Pascal,先寫變量名args,冒號隔開,再在後面寫變量的類型Array<String> 。 安全
3.與Scala和Groovy同樣 ,代碼行末尾的分號是可選的。在大多數狀況下, 編譯器根據換行符就可以推斷語句已經結束。
4.Kotlin中使用fun關鍵字聲明函數(方法),充滿樂趣的fun。
人們爲何喜歡Kotlin?Kotlin爲何值得咱們去學習?下面是一個不徹底的清單列表:
Kotlin的優點是,既有Java的完整生態(Kotlin 徹底無縫使用各種Java API框架庫),又有現代語言的高級特性 (語法糖)。
Kotlin 語言的設計的初衷之一是爲了 JetBrains 團隊的內部使用,旨在幫助公司下降成本。用過IntelliJ IDEA的都知道JetBrains 團隊出品,皆是良品。毫無疑問,Kotlin的設計是務實的 。發展和促進 Kotlin 的好處大於其成本, 在這個過程當中, Kotlin 已經演變成了一個 JetBrains 的效率工具。其強烈的務實取向強烈地吸引了一大批Java程序員。
Kotlin 也成爲 JetBrains 工具生態系統中重要的一員。但願在將來幾年內 Kotlin 成爲主要的非 Java的 JVM語言,甚至有一天成爲下一個Java語言。能夠預測的是,Kotlin 將大大提高整個Java 互聯網開發者的效率和質量。
Kotlin語言的特性能夠簡單歸納以下:
1.實用主義( Pragmatic ):務實、注重工程實踐性。咱們常常會聽到或者看到人們說編程是數學,或者是工程,是藝術,是科學,這些說法都是頗有道理的。Kotlin是一門偏重工程實踐與藝術上的極簡風格的語言。
2.極簡主義( Minimalist ):語法簡潔優雅不囉嗦,類型系統中一切皆是引用(reference)。
3.空安全(Null Safety):有一個簡單完備的類型系統來支持空安全
4.多範式 (multi-paradigm ):同時一等支持 OOP 與 FP 編程範式。各類編程風格的組合可讓咱們更加直接地表達算法思想和解決問題的方案,能夠賦予咱們思考上更大的自由度和靈活性。
5.可擴展:直接擴展類的函數與屬性(extension functions & properties)。這與咱們在Java中常常寫的util類是徹底不同的體驗!Kotlin是一門很是注重用戶體驗的語言。
6.高階函數與閉包(higher-order functions & closures)。Kotlin 的類型中,函數類型(function type)也是一等類型( first class type),在Kotlin中咱們能夠把函數當成值進行傳遞。這直接賦予了 Kotlin 函數式編程的特性。
使用Kotin能夠寫出一些很是優雅的代碼。
7.支持快速實現 DSL。有了擴展函數、閉包等特性的支持,使用Kotlin實現一個DSL將會至關簡單方便。
「咱們認爲Kotlin的定位是一種現代化工業語言:它專一於代碼重用和可讀性的彈性抽象,以及面向早期錯誤偵測,和明確捕獲維護與清理的意圖,這些問題的靜態類型安全性。Kotlin最重要的使用場景之一是對於一個龐大的Java代碼庫,其開發者須要一個更棒的語言:你可以將Java和Kotlin自由混合,遷移能夠是漸進式的,不須要一會兒對整個代碼庫進行改變。」
「Kotlin旨在成爲一種面向工業的面嚮對象語言,並且是一種比Java更好的語言,但仍然能夠與Java代碼徹底互操做,容許企業逐步從Java遷移到Kotlin 。」
Andrey Breslav, Kotlin創始人
編程的真正的問題在於,如何把人類腦子裏對問題的解決方案「具化」到機器世界,而這個「具化」的過程正是編程語言所要表達的東西。如何富有表現力而且安全簡潔地表達,這是全部編程語言所要解決的問題。
Kotlin設計了一個「歸一化」的類型系統(一切類型皆是引用類型),純自然地設置了一道空指針的屏障,使得Kotlin比Java更加安全可靠。Kotlin還引入了類型推斷、一等支持函數式編程、Lambda、高階函數、類的擴展函數與屬性、DSL等諸多特性,使得咱們能夠編寫簡單、優雅且高效的代碼,更加專一地投入在業務邏輯的實現上。
優秀的程序員固然會選擇使用Kotlin這些更加先進的特性,由於它們毫無疑問有助於更直接地表達觀點,並且也沒有額外的開銷。何樂而不爲呢?
「工欲善其事必先利其器」。本節咱們簡單介紹一下學習Kotlin的工具平臺。
若是你想快速體驗一下Kotlin,只須要瀏覽器打開雲端IDE https://try.kotlinlang.org/
在這裏你能夠快速感覺到Kotlin語言到底長什麼樣子。可是,這裏不支持代碼智能提示以及自動補全等功能。
有時候咱們並不須要打開IDE來作一些事情。打開 IDE 是件很麻煩的事情,在某些場景下,咱們比較喜歡命令行。
使用命令行環境,咱們能夠方便地使用Kotlin REPL(Read-Eval-Print-Loop,交互式編程環境)。REPL能夠實時編寫Kotlin代碼,並查看運行結果。一般REPL交互方式能夠用於調試、測試以及試驗某種想法。
若是你想本地快速測試一個簡短的Kotlin代碼,可使用命令行REPL。Kotlin是運行在JVM環境下的語言。首先咱們要有JDK環境(Java環境配置此處省略)。
目前,Kotlin最新正式發佈的版本是1.1.50。首先,去下載Kotlin運行環境安裝包: https://github.com/JetBrains/...
解壓完kotlin-compiler-1.1.50.zip,放到相應的目錄下。而後配置系統環境變量:
export KOTLIN_HOME=/Users/jack/soft/kotlinc export PATH=$PATH:$KOTLIN_HOME/bin
執行source ~/.bashrc
, 命令行輸入kotlinc
, 便可進入 Kotlin REPL界面
$ kotlinc Welcome to Kotlin version 1.1.50 (JRE 1.8.0_40-b27) Type :help for help, :quit for quit >>> println("Hello,World!") Hello,World! >>> import java.util.Date >>> Date() Wed Jun 07 14:19:33 CST 2017
咱們若是想擁有學習Kotlin的相對較好的體驗,就不建議使用eclipse了。畢竟Kotlin是JetBrains家族的親兒子,跟Intelli IDEA是血濃於水啊。
咱們使用IDEA新建gradle項目,選擇Java,Kotlin(Java)框架支持,以下圖:
新建完項目,咱們寫一個HelloWorld.kt類
package com.easy.kotlin import java.util.Date import java.text.SimpleDateFormat fun main(args: Array<String>) { println("Hello, world!") println(SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())) }
直接運行HelloWorld.kt,輸出結果以下
Hello, world! 2017-05-29 01:15:30
如今的編程語言已經足夠多了,爲何咱們還須要更多的語言?Java已經如此流行普及足夠強大了,爲何咱們還須要Kotlin、Scala這樣的語言呢?
其實,若是咱們仔細想一想,這個問題自己的邏輯就不成立。你想一想,咱們能這樣說嗎——煎雞排已經足夠好吃了,爲何咱們還要去吃煎牛排呢?
從最先的機器語言(01機器碼,彙編語言)到高級語言(Lisp,Basic,Pascal,C,C++,Java,Haskell等),再到現代編程語言(Go,Swift,Scala,Kotlin等),編程語言百花齊放、百家爭鳴,其演化史可謂是蓬勃繁榮。
最先的編程語言就是01機器碼(Machine Code)。那個時候的程序員要會用0和1表示一切!
後來人們聰明地想到,是否是能夠把一些經常使用的指令操做單獨抽象出來,用特定的關鍵字來映射01機器碼序列?這就是彙編語言,這能夠算做是編程語言過程當中的第一次抽象封裝。
後來彙編用久了,人們也逐漸發現了使用匯編過程當中的問題:可移植性差。彙編代碼中是大量的字節指令碼,並且還必須一步一步地告訴計算機每一步要怎麼作,一個步驟出錯,執行結果就是程序員們意想不到的!調試程序也很困難。使用匯編語言編程,極易在子程序調用過程當中致使寄存器內容錯誤,而在高級語言中,全部參數都必須嚴格匹配。
高級語言就是爲了解決彙編語言的這些問題進行的更高一層的抽象與封裝。這層封裝就是編譯器。一般來講,設計一門語言相對容易,而實現這門語言的編譯器則是比較複雜的。編譯器制定了一系列的協議規範、語法規則等,只要程序員們按照這個協議規範來編程,編譯器就能夠將高級語言的源代碼翻譯成對應CPU指令集上的彙編語言代碼。高級語言不要求程序員掌握計算機的硬件運行,只要寫好上層代碼。著名的高級語言有 BASIC、FORTRAN(公式翻譯)、 COBOL(通用商業語言)、 C、 PASACL、ADA 語言等。
儘管 C 語言 (1972, Dennis MacAlistair Ritchie,啓發語言有 B語言、彙編、ALGOL68等)已經足夠普及且很是強大,後來仍是出現了針對 C 語言進行改進和功能擴展的新語言 C++ ( 1979,Bjarne Stroustrup ),C++ 集成了 C 語言的特性,而後加入了面向對象程序設計的特性支持。
而C/C++語言最大的一個問題就是「一切都會尖叫着中止」,由於它們使用了直接操縱內存的指針。一旦由於使用指針而出現了內存錯誤,系統核心就會崩潰。
有沒有一種語言能夠控制這樣的風險呢?
後來的Java(1995,James Gosling)繼承了 C/C++ 語言的優勢,摒棄了C++裏的指針操做、手動管理內存、多繼承等諸多複雜而並不實用功能特性,引入了劃時代的 JVM(Java Virtual Machine)。引用James Gosling的話就是
「大部分人大談特談JAVA語言,這對於我來講也許聽起來很奇怪,可是我沒法不去在乎。JVM纔是Java生態系統的核心啊。
我真正關心的是Java虛擬機的概念,由於是它把全部的東西都聯繫在了一塊兒;是它造就了Java語言;是它使得事物能在全部的異構平臺上獲得運行;也仍是它使得全部類型的語言可以共存。」
首先,JVM實現了Java的可移植性。
另外,JVM裏面實現了一個垃圾收集器(GC,Garbage Collector)來管理內存,GC 對保證系統的可靠性和安全性很是實用有益。
同時,JVM還奠基了一個龐大的語言生態的基礎。
Java是互聯網時代當之無愧的最流行的開發語言。通過20多年的積累和沉澱,Java生態擁有了不少優秀的開源社區,如Apache和Spring。有了這些框架,咱們能夠更加專一業務的實現。
Java語言也有很差的一面。咱們簡單列舉以下。
1.檢查異常(Checked Exceptions)。檢查異常會在編譯時強制執行try catch處理,同時還須要進行某種排序處理。 檢查異常是一個失敗的實踐,幾乎全部的主要API提供者都反對可檢查異常。Kotlin中摒棄了檢查異常。
2.基本類型和數組。Java的這個設計保留了字節碼的底層細節,違反了「凡事皆爲對象」原則。泛型沒法包容基本類型就是一個經典的例子。這也使得Java的類型系統顯得不是那麼地簡單統一。比較好的方案是,源代碼不用直接使用基本類型或者數組,編譯器(或者JVM)來決定是否能夠幫你對其進行優化。Kotlin正是這麼作的。
3.靜態變量(Static)。靜態方法常常會致使須要顯式的定義接口,從而使得API更加複雜。一個更好的辦法就是採用單例對象,單例對象在大多數狀況下表現都跟靜態對象差很少,只不過也能夠像一個對象同樣被傳遞而已。Kotlin中提供了 object 單例對象。
4.泛型。Java泛型自己就很複雜,當使用? exends和? super等變種句型時就變得尤爲複雜。很是容易搞錯。這個問題在《Effective Java》一書中提出了PECS(Producer extends Consumer super)的建議,Kotlin直接使用了這個方案。
5.空指針異常(NPE)。Java中咱們不得不寫一堆防護代碼來避免使人頭疼的NPE。Kotlin中引入了可空類型與安全調用符、Elvis操做符等特性實現空安全。咱們將在第3章中介紹。
6.一堆getter/setter單調冗長的樣板代碼。例以下面的Person Bean類
class PersonJava { Integer id; String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public PersonJava(Integer id, String name) { this.id = id; this.name = name; } }
在Kotlin中是這樣子的:
data class PersonKotlin(val id: Int, val name: String)
7.不容易傳遞函數。Java中沒有提供一等函數類型,函數式編程(FP)只能經過使用接口類型以及多態特性「曲線」來實現。Java會將每個算法(方法)都放入類中,這樣的限制會出現這樣的荒唐事:咱們只是想要實現一個函數算法,而這個時候咱們必須還得整出一個類出來放置這樣的方法;一樣,若是在其它地方要調用這個方法,咱們也必須經過建立該類來實現調用。在Kotlin中直截了當地提供了一等函數類型(First-Class Function Type)。跟普通類型同樣,函數類型能夠做爲值來傳遞,也能夠做爲返回值。
還有其它的經驗教訓,上面所述只是其中的一部分。
不能否認的是, C、 C++ 和 Java 都是很是優秀的編程語言。可是事物老是不斷髮展變化的。就像 C++ 是對 C 的繼承與發展,Java 是對 C++ 的繼承與改造,而Kotlin也是對Java 的繼承與變革。
這裏是一張來自Java官網文檔(http://docs.oracle.com/javase...)裏面的一張 Java 技術模塊架構圖
爲了在JVM上正確運行咱們的程序,咱們只須要可以按照規範生成正確的 class 文件,而後加載到JVM中執行文件中指定的操做字節指令碼(byte code)便可。
在過去20多年的發展歷程中(1991-2017,若是算上最初的稱之爲oak語言的Java前生的話),Java語言、JVM、API庫和框架、應用工具和Web服務器的速度、穩定性和功能方面卻一直在提高,如今已被公認爲是開發高端服務器。
JVM最初是爲了支持java編程語言。然而,隨着時間的流逝,愈來愈多的語言被改編或設計運行在JVM上。除了java語言,比較知名的JVM上的編程語言還有:Groovy、Scala、Clojure等。
JVM上主流編程語言歷史時間軸概覽:
計算機中的全部問題 , 均可以經過向上抽象封裝一層來解決。
Java虛擬機對各個平臺而言,實質上是各個平臺上的一個可執行程序。例如在windows平臺下,java虛擬機對於windows而言,就是一個java.exe進程而已。
一般狀況下,在JVM平臺上語言從源代碼編譯到JVM上執行的總體過程以下圖所示
其中,運行在JVM上的字節碼文件是不依賴於硬件和操做系統的二進制格式的文件。依賴硬件和操做系統的部分,由JVM分別在這些平臺上來實現。例如JDK 8
咱們常常說的Java語言是平臺無關的,跨平臺的。其實這是針對從Java/Scala/Kotlin/Groovy等的源代碼到JVM字節碼這一層是平臺無關的。
可是,真正到了把JVM字節碼經過解釋器映射到不一樣平臺(操做系統,CPU硬件架構)上,JVM就必須針對各個平臺實現一套解釋器。只是這一層經過抽象封裝,對 Java/Scala/Kotlin/Groovy 程序員而言已經徹底透明,無需再作相關的工做而已。
下一代廣泛可接受語言(next mass-appeal language)中,人的因素應該起到重要做用。在功能方面,應該具有諸如如下特性:
語言設計其實堪比藝術品設計,每一個人的口味跟審美都有各自的風格與特徵,因此實現出一門好的編程語言確實不容易。
人的生命只有一次。生命過短暫,因此不要去作一些重複無聊的事情。能交給計算機作的,就儘可能交給計算機去作。此乃人類進行計算機編程的濫觴之地。
將來人工智能將取代大部分的重複手工勞動。將大大解放人類的勞動力,從而使得人類可以花更多的時間和精力,去創造去創新。而人工智能的本質,就是對人類智能的抽象建模。咱們人類寫的操做系統、瀏覽器、辦公軟件、畫圖設計工具、3D建模軟件、電商系統、金融平臺、社交APP,不就是另外一種層次上的人工智能嗎?這些東西,背後都是01的映射。固然,01背後是物理層次的,量子微觀的世界了,更加奧妙無窮。
縱覽整個計算機的發展史,最重要的思想非「抽象」莫屬。
一層層的抽象封裝了實現的細節,計算機開疆擴土,南征北戰,發展到了今天蔚爲壯觀的互聯網,雲計算,大數據,機器智能的時代。
同時,也使得程序員寫代碼,從最初的拿着符號表在紙袋上打孔,到使用近似天然語言的高級編程語言來編程(固然背後少不了編譯器、解釋器,還有的是先經過虛擬機中間字節碼這一層,再經過解釋器映射到機器碼,最後在硬件上做高低電平的超高頻率的舞蹈),以及當今各類庫API、框架、集成開發工具集,智能化的編碼提示,代碼生成等等技術,使得咱們如今程序員,能更多的去關注問題自己以及邏輯的實現。
從只有少數技術人會用的命令行的Unix、DOS操做系統,到人性化的GUI圖形界面操做系統,再到移動互聯網時代的智能設備,計算機與互聯網愈來愈融入到人類生活的方方面面。
正如解決數學問題一般咱們會談「思想」,諸如反證法、化繁爲簡等,解決計算機問題也有不少很是出色的思想。思想之因此稱爲思想,是由於「思想」有拓展性與引導性,能夠解決一系列問題。
解決問題的複雜程度直接取決於抽象的種類及質量。過將結構、性質不一樣的底層實現進行封裝,向上提供統一的API接口,讓使用者以爲就是在使用一個統一的資源,或者讓使用者以爲本身在使用一個原本底層不直接提供、「虛擬」出來的資源。