本文是對<<Kotlin in Action>>
的學習筆記,若是須要運行相應的代碼能夠訪問在線環境 try.kotlinlang.org,這部分的思惟導圖爲: java
在Kotlin
中,函數的基本結構由四個部分構成:數組
函數的聲明以關鍵字 fun 開始,函數名稱 緊隨其後,接下來是括號括起來的 參數列表,參數列表的後面跟着 返回類型,返回類型和參數列表之間用冒號隔開,最後是函數體。函數
下面是一個比較大小的函數例子,上面談到的四個部分構成如圖中標註所示: 學習
在上面的例子中,if
是表達式,而不是語句,表達式和語句的區別在於:3d
在Java
中,全部的控制結構都是語句,而在Kotlin
中,除了for
、do
和do/while
之外大多數控制結構都是表達式。code
當函數體是由單個表達式構成時,能夠用這個表達式做爲完整的函數體,而且去掉花括號和return
語句,上面的例子就是這種狀況,所以能夠改寫爲: cdn
對於 表達式體函數,能夠省略返回類型,由於編譯器會分析做爲函數體的表達式,並把它的類型做爲函數的返回類型,這種分析稱爲 類型推導。可是對於有返回值的 代碼塊體函數,必須顯示地寫出返回類型和return
語句。對象
上面的例子能夠簡化爲: blog
在Kotlin
中,變量的聲明以關鍵字val/var
開始,而後是變量名稱,最後能夠加上類型(不加也能夠),這裏分爲兩種狀況:遞歸
Int
和Double
類型:
聲明變量的關鍵字有兩個:
使用val
聲明的變量不能在初始化以後再次賦值,它對應的是Java
的final
變量。 默認狀況下,應該儘量地使用val
關鍵字來聲明全部的Kotlin
變量。在定義了val
變量的代碼塊執行期間,val
變量只能進行惟一一次初始化,可是,若是編譯器能確保惟一一條初始化語句會被執行,能夠根據條件使用不一樣的值來初始化它。
這種變量的值能夠改變,可是它的類型倒是改變不了的。
Kotlin
能夠在字符串字面值中引用局部變量,只須要在變量名稱前面加上字符$
。
$
,須要對它進行轉義。
類的概念就是把數據和處理數據的代碼封裝成一個單一的實體,在Java
中,數據存儲在字段中,而且一般是私有的。若是想讓類的使用者訪問到數據得提供訪問方法,即getter/setter
。
在Java
中,字段和其訪問器的組合經常被叫做屬性。在Kotlin
中,屬性是頭等的語言特性,徹底 替代了字段和訪問器方法。在類中聲明一個屬性和聲明一個變量同樣:使用val/var
關鍵字,前者是隻讀的,然後者是可變的。
當聲明屬性的時候,就聲明瞭對應的訪問器(只讀屬性有一個gettter
,而可變屬性則有getter/setter
),例以下面的例子,聲明瞭只讀的name
屬性,可變的isMarried
屬性,其賦值和讀取的方法以下所示:
假設聲明一個矩形,它能判斷本身是不是正方形,那麼就不須要一個單獨的字段來存儲這個信息,此時咱們能夠寫一個自定義的訪問器:用val
開頭做爲聲明,緊跟着的是屬性的名稱和類型,接下來是get()
關鍵字,最後是一個函數體。
Kotlin
中包的概念和Java
相似,每一個kotlin
文件都能以一個package
語句開頭,而文件中定義的全部聲明(類、函數及屬性)都會被放到這個包中。import
關鍵字。kotlin
不區分導入的是類仍是函數,並且,它容許使用import
關鍵字導入任何種類的聲明,能夠直接導入頂層函數的名稱,也能夠在包名稱後加上.*
來導入特定包中定義的全部聲明。Java
中,要把類放到和包結構相匹配的文件與目錄結構中,而在kotlin
中,能夠把多個package
聲明不相同的類放在同一個文件夾中。聲明枚舉類時,enum
是一個所謂的軟關鍵字,只有當它出如今class
前面時纔有特殊的意義,在其餘地方能夠當作普通名稱使用。而class
仍然是一個關鍵字,下面是一個枚舉類的聲明:
如下是一個帶屬性的枚舉類:
when
是一個有返回值的表達式,所以,做爲表達式函數體,它能夠去掉花括號和return
語句,並省略返回類型的聲明。
下面是一個經過when
處理枚舉類的例子,它和Java
中的switch
語句相似,根據when
中Color
的值走到對應的分支,除此以外,咱們能夠把多個值用逗號間隔,合併到同一個分支:
在Java
中,和when
相似的switch
語句要求必須使用常量(枚舉常量、字符串或者數字字面值)做爲 分支條件,而when
容許使用任何對象,咱們使用一個函數來混合兩種顏色。下面例子中用到的setOf
是由Kotlin
標準函數庫提供的,它能夠建立出一個Set
,而且會包含全部指定爲函數實參的對象,只要兩個set
中包含同樣的條目,它們就是相等的,集合的條目順序並不重要。
when
表達式提供參數,這樣分支條件就是任意的布爾表達時,這種寫法的優勢是不會建立額外的對象,但代價是它更難理解。
在kotlin
中,判斷一個變量是不是某種類型須要使用is
關鍵字,它和Java
當中的instanceOf
類似。
Java
中,在檢查完後還須要顯示地加上類型轉換。kotlin
中,若是你檢查過一個變量是某種類型,後面就不須要再轉換它,能夠把它當作你檢查過的類型來使用。咱們用下面這個例子,Num
和Sum
都實現了Expr
接口,經過is
判斷它的類型,完成遞歸求和。能夠看到,在is
判斷以後,再也不須要轉換成Num
或Sum
,就能夠直接訪問該類的成員變量。
智能轉換 只在變量通過is
檢查且以後再也不發生變化 的狀況下有效,當你對一個類的屬性進行智能轉換的時候,這個屬性必須是一個val
屬性,並且不能有自定義的訪問器,不然,每次對屬性的訪問是否都能返回一樣的值將無從驗證。
if
和when
均可以使用代碼塊做爲分支體,這種狀況下,代碼塊中的最後一個表達式就是結果,這個規則在全部使用代碼塊並指望獲得一個結果的地方成立。一樣的規則對try
主體和catch
子句也有效。
kotlin
和Java
同樣,有while
循環和do-while
循環,它們的語法和Java
中相應的循環徹底一致。
在Java
當中,對於循環的處理方式爲:先初始化變量,在循環的每一步更新它的值,並在值知足某個限制條件時退出循環。
而在Kotlin
中,爲了替代常見的循環用法,使用了 區間 的概念,其本質上就是兩個值之間的間隔,這兩個值一般是數字:一個起始值,一個結束值。使用..
運算符來表示區間,而結束值始終是區間的一部分。
downTo
、
step
和
until
等用於區間的語法,用於進行循環操做,例以下面的例子
downTo
用於遞減到指定的值,而
step
則指定步長:
until
則可使迭代不包含指定的結束值,例以下面這樣:
這裏咱們用到了TreeMap
,在更新map
時,咱們能夠像使用數組同樣,只不過下標變成了key
值:
下面的例子展現了for
容許容許展開迭代中的集合的元素,把展開的結果存儲到了兩個獨立的變量中:letter
是鍵、binary
是值:
使用in
運算符來檢查一個值是否在區間中,或者它的逆運算!in
來檢查這個值是否不在區間中,區間不只限於字符,假若有一個支持實例比較操做的任意類(實現了java.lang.Comparable
接口),就能建立這種類型的對象的區間。
kotlin
的異常處理和Java
以及其餘許多語言的處理方式相似:一個函數能夠正常結束,也能夠在出現錯誤的狀況下拋出異常。方法的調用者能捕獲到這個異常並處理它;若是沒有處理,異常會沿着調用棧再次拋出。
throw
關鍵字,可是沒必要使用new
關鍵字來建立異常實例。throw
結構是一個表達式,能做爲另外一個表達式的一部分使用。當使用帶有catch
和finally
子句的try
結構來處理異常時,下面是一個典型的結構:
Java
最大區別就是throws
子句沒有出如今代碼中:若是使用Java
來寫這個函數,你會顯示地在函數聲明上面寫上throws IOException
。這是由於IOException
是一個受檢異常,在Java
中,這種異常必須顯示地處理,必須聲明你的函數能拋出全部的受檢異常。
kotlin
不區分受檢異常和未受檢異常,沒必要指定函數拋出的異常,並且能夠處理也能夠不處理異常。BufferReader.close
可能拋出須要處理的受檢異常,若是關閉失敗,大多數程序不會採起什麼有意義的行動,因此捕獲來自close
方法的異常所需的代碼是多餘的。kotlin
中的try
關鍵字就像if
和when
同樣,引入了一個表達式,能夠把它的值賦給一個變量,而且須要用花括號把語句主體括起來。若是主體包含多個表達式,那麼整個try
表達式的值就是最後一個表達式的值。