Kotlin 常見符號大全

KOTLIN

【?,!!,?:,:: ,->,$,_(下劃線),@,as,..,{},,,】

1. 【?】

" ?" 修飾在成員變量的類型后面,表示這個變量可以為null,系統(tǒng)在任何情況下不會報它的空指針異常。
" ? " 修改在對象后面代表該對象如果為null則不處理后面邏輯
如果我們定義的變量是一個可以為空的類型,則要用【String?】

//在變量類型后面加上問號,代表該變量是可空變量  
var name: String? = "eryang"  //(PS:var和val關鍵字代表的意義會在另一篇幅中去著重講)
name= null // 編譯正確

var name: String = "eryang"
name= null // 編譯錯誤

val len = name.length // 錯誤:變量“b”可能為空
val len = name?.length //如果 name非空,就返回 name.length ,否則返回 null,這個表達式的類型是 Int? 。
?.

let函數(shù)和?.同時使用來處理可空表達式

person?.let{ 
      //內(nèi)部的it一定是非空的
 }
//如果person為空就不會調(diào)用let函數(shù)
//如果person不為空才會調(diào)用let函數(shù),所以?.和let函數(shù)配合使用可以很方便的處理可空表達式
person?.let { 
   println(it.name) //輸出name
}

下面再舉個例子來深刻理解下let函數(shù):

// 沒有使用let函數(shù)的代碼是這樣的,看起來不夠優(yōu)雅

mVideoPlayer?.setVideoView(activity.course_video_view)
mVideoPlayer?.setControllerView(activity.course_video_controller_view)
mVideoPlayer?.setCurtainView(activity.course_video_curtain_view)

// 使用let函數(shù)后的代碼是這樣的

mVideoPlayer?.let {
       it.setVideoView(activity.course_video_view)
       it.setControllerView(activity.course_video_controller_view)
       it.setCurtainView(activity.course_video_curtain_view)
}

2. 【!!】(Kotlin不推薦使用非空斷言,通常我們會用?:來防止程序運行時報空指針異常而崩潰)

" !! "放在對象后面代表該對象如果為null則拋出異常
" !! "放在方法傳遞實參后面,也是代表不能為null,為null會拋異常

val len = name!!.length//如果name不為空,則返回name.length,如果name為空,則拋出異常NullPointerException

使用斷!!可以很方便的在拋出空指針異常的時候定位到異常的變量的位置,但是千萬不要連續(xù)使用斷言!!

student!!.person!!.name//如果報空指針異常了則無法判斷到底是student為空還是person為空,所以不要連續(xù)使用斷言!!

" !!. "的用法就是相當于Java里的if()else()判斷null

val nullClass: NullClass?=null

nullClass!!.nullFun()

轉化成JAVA代碼

NullClass nullClass = null;
        
if (nullClass!=null) {
    nullClass.nullFun();
}else {
    throw new NullPointerException();
}
!!

3.【?:】Elvis操作符

對象foo ?: 對象bar 表達式,意思為: 當對象 foo值為 null 時,那么它就會返回后面的對象 bar,否則返回foo。


?:
val len = name?.length ?: -1//當name不為空時,返回name.length,當name為空時,返回-1

val roomList: ArrayList<Room>? = null
val mySize= roomList?.size ?: 0   //mySize 的值就為0,因為 roomList?.size 為空,

val roomList: ArrayList<FPXBean>? = null
if (roomList?.size ?: 0 > 0) {    // 這一行添加了?:
    Log.d("TAG", "-->> 列表數(shù)不是0")
}

4. 【::】

雙冒號操作符 表示把一個方法當做一個參數(shù),傳遞到另一個方法中進行使用,通俗的來講就是引用一個方法

反射

利用 ::,甚至可以享受到優(yōu)于 Java 的反射特性。

inline fun <reified T> T.foo3(string: String) {
    Log.e(T::class.simpleName, string)
}

這里暫時不需要理會 inline 和 reified,我們看到,直接使用泛型 T:: 即可反射獲得其內(nèi)部屬性,如 class,constructor 等,這在 Java 中是不可能做到的。

//得到類的Class對象
startActivity(Intent(this@KotlinActivity, MainActivity::class.java))
::方法名

雙冒號跟方法名作用就是將方法作為參數(shù)傳入。


class ColonMagic {
 
    /**
     * 不需要參數(shù)
     */
    private fun sayNoWords() {
        println(" no  msg   ")
    }
 
    /**
     * 一個參數(shù)
     * message:String類型
     */
    private fun say(message: String) {
        println(message)
    }
 
    /**
     * 兩個參數(shù)
     * msg: String類型
     * dosay: (String) -> Unit 一個參數(shù)為String不需要返回值的方法體
     */
    private fun peopleDo(msg: String, doSay: (String) -> Unit) {
        //doSay(msg)調(diào)用的就是傳入的say方法,即say(msg),只不過參數(shù)名是doSay本質(zhì)是say方法
        //此處打印出來 I say !  日志
        doSay(msg)
    }
 
