Kotlin 常见符号大全

【?,!!,?:,:: ,->,$,_(下划线),@,as,…,{},,,】

1. 【?】

" ?" 修饰在成员变量的类型后面,表示这个变量可以为null,系统在任何情况下不会报它的空指针异常。
" ? " 修改在对象后面代表该对象如果为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函数和?.同时使用来处理可空表达式

person?.let{ 
      //内部的it一定是非空的
 }
//如果person为空就不会调用let函数
//如果person不为空才会调用let函数,所以?.和let函数配合使用可以很方便的处理可空表达式
person?.let { 
   println(it.name) //输出name
}

下面再举个例子来深刻理解下let函数:

// 没有使用let函数的代码是这样的,看起来不够优雅

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

// 使用let函数后的代码是这样的

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

使用断!!可以很方便的在抛出空指针异常的时候定位到异常的变量的位置,但是千万不要连续使用断言!!

student!!.person!!.name//如果报空指针异常了则无法判断到底是student为空还是person为空,所以不要连续使用断言!!

" !!. "的用法就是相当于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", "-->> 列表数不是0")
}

4. 【::】

双冒号操作符 表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法
反射
利用 ::,甚至可以享受到优于 Java 的反射特性。

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

这里暂时不需要理会 inline 和 reified,我们看到,直接使用泛型 T:: 即可反射获得其内部属性,如 class,constructor 等,这在 Java 中是不可能做到的。

//得到类的Class对象
startActivity(Intent(this@KotlinActivity, MainActivity::class.java))

::方法名
双冒号跟方法名作用就是将方法作为参数传入。

class ColonMagic {
 
    /**
     * 不需要参数
     */
    private fun sayNoWords() {
        println(" no  msg   ")
    }
 
    /**
     * 一个参数
     * message:String类型
     */
    private fun say(message: String) {
        println(message)
    }
 
    /**
     * 两个参数
     * msg: String类型
     * dosay: (String) -> Unit 一个参数为String不需要返回值的方法体
     */
    private fun peopleDo(msg: String, doSay: (String) -> Unit) {
        //doSay(msg)调用的就是传入的say方法,即say(msg),只不过参数名是doSay本质是say方法
        //此处打印出来 I say !  日志
        doSay(msg)
    }
 
    fun people() {
        //调用peopleDo方法,并传入参数  “I say !” 和 say方法体
        //此处 ::say 是将say方法作为参数传入peopleDo方法
        //此处只是将say作为参数,而不会调用say方法,也就不会println(message),不会输出日志
        peopleDo("I say !", ::say)
 
        //此处报错,因为需要的是(String) -> Unit; 一个String参数,无返回值的方法体
        //但是sayNoWords方法是没有参数的,所以会报错
        peopleDo("I say !", ::sayNoWords)
    }
}

fun main(msg: Array<String>) {
    ColonMagic().people();
}

mian方法中调用 ColonMagic().people();打印日志如下:

I say !

方法作为参数传入时不会被调用,所以最后只有一行 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)
}

作为参数的函数,该函数的参数类型和返回值类型一定要和规定的一致。上述的例子中bar1()是没有任何参数类型的,而foo2中第二个参数body:(String) -> Unit ,需要一个字符串类型,所以 foo2(“xxx”, this::bar1) 这种写法是错误的; foo2(“xxx”, this::bar1) 这种写法是对的,因为bar2(string: String) 的参数类型是一个字符串,符合参数类型和返回值类型一定要和规定的一致。

5. “->”符号操作符

单从形态上看,是一种流向和对应的关系。即前面的语句执行之后,将执行流转到指向的语句,并且是对应的。

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和/t都会被保留。(\t是补全当前字符串长度到8的整数倍,最少1个最多8个空格,补多少要看你\t前字符串长度,比如当前字符串长度10,那么\t后长度是16,也就是补6个空格,如果当前字符串长度12,此时\t后长度是16,补4个空格)

7. 【_】(下划线)

在Kotlin中,可以使用一个下划线字符(_)作为lambda或表达式函数的参数的名称,或作为解构条目的名称。

①作为lambda函数的参数名称

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") 
}

②作为解构声明的参数
解构声明就是将一个对象解构(destructure)为多个变量,也就是意味着一个解构声明会一次性创建多个变量。尽管这样很方便,但是,如果用不到的变量必然也必须得声明,从而造成了变量的冗余。Kotlin-解构声明

data class Person(var age: Int, var name: String)
//Peron声明了 age,name两个变量。解构时如果只需要age这一个变量时
val person = Preson(18, "eryang")
val (age, _) = person

