日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《Kotlin实战》读书笔记第二章

發(fā)布時間:2024/3/7 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Kotlin实战》读书笔记第二章 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Kotlin基礎

1.基本要素:函數(shù)和變量

函數(shù)

語句和表達式:

在Kotlin中,if是表達式而不是語句。

  • 表達式:有值,能作為另一個表達式的一部分使用
  • 語句:無值,總是包圍著它的代碼塊中的頂層元素

在Java中,所有控制結構都是語句。
在Kotlin中,除了循環(huán)以外的大多數(shù)控制結構都是表達式。
在Java中,賦值是表達式,在Kotlin中則是語句。這有助于避免比較和賦值之間的混淆。

表達式函數(shù)體:

函數(shù)體由單個表達式構成的函數(shù)。

用表達式作為完整的函數(shù)體,并去掉花括號和return語句。

fun max(a: Int,b: Int) = if(a > b) a else b

變量

聲明變量關鍵字由兩個:

  • val:不可變引用,來自value。不能在初始化之后再次賦值,對應final變量
  • var:可變引用,來自variable。對應普通變量

默認情況下盡可能使用val關鍵字來聲明變量。

使用不可變引用,不可變對象,無副作用的函數(shù)讓你的代碼更接近函數(shù)式編程風格。

字符串模板

val name = "world" println("hello,$name")

和許多腳本語言一樣,Kotlin可以在字符串字面值中引用局部變量,在變量前加上$即可。

這等價于Java中的字符串連接,編譯后的代碼創(chuàng)建了一個StringBuilder對象,并把常量和變量附加上去。

對象表達式和聲明的區(qū)別

他倆之間只有一個特別重要的區(qū)別:

  • 對象表達式在我們使用的地方立即初始化并執(zhí)行的

  • 對象聲明是懶加載的,是在我們第一次訪問時初始化的。

2.類和屬性

屬性

值對象:只有數(shù)據(jù)沒有其他代碼的類。

在Java中,字段和其訪問器的組合被叫做屬性

在Kotlin中,屬性是頭等的語言特性,在類中聲明一個屬性和聲明一個變量一樣:使用val和var關鍵字。

自定義訪問器

class Rectangle(val h: Int, val w: Int){val isSquare: Booleanget(){return h == w} }

屬性isSquare不需要字段來保存其值,它的值是每次訪問屬性的時候被計算出來的。

也可以寫成表達式體get() = h == w

Kotlin源碼布局:目錄和包

Java把所有類組織成包,Kotlin也有類似的概念。

Kotlin不區(qū)分導入的是類還是函數(shù),允許使用import關鍵字導入任何種類的聲明??梢灾苯訉腠攲雍瘮?shù)的名稱。

在Java中,要把類放到和包結構相匹配的文件與目錄結構中。

在Kotlin中則不需要,可以把多個類放在同一個文件中,文件的名字還可以隨意選擇。也沒有對磁盤上源文件的布局強加任何限制。包的層級結構不需要遵循目錄的層級結構。

3.表示處理和選擇:枚舉和“when”

聲明枚舉類

枚舉并不是值的列表,可以給枚舉類聲明屬性和方法。

enum class Color(val r: Int, val g: Int, val b: Int ) {RED(255, 0, 0), ORANGE(255, 165, 0),YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),INDIGO(75, 0, 130), VIOLET(238, 130, 238);fun rgb() = (r * 256 + g) * 256 + b }fun main(args: Array<String>) {println(Color.BLUE.rgb()) }

當你聲明了枚舉類的屬性,那么聲明枚舉常量的時候,必須提供此枚舉常量的屬性值。

**Kotlin中唯一必須使用分號的地方:**在枚舉類中,定義方法之前,用分號把常量和方法隔開。

使用“when”處理枚舉類

Java中switch語句,在Kotlin中對應的結構是when。

when是一個有返回值的表達式,因此可以直接寫一個返回when表達式的表達式體函數(shù)。