    fun people() {
        //調(diào)用peopleDo方法,并傳入?yún)?shù)  “I say !” 和 say方法體
        //此處 ::say 是將say方法作為參數(shù)傳入peopleDo方法
        //此處只是將say作為參數(shù),而不會調(diào)用say方法,也就不會println(message),不會輸出日志
        peopleDo("I say !", ::say)
 
        //此處報錯,因為需要的是(String) -> Unit; 一個String參數(shù),無返回值的方法體
        //但是sayNoWords方法是沒有參數(shù)的,所以會報錯
        peopleDo("I say !", ::sayNoWords)
    }
 
}
 
fun main(msg: Array<String>) {
    ColonMagic().people();
}

mian方法中調(diào)用 ColonMagic().people();打印日志如下:

I say !

方法作為參數(shù)傳入時不會被調(diào)用,所以最后只有一行 I say !日志。

fun main() {
    foo2("xxx", this::bar2)     //right
    foo2("xxx", this::bar1)     //wrong, compile fail
}

fun bar1() {
    print("bar1")
}

fun foo2(content: String, body: (String) -> Unit) {
    body(content)
}

fun bar2(string: String) {
    print(string)
}

作為參數(shù)的函數(shù),該函數(shù)的參數(shù)類型和返回值類型一定要和規(guī)定的一致。上述的例子中bar1()是沒有任何參數(shù)類型的,而foo2中第二個參數(shù)body:(String) -> Unit ,需要一個字符串類型,所以 foo2("xxx", this::bar1) 這種寫法是錯誤的; foo2("xxx", this::bar1) 這種寫法是對的,因為bar2(string: String) 的參數(shù)類型是一個字符串,符合參數(shù)類型和返回值類型一定要和規(guī)定的一致。

  1. “->”符號操作符,單從形態(tài)上看,是一種流向和對應的關系。即前面的語句執(zhí)行之后,將執(zhí)行流轉到指向的語句,并且是對應的。

6.【$】符合和多行輸入符

val i = 10
println("i = $i") // prints "i = 10"

val s = "abc"
println("$s.length is ${s.length}") // prints "abc.length is 3"

如上面的代碼中,要把" i "連接到字符串中,模板表達式以美元符號($)開頭,由一個簡單名稱組成: $i
//三引號的形式用來輸入多行文本
val str = """ 
    one
    two
        """
//等價于          
val str = "one\ntwo"

三引號之間輸入的內(nèi)容將被原樣保留,之中的單號和雙引號不轉義,其中的不可見字符比如/n和/t都會被保留。(\t是補全當前字符串長度到8的整數(shù)倍,最少1個最多8個空格,補多少要看你\t前字符串長度,比如當前字符串長度10,那么\t后長度是16,也就是補6個空格,如果當前字符串長度12,此時\t后長度是16,補4個空格)

7. 【_】(下劃線)

在Kotlin中,可以使用一個下劃線字符(_)作為lambda或表達式函數(shù)的參數(shù)的名稱,或作為解構條目的名稱。