③数字字面值中的下划线
Kotlin的数字面值可以使用下划线来分隔数值进行分组:

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")
     }
}

命名函数自动定义标签

fun fun_run(){
    run {
        println("lambda")
    }
    var i: Int = run {
        return@run 1
    }
    println("$i")
    //匿名函数可以通过自定义标签进行跳转和返回
    i = run (outer@{
        return@outer 2
    })
    println(i)
}

从forEach函数跳出

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函数中continue,实际上是从匿名函数返回
             if (it == 2) return@outer //相当于在forEach函数中使用break,实际上是跳转到outer之外
         }
     }

    if (i == 3)
    {
        //每个函数的名字代表一个函数地址,所以函数自动成为标签
        return@forEach_label //等同于return
    }
}

9.【as】类型转换运算符

①“不安全的” 类型转换操作符
如果类型转换不成功,类型转换操作符通常会抛出一个异常。因此,我们称之为 不安全的(unsafe)。在 Kotlin 中,不安全的类型转换使用中缀操作符 as

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

在这里插入图片描述
注意 null 不能被转换为 String,因为这个类型不是 可为 null 的(nullable),也就是说,如果 y 为 null,上例中的代码将抛出一个异常。为了实现与 Java 相同的类型转换,我们需要在类型转换操作符的右侧使用可为 null 的类型,比如:

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

println(“x = $x”) // x = null
上述代码,表示允许 String 可空,这样当 y = null 时,不会抛异常;但是,当类型转换失败时,还是会崩溃,如下:

val y = 66
val x: String? = y as String?

在这里插入图片描述
②“安全的” (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

在这里插入图片描述

10.【…】

Kotlin中有区间的概念,区间表达式由具有操作符形式 … 的 rangeTo 函数辅以 in 和 !in 形成。 区间是为任何可比较类型定义的,但对于整型原生类型,它有一个优化的实现。以下是使用区间的一些示例:

if (i in 1..10) { // 等同于 1 <= i && i <= 10 (1 <= i <= 10)
    println(i)
}
//使用until函数,创建一个不包括其结束元素的区间
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) // 什么都不输出

如果你想倒序迭代数字呢?也很简单。你可以使用标准库中定义的 downTo() 函数

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

step()函数,可以指定任意步长

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

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

11.【{}】
这里指的是lambda表达式的符号。

// 一个参数
var callback: ((str: String) -> Unit)? = null
callback = { println(it)}
// 判断并使用
callback?.invoke("hello")

//两个参数
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部分。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Kotlin为我们提供了许多内置函数来简化代码编写和提高代码的可读性。下面是一些常用的Kotlin内置函数: 1. apply函数:apply函数允许我们在对象的上下文中执行一系列操作,并返回该对象本身。这对于初始化对象的属性非常有用。 2. also函数:also函数与apply函数类似,不同之处在于它返回的是传入的对象,而不是上下文对象本身。它通常用于执行一些附加操作,例如打印日志或进行调试。 3. let函数:let函数允许我们对一个非空的对象执行一系列操作,并返回一个结果。它可以帮助我们避免空指针异常。 4. run函数:run函数允许我们在上下文中执行一系列操作,并返回该上下文的结果。它类似于apply函数,但不同之处在于run函数返回的是闭包的结果,而不是上下文对象本身。 5. with函数:with函数允许我们在上下文中执行一系列操作,而无需使用上下文对象的名称。它通常与非空的对象一起使用,以方便地访问对象的属性和方法。 6. takeIf函数:takeIf函数接受一个断言条件作为参数,并返回该对象本身,如果条件为真;否则返回null。这用于根据条件过滤对象。 7. takeUnless函数:takeUnless函数与takeIf函数相反,它接受一个断言条件作为参数,并返回该对象本身,如果条件为假;否则返回null。它也用于根据条件过滤对象。 这些内置函数在Kotlin标准库中定义,可在任何Kotlin项目中使用。它们有助于简化代码,提高开发效率。了解这些函数的用法将使您能够更好地利用Kotlin的语言特性。 请注意,这只是一小部分Kotlin内置函数的介绍。在Kotlin的标准库中还有许多其他有用的函数等待您去探索和使用。希望这些信息对您有所帮助! <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Kotlin之内置函数](https://blog.csdn.net/qq_32955807/article/details/128448836)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Kotlin中内置函数的用法和区别总结](https://download.csdn.net/download/weixin_38692928/14029345)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值