enum class Color {RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET }fun getMnemonic(color: Color) =when (color) {Color.RED -> "Richard"Color.ORANGE -> "Of"Color.YELLOW -> "York"Color.GREEN -> "Gave"Color.BLUE -> "Battle"Color.INDIGO -> "In"Color.VIOLET -> "Vain"}fun getWarmth(color: Color) = when(color) {Color.RED, Color.ORANGE, Color.YELLOW -> "warm"Color.GREEN -> "neutral"Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold" }fun main(args: Array<String>) {println(getMnemonic(Color.BLUE)) }

和Java不一樣你不需要寫break語句,并且可以把多個值合并到同一個分支。

在“when”結構中使用任意對象

when允許使用任何對象作為分支條件。

fun mix(c1: Color, c2: Color) =when (setOf(c1, c2)) {setOf(RED, YELLOW) -> ORANGEsetOf(YELLOW, BLUE) -> GREENsetOf(BLUE, VIOLET) -> INDIGOelse -> throw Exception("Dirty color")}fun main(args: Array<String>) {println(mix(BLUE, YELLOW)) }

使用不帶參數(shù)的“when”

上面一個例子中的代碼效率有點低,因為每次調用它都會創(chuàng)建一些Set實例。

可以換一種方式重寫:

fun mixOptimized(c1: Color, c2: Color) =when {(c1 == RED && c2 == YELLOW) ||(c1 == YELLOW && c2 == RED) ->ORANGE(c1 == YELLOW && c2 == BLUE) ||(c1 == BLUE && c2 == YELLOW) ->GREEN(c1 == BLUE && c2 == VIOLET) ||(c1 == VIOLET && c2 == BLUE) ->INDIGOelse -> throw Exception("Dirty color")}

若沒有給when表達式提供參數(shù),則分支條件就是任意的布爾表達式。

智能轉換:合并類型檢查和轉換

接下來用一個函數(shù)做例子,此函數(shù)要求完成 (1+2)+4 的算術表達式的求值。

interface Expr class Num(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Exprfun eval(e: Expr): Int {if (e is Num) {val n = e as Numreturn n.value}if (e is Sum) {return eval(e.right) + eval(e.left)}throw IllegalArgumentException("Unknown expression") }fun main(args: Array<String>) {println(eval(Sum(Sum(Num(1), Num(2)), Num(4)))) }

上面的代碼展示了一種簡單的類結構來表達這種表達式編碼方式:Expr接口和其實現(xiàn)類Num和Sum

注意Expr接口沒有聲明任何方法,他只是一個標記接口,用來給不同種類的表達式提供一個公共的類型。

在Kotlin中,使用 is 檢查來判斷一個變量是否為某種類型。

is 檢查和Java中的 instanceOf 相似。但是Kotlin中若你檢查過某變量的類型,后面再使用它就不需要轉換了。

編譯器為你執(zhí)行了類型轉換,這種行為稱為智能轉換。

智能轉換只在變量經過is檢查且之后不再發(fā)生變化的情況下有效。當你對一個類的屬性進行智能轉換的時候,這個屬性必須是val屬性,且不能有自定義的訪問器。否則每次對屬性的訪問是否都能返回同樣的值將無從驗證。

使用as關鍵字來表示到特定類型的顯示轉換。

重構:用“when”代替“if”

Kotlin沒有三元運算符,因為if表達式有返回值。

這意味著可以用表達式體語法重寫eval函數(shù)。

fun eval(e: Expr): Int =if (e is Num) {e.value} else if (e is Sum) {eval(e.right) + eval(e.left)} else {throw IllegalArgumentException("Unknown expression")}

若if分支只有一個表達式,花括號可以省略。

若if分支是代碼塊,代碼塊中最后一個表達式會被作為結果返回。

接下來使用when來重寫:

fun eval(e: Expr): Int =when (e) {is Num ->e.valueis Sum ->eval(e.right) + eval(e.left)else ->throw IllegalArgumentException("Unknown expression")}

when表達式并不僅限于檢查值是否相等,它還允許你檢查實參值的類型。

代碼塊作為“if”和“when”的分支

分支體是代碼塊,代碼塊中最后一個表達式會被作為結果返回。

fun evalWithLogging(e: Expr): Int =when (e) {is Num -> {println("num: ${e.value}")e.value}is Sum -> {val left = evalWithLogging(e.left)val right = evalWithLogging(e.right)println("sum: $left + $right")left + right}else -> throw IllegalArgumentException("Unknown expression")}

規(guī)則:代碼塊中最后的表達式就是結果

此規(guī)則對try主體和catch子句也有效。

此規(guī)則對常規(guī)函數(shù)不成立。一個常規(guī)函數(shù)要么具有不是代碼塊的表達式函數(shù)體,要么具有包含顯示return語句的代碼塊函數(shù)體。

4.迭代事物:“while”循環(huán)和“for”循環(huán)

while循環(huán)和Java中的沒有區(qū)別。

for循環(huán)和Java的for-each循環(huán)一致,其寫法和for<item> in <elements> 和C#一樣。

迭代數(shù)字:區(qū)間和數(shù)列

區(qū)間:兩個值之間的間隔,使用..來表示區(qū)間。

val oneToTen = 1..10

Kotlin的區(qū)間是閉合的,結束值是區(qū)間的一部分。

若你能迭代區(qū)間中所有的值,這樣的區(qū)間被稱作數(shù)列。

fun fizzBuzz(i: Int) = when {i % 15 == 0 -> "FizzBuzz "i % 3 == 0 -> "Fizz "i % 5 == 0 -> "Buzz "else -> "$i " }fun main(args: Array<String>) {for (i in 100 downTo 1 step 2) {print(fizzBuzz(i))} }

上述代碼迭代了一個步長為2的遞減數(shù)列。

迭代map

下面的程序將字符轉換成二進制打印出來:

fun main(args: Array<String>) {val binaryReps = TreeMap<Char, String>()for (c in 'A'..'F') {val binary = Integer.toBinaryString(c.toInt())binaryReps[c] = binary}for ((letter, binary) in binaryReps) {println("$letter = $binary")} }

..也可以創(chuàng)建字符區(qū)間。這里從A迭代到F,包括F。

for循環(huán)允許展開迭代中的集合的元素,并把展開的結果存儲到了兩個獨立變量letter和binary中。

可以用這樣的展開語法在迭代集合的同時跟蹤當前項的下標。

下面的代碼遍歷的list并打印出下標:

val list = arrayListOf("10", "11", "1101")for ((index, element) in list.withIndex()) {println("$index : $element")}

使用“in”檢查集合和區(qū)間的成員

使用in運算符來檢查一個值是否在區(qū)間中,或者其逆運算,!n,檢查不在區(qū)間中。

下面的代碼檢查一個char是數(shù)字還是字母:

fun recognize(c: Char) = when (c) {in '0'..'9' -> "It's a digit!"in 'a'..'z', in 'A'..'Z' -> "It's a letter!"else -> "I don't know…?" }fun main(args: Array<String>) {println(recognize('8')) }

區(qū)間不限于數(shù)字和字符,只要支持實例比較操作(實現(xiàn)了java.lang.Comparable接口),就能創(chuàng)建這一種類型的對象區(qū)間。

如果是這樣的區(qū)間,并不能列舉出這個區(qū)間中的所有對象。

比如我們不能列舉出“Java”和“Kotlin”之間所有的字符串。

但是我們任然可以用in運算符檢查一個對象是否屬于這個區(qū)間。

5.Kotlin中的異常

Kotlin的異常處理大體上和Java一致。Kotlin中的throw結構是一個表達式,能作為另一個表達式的一部分使用。

“tyr”“catch”和“finally”

下面的代碼從給定文件中讀取一行,解析成數(shù)字并返回值;若不是有效數(shù)字則返回null。

fun readNumber(reader: BufferedReader): Int? {try {val line = reader.readLine()return Integer.parseInt(line)}catch (e: NumberFormatException) {return null}finally {reader.close()} }fun main(args: Array<String>) {val reader = BufferedReader(StringReader("239"))println(readNumber(reader)) }

和Java最大的區(qū)別是throws子句沒有出現(xiàn)在代碼中。

和其他許多現(xiàn)代JVM語言一樣,Kotlin并不區(qū)分受檢異常和未受檢異常。不用指定函數(shù)拋出的異常,可以處理也可以不處理異常。

“try”作為表達式

修改上面的例子如下:

fun readNumber(reader: BufferedReader) {val number = try {Integer.parseInt(reader.readLine())} catch (e: NumberFormatException) {return}println(number) }fun main(args: Array<String>) {val reader = BufferedReader(StringReader("not a number"))readNumber(reader) }

try關鍵字引入了一個表達式,可以把它的值賦給一個變量。

return語句放在catch代碼塊中,因此該函數(shù)的執(zhí)行在catch代碼塊之后不會再繼續(xù)。

如果你需要返回值,可以將return替換為null,最后會打印出null

6.小結

  • fun關鍵字用來聲明函數(shù),val和var分別聲明只讀變量和可變變量
  • 字符串模板:在變量前加上$或者用${}包圍一個表達式,來把值注入字符串
  • if,when,try catch都是帶返回值的表達式
  • 檢查變量類型之后不必再顯示的轉換,編譯器用智能轉換自動幫你完成
  • ..會創(chuàng)建一個區(qū)間,還可以使用in和!n運算符來檢查值是否屬于區(qū)間
  • Kotlin不要求你聲明函數(shù)可以拋出的異常

總結

以上是生活随笔為你收集整理的《Kotlin实战》读书笔记第二章的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。