天天看點

Kotlin學習筆記五、控制語句

一、條件分支

a、簡單分支

最簡單的條件分支莫過于if…else…

var mod = System.currentTimeMillis() % 3
if (mod == 0L){
	println("if...else...語句下時間節點剛好是可以被2整除的偶數:$mod")
}else if (mod == 1L){
	println("if...else...語句下嗯,這是個技術:$mod")
}else{
	println("if...else...語句下*****也是一個技術和體力兼備的活兒,你以為就是簡單的活塞運動?")
}
           

b、多路分支

kotlin的多路分支其實就是Java裡面的switch分支的變種,不過kotlin不再使用switch了,相比Java有許多變化:

  1. 使用when()語句來代替switch().
  2. “case常量值:”則被新的語句“常量值->”所代替。
  3. 然後他沒有break結束語,kotlin的機制是預設處理完一個分支就直接跳出多路分支語句。
  4. default關鍵字被else所代替,而且也是必不可缺的。
    var mod = System.currentTimeMillis() % 3
    when (mod){
    	0L -> println("when語句下時間節點剛好是可以被2整除的偶數:$mod")
    	1L ->  println("when語句下嗯,這是個技術:$mod")
    	else -> println("when語句下****也是一個技術和體力兼備的活兒,你以為就是簡單的活塞運動?")
    }
               

我們在Java的switch語句中,經常會出現這樣的情況:多個case條件下的處理邏輯是一樣的,但是這時候有多少個這樣的條件,我們就需要寫多少行case語句,然後省去break,這樣看着别扭。在kotlin裡面,則完全不需要這樣麻煩,我們可以将這樣的多個條件并排的寫在一行,之間用”,”隔開即可。如果這幾個條件值剛好又是連續的數字,則我們可以用關鍵字”in 開始值…結束值”指定區間範圍。另外,若條件不在某個連續的區間範圍内,我們可以用關鍵字”!in 開始值…結束值” 指定區間範圍。

var inin = (System.currentTimeMillis() % 9).toInt()
when(inin){
	0,1,8,9 -> println("when多條件下,時間多個相同邏輯的條件:$inin")
	in 2..5 -> println("when多條件下,嗯,這是個技術:$mod")
	!in 6..8 -> println("when多條件下,****也是一個技術和體力兼備的活兒,不是簡單的活塞運動:$mod")
	else -> println("多條件下的這個lese狀态下懶得找什麼語句了,湊合吧")
}
           

這裡要注意的是:

開始值.結束值之間的小數點是兩個,不是三個,這點要切記

開始值.結束值之間的小數點是兩個,不是三個,這點要切記

開始值.結束值之間的小數點是兩個,不是三個,這點要切記

重要的事情說三遍。

c、類型判斷

就是Java裡面的變量屬于那種資料類型的判斷。Java中用到的關鍵字是instanceof,而kotlin裡面用到的關鍵字則是is。而且,when()語句判斷也可廣泛用于類型判斷,二者結合,相當奇妙:

var mod = (System.currentTimeMillis() % 3).toInt()
var type = when(mod){
	0 -> mod.toFloat()
	1 -> mod.toDouble()
	else -> mod.toLong()
}
when(type) {
	is Float -> println("Float詩鬼李賀")
	is Double -> println("Double詩仙李白")
	is Long -> println("Long詩聖杜甫")
}
           

二、循環

a、循環

kotlin的循環主要是for循環和while循環兩種,但是for循環有些變化,不再是for(初始值;結束條件;變量變化),而是for(item in …)。比如:

var ancientPoetry:MutableList<String> = mutableListOf(
"天下風雲出我輩", "一入江湖歲月催", "皇圖霸業談笑中", "不勝人生一場醉",
"提劍跨騎揮鬼雨", "白骨如山鳥驚飛", "塵事如潮人如水", "隻歎江湖幾人回",
"英雄路遠掌聲近", "莫問蒼生問星辰", "天地有涯風有信", "大海無量不見人")
var Poetry = ""
           

for循環實作

for (index in ancientPoetry.indices){
	if ((index + 1) %2 == 0){
	    Poetry = "$Poetry${ancientPoetry.get(index)}。\n"
	}else{
	    Poetry = "$Poetry${ancientPoetry.get(index)}, "
	}
}
logging(Poetry)
           

while循環實作

var poetryWhile = "";
var index = 0;
while (index < ancientPoetry.size){
	if ((index + 1) % 2 == 0){
	    poetryWhile = "$poetryWhile${ancientPoetry.get(index)}。\n"
	}else{
	    poetryWhile = "$poetryWhile${ancientPoetry.get(index)}, "
	}
	index++
}
logging(poetryWhile)
           

do…while循環實作:

fun mPoetry(){
    var ancientPoetry:MutableList<String> = mutableListOf(
            "天下風雲出我輩", "一入江湖歲月催", "皇圖霸業談笑中", "不勝人生一場醉",
            "提劍跨騎揮鬼雨", "白骨如山鳥驚飛", "塵事如潮人如水", "隻歎江湖幾人回",
            "英雄路遠掌聲近", "莫問蒼生問星辰", "天地有涯風有信", "大海無量不見人")
    var Poetry = ""
    var index = 0
    var size = ancientPoetry.size - 1
    do {
        if ((index + 1) %2 == 0){
            Poetry = "$Poetry${ancientPoetry.get(index)}。\n"
        }else{
            Poetry = "$Poetry${ancientPoetry.get(index)}, "
        }
        index++
    }while (index <= size)
    	println(Poetry)
}
           

b、跳出多重循環

當循環中,滿足了我們的指定條件或者避免某種異常出現,我們需要在某種情況下跳出循環或者終止循環。

同樣的,kotlin裡面,對于單層循環,跳出目前循環用的也是continue這個關鍵字。終止循環用beak這個關鍵字。

對于多重循環,也可以像Java那樣,通過設立标記位來跳出循環或者終止循環。但是kotlin比你想象的要強大。他采取了新的手段,來跳出或者終止多重循環——outside關鍵字:

var position = 0
[email protected] while (position < ancientPoetry.size){
	if (ancientPoetry.get(position).isNullOrBlank()){
	    continue
	}
	var item = ancientPoetry.get(position)
	var local = 0;
	while (local < item.length){
	    var str:String = item[local].toString()
	    if ("回".equals(str)){
			logging(str + "--------------------")
			[email protected]
	    }
	    local++
	}
	position++
}
           

注意上面雙層while循環中outside關鍵字出現的次數和位置。

三、空安全

a、字元串的空判斷

開發中讓我們最抓狂的莫過于各種防不勝防的異常處理,包括空指針異常NullPointException、數組越界異常IndexOutOfBoundsException、資料類型轉換異常ClassCastException/ NumberFormatException等等。特别是空指針異常NullPointException讓人焦頭爛額,kotlin中常用的校驗字元串為空的有以下幾個方法:

1、isNullOrempty():為空指針、字元串長度為0時傳回true,非空串與可空串均可調用;

2、isNullOrBlank():為空指針,字元串長度為0,全部為空格時傳回true,非空串與可空串均可調用;

3、isEmpty():字元串長度為0,隻有非空串可調用;

4、isNotEmpty():字元串長度大于0時傳回true,隻有非空串可以調用;

5、isBlank():字元串長度為0、全部為空格時傳回true,隻有非空串可調用;

6、isNotBlank():字元串長度大于0且不是全空格串時傳回true,隻有非空串可調用;

b、聲明可空變量

聲明一個可空變量就相當于Java裡面建立一個對象,但是不通過關鍵字new去完成初始化:

StringBuffer sb;
或者
StringBuffer sb = null;
           

這樣單純的聲明變量但是沒有完成初始化直接使用,那麼就很容易引發NullPointException空指針異常。在kotlin裡面,則可以避免這種情況出現——聲明一個可空變量:

var strCanNull:String?
           

就這樣,就完成了一個可空字元串變量的聲明。舉例說明:

var str01:String = "我是有值的"
var str02:String? = null
var str03:String? = "可空的字元串"
var length01 = str01.length

// 帶“?”方式聲明的的變量,使用的時候需要注意在該變量後面帶上“? ”辨別,否則開發環境會爆紅,無法通過IDE編譯
var length02 = str02?.length
var length03 = str03?.length
logging("str01字元串的長度:$length01, str02字元串的長度:$length02,str03字元串的長度:$length03")
logging("空字元串用于比較:${str02.equals("22")}")
logging("空字元串用于字元串拼接:${str02 + "我的曉曉"}")

// 空字元串用于截取操作str02.substring(0,2)的時候,開發環境會爆紅,提示你進行非空判斷。
if (str02 != null) {
	logging("空字元串用于截取:${str02.substring(0,2)}")
}

//因為str01定義的時候就已經确定了他不會是空的,是以使用的時候不用判斷,也不用加?辨別符
logging("空字元串用于截取:${str01.substring(0,2)}")

str01 = null.toString()

// 經過下面的這幾輪測試,我們發現,str01經null.toString()操作後,str01實際上是一個"null"這樣的字元串,
// 而且kotlin裡面,經過非空指派操作後,字元串型變量就不再允許進行null的指派,比如如下操作都是不允許的: 
str01=null/str01:String? = null。

//但可以進行str01=""操作,然後引發未知異常,這一點需要特别注意
logging("str01變為null.toString的結果是啥:$str01")
logging("str01變為null.toString後是個空字元串還是空對象str01==null:${str01==null}")
logging("str01變為null.toString後是個空字元串str01==\"null\":${str01=="null"}")
logging("str01變為null.toString後是個空字元串str01.equals(\"null\"):${str01.equals("null")}")

//雖然不可以進行null的指派操作,但是可以進行""的指派操作,然後引發未知異常,這一點需要特别注意。
str01 = ""
try {
	logging("str01字元串進行截取操作:${str01.substring(0,1)}")
}catch (e:Exception){
	logging("對str01=\"\"字元串進行截取操作抛出異常")
	e.printStackTrace()		
}
           

總結,kotlin引入了空安全的概念,并在編譯的實話開始對變量是否為空的校驗,相關的操作符說明如下:

1、聲明變量執行個體時,在類名稱後面加?,表示該變量可以為空;

2、調用變量方法時,在變量名稱後面加?,表示一旦變量為空就傳回null;

3、新引入運算符“?:”,表示一旦變量為空,就傳回該運算符右邊的表達式,類似Java的三目運算,條件為false的時候,就執行”:”右邊的表達式;

4、引入新運算符“!!”,通知編譯器不做非空校驗。如果運作時發現變量為空,就抛出異常。

四、等式判斷(字元串相等判斷)

簡單來說就是判斷兩個變量的值是否相同或者相等,基本資料類型為相等,引用資料類型為相同。在C語言裡面,判斷是否相等,用的是“= =”運算符,判斷是否相同用的是“strcmp”運算符,C++、Java裡面判斷是否相等,用的也是“==”運算符,判斷是否相同用的是“equels”運算符,但是equels運算符的内部實作其實跟strcmp是一回事,屬于換湯不換藥的性質。

Kotlin在總結前面語言的一些弊病之後,決心割除這些沿襲已久的積弊,反正都把字元串當做基本資料類型那樣,何不直接統一相關的比較運算操作符呢。是以既然基本資料類型直接的比較實用“= =”,那麼字元串也用“= =”來判斷,相等用“==”,不等用“!=”.

Kotlin學習筆記五、控制語句
var str01 = "asdfgh"
var str02 = "asdfgh"
var str03 = "asdfghjkl"
logging("str01和str02相等嗎:${str01==str02}") //相等
logging("str01和str02不相等嗎:${str01!=str02}") //相等
logging("str01和str03相等嗎:${str01==str03}") //不等
           

五、引用相等(比如對象)

判斷是否相等,有時候僅僅判斷兩個變量值是否相等還不足以完成某種一緻性的判斷。要完成這種一緻性的判斷需要另外一種由内而外全部先更的判斷準則,該準則叫做引用相等,意思是除了值相等以外,還要求引用的記憶體位址也必須相等。

Kotlin裡面,結構相等的運算符用的是雙等号“= =”;相應的,引用相等用的便是三個等号"= = =",不相等則是“!= =”。

關于幾個“=”操作符的含義,可以這樣了解:

“=”:指派運算;

“= =”:等于運算或者比較運算,比較的是對象内部的值,而不是對象本身。重在“結構相等”。

“= = =”:完全等于運算,不僅僅要比較值(結構相等),還要比較對象本身(引用相等),隻有二者同時相等,才算是相等,才傳回true。

下面列舉幾個常見的等是判斷情景:

1、對于基本資料類型,包括整型、浮點型、單精度、雙精度、布爾值、長整型、字元串,結構相等和引用相等沒有差別。

2、同一個類聲明的不同變量,隻要有一個屬性不相等,那麼既是結構不相等,也是引用不相等。

3、同一個類聲明的不同變量,若是equals方法校驗的每隔屬性都相等,則其結構相等,但是引用不等

4、總的來說,可以這樣了解:結構是否相等判斷偏重于其内容,引用相等判斷偏重于其記憶體位址。

logging("結構相等判斷:str01和str02相等嗎:${str01===str02}")//相等
var date:Date = Date()
var dateClone = date.clone()
logging("結構相等判斷:date==dateClone嗎:${date==dateClone}")//相等
logging("引用相等判斷:date===dateClone嗎:${date===dateClone}")//不等
           

六、is操作符和in操作符:

A、運算符is和!is

主要用于判斷變量是否屬于某種類型,作用跟Java裡面的instanceof作用相同,但相比Java關鍵字,kotlin的關鍵字及寫法更簡潔。

Kotlin學習筆記五、控制語句

var listString:List = listOf(“華為”, “小米”, “Apple”, “ViVo”, “OPPO”)

var item = “華為”

logging(“通過is關鍵字能夠判斷item這個變量是不是String類型的變量:${item is String}”)

B、運算符 in和!in

Kotlin語言裡面的in運算符主要用于判斷數組、隊列、集合、映射等裡面是否包含某個元素。如果我們是在Java裡面判斷數組或者集合裡面是否包含某個元素,隻能通過循環的方式拿到每一個item,然後和目标元素對比。這樣太耗費資源和時間了。但這在kotlin裡面就是一行代碼一個關鍵字的事兒:

logging("通過in關鍵字能夠判斷一個list裡面是否包含某個元素\"${item}\"麼:${item in listString}")
           

注意最後的{}大括号裡面的代碼:item in listString,它是關鍵。

可以這麼了解:

Kotlin裡面的關鍵字“in”作用跟Java裡面的“contains()”方法作用是一樣的,都是判斷某個對象是否包含另外一個對象,
或者一個對象是否在另一個對象裡面。
           

舉例:

var strArray:Array<String> = arrayOf("東邪",  "西毒",  "南帝",  "北丐")	
if (3 in strArray:Array){
    println(strArray:Array.contentToString())
}

String x3 = "goeasyway";
if (x3.contains("way")){
    System.out.println("x3包含字元串“way”");
}