①作為lambda函數(shù)的參數(shù)名稱
fun main(args: Array<String>) {
    val aa = mapOf(1 to "a",2 to "B")
    aa.forEach { key, value -> println("value:$value") 
}

在上述示例中,只是用到了value值,key并沒有用到。這樣,我們就想不在聲明key,那么就需要使用下劃線字符(_)作為key替代,即:

fun main(args: Array<String>) {
    val aa = mapOf(1 to "a",2 to "B")
    aa.forEach { _, value -> println("value:$value") 
}
②作為解構聲明的參數(shù)

解構聲明就是將一個對象解構(destructure)為多個變量,也就是意味著一個解構聲明會一次性創(chuàng)建多個變量。盡管這樣很方便,但是,如果用不到的變量必然也必須得聲明,從而造成了變量的冗余。Kotlin-解構聲明

data class Person(var age: Int, var name: String)
//Peron聲明了 age,name兩個變量。解構時如果只需要age這一個變量時
val person = Preson(18, "eryang")
val (age, _) = person
③數(shù)字字面值中的下劃線

Kotlin的數(shù)字面值可以使用下劃線來分隔數(shù)值進行分組:

val oneMillion = 1_000_000
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

fun main(args: Array<String>) {

    // Log: 1000000
    println(oneMillion)

    // Log: ffecde5e
    println(hexBytes.toString(16))

    // Log: 11010010011010011001010010010010
    println(bytes.toString(2))
}

8.【@】

①限定this的類型
class User {
    inner class State{
        fun getUser(): User{
            //返回User
            return this@User
        }
        fun getState(): State{
            //返回State
            return this@State
        }
    }
}
②作為標簽
跳出雙層for
loop@ for (itemA in arraysA) {
     var i : Int = 0
      for (itemB in arraysB) {
         i++
         if (itemB > 2) {
             break@loop
         }
         println("itemB:$itemB")
     }
}
命名函數(shù)自動定義標簽
fun fun_run(){
    run {
        println("lambda")
    }
    var i: Int = run {
        return@run 1
    }
    println("$i")
    //匿名函數(shù)可以通過自定義標簽進行跳轉和返回
    i = run (outer@{
        return@outer 2
    })
    println(i)
}
從forEach函數(shù)跳出
fun forEach_label(ints: List<Int>)
{
    var i =2
    ints.forEach {
        //forEach中無法使用continue和break;
//        if (it == 0) continue //編譯錯誤
//        if (it == 2) /*break //編譯錯誤 */
        print(it)
    }
     run outer@{
         ints.forEach {
             if (it == 0) return@forEach //相當于在forEach函數(shù)中continue,實際上是從匿名函數(shù)返回
             if (it == 2) return@outer //相當于在forEach函數(shù)中使用break,實際上是跳轉到outer之外
         }
     }

    if (i == 3)
    {
        //每個函數(shù)的名字代表一個函數(shù)地址,所以函數(shù)自動成為標簽
        return@forEach_label //等同于return
    }
}

9.【as】類型轉換運算符

①“不安全的” 類型轉換操作符

如果類型轉換不成功,類型轉換操作符通常會拋出一個異常。因此,我們稱之為 不安全的(unsafe)。在 Kotlin 中,不安全的類型轉換使用中綴操作符 as

val y = null
val x: String = y as String
// 輸出
輸出

注意 null 不能被轉換為 String,因為這個類型不是 可為 null 的(nullable),也就是說,如果 y 為 null,上例中的代碼將拋出一個異常。為了實現(xiàn)與 Java 相同的類型轉換,我們需要在類型轉換操作符的右側使用可為 null 的類型,比如:

val y = null
val x: String? = y as String?
println("x = $x")   // x = null

上述代碼,表示允許 String 可空,這樣當 y = null 時,不會拋異常;但是,當類型轉換失敗時,還是會崩潰,如下:

val y = 66
val x: String? = y as String?
image.png
②“安全的” (nullable) 類型轉換操作(as?)

為了避免拋出異常,你可以使用 安全的 類型轉換操作符 as?,當類型轉換失敗時,它會返回 null,但不會拋出異常崩潰:

val y = 66
val x: String? = y as? String
println("x = $x")   // x = null

val y = null
val x: String? = y as? String
println("x = $x")   // x = null

嘗試把值轉換成給定的類型,如果類型不合適就返回null


image.png

10.【..】

Kotlin中有區(qū)間的概念,區(qū)間表達式由具有操作符形式 .. 的 rangeTo 函數(shù)輔以 in 和 !in 形成。 區(qū)間是為任何可比較類型定義的,但對于整型原生類型,它有一個優(yōu)化的實現(xiàn)。以下是使用區(qū)間的一些示例:

if (i in 1..10) { // 等同于 1 <= i && i <= 10 (1 <= i <= 10)
    println(i)
}
//使用until函數(shù),創(chuàng)建一個不包括其結束元素的區(qū)間
for (i in 1 until 10) {   // i in [1, 10) 排除了 10
     println(i)
}

for (i in 1..4) print(i) // 輸出“1234”

for (i in 4..1) print(i) // 什么都不輸出

如果你想倒序迭代數(shù)字呢?也很簡單。你可以使用標準庫中定義的 downTo() 函數(shù)

for (i in 4 downTo 1) print(i) // 輸出“4321”

step()函數(shù),可以指定任意步長

for (i in 1..4 step 2) print(i) // 輸出“13”

for (i in 4 downTo 1 step 2) print(i) // 輸出“42”

11.【{}】

這里指的是lambda表達式的符號。

// 一個參數(shù)
var callback: ((str: String) -> Unit)? = null
callback = { println(it)}
// 判斷并使用
callback?.invoke("hello")

//兩個參數(shù)
var callback2: ((name: String, age: Int) -> Unit)? = null
callback2 = { hello: String, world: Int -> println("$hello's age is $world") }
callback2?.invoke("Tom", 22)

var callback3 :((num1:Int, num2: Int)->String)? = null
//類型可以推斷
callback3 = { num1, num2 ->
    var res:Int = num1 + num2
    res.toString()
}

println(callback3?.invoke(1, 2))

kotlin中{}里面整個是lambda的一個表達式,而java8中{}部分只是lambda表達式的body部分。

12.【..】

13.【..】

14.【..】

15.【..】

參考:
1:https://blog.csdn.net/lckj686/article/details/80448471
2:https://blog.csdn.net/u011288271/article/details/106495785
3:https://blog.csdn.net/u011489043/article/details/95175506
4:https://blog.csdn.net/zxc123e/article/details/73368781

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375