【Android】Kotlin教程(2)

文章目录

1.空安全

为了避免NullPointerException,Kotlin的做法是不让我们给非空类型变量赋null值,但是null在Kotlin中依然存在。

kotlin 复制代码
    var str1:String = "hello world"
    str1 = null


    var str2:String? = "hello world"
    str2 = null

2.let安全调用

let 是一个作用于对象的范围函数(scope function),它允许你在给定的对象上执行一段代码块,并且在这个代码块中可以访问该对象。let 函数的一个主要用途是避免空指针异常(NullPointerException),以及简化一些常见的操作。

1.避免空指针异常:

kotlin 复制代码
val name: String? = "Alice"
name?.let {
    println("Name is $it")
}

2.简化代码:

kotlin 复制代码
val nullableString: String? = "Hello, World!"
val length = nullableString?.let {
    println("Length before trimming: ${it.length}")
    it.trim().length
}

println("Final length: $length")  // 输出 "Final length: 13"

3.返回值:

kotlin 复制代码
val nullableString: String? = " Hello, World! "
val trimmedLength = nullableString?.let {
    it.trim().length
}

println(trimmedLength)  // 输出 13

4.链式调用:

kotlin 复制代码
val person = Person()
person.name?.let { name ->
    println("Person's name is $name")
} ?: run {
    println("Person's name is not set")
}

3.非空断言操作符!!

非空断言操作符 !! 用于告诉编译器你确定某个可空类型(nullable type)的变量或表达式实际上是非空的。使用这个操作符时,如果该变量或表达式的值是 null,则会抛出一个 KotlinNullPointerException。非空断言操作符通常用于那些你非常确定不会为 null 的情况,或者你希望在值为 null 时立即处理异常的情况。

kotlin 复制代码
    str2 = null
    println(str2!!.capitalize())

4.空合并操作符 ?:

空合并操作符 ?: 是一个非常有用的操作符,用于处理可能为 null 的值。它允许你提供一个默认值,当表达式的结果为 null 时,将使用这个默认值。这有助于避免空指针异常,并使代码更加简洁和安全。

kotlin 复制代码
    val name: String? = null
    val greeting = "Hello, ${name ?: "Guest"}!"
    println(greeting)  // 输出 "Hello, Guest!"

1.提供默认值:

当你需要为一个可能为 null 的变量提供一个默认值时,可以使用空合并操作符。

kotlin 复制代码
val name: String? = null
val greeting = "Hello, ${name ?: "Guest"}!"
println(greeting)  // 输出 "Hello, Guest!"

2.简化条件语句:

kotlin 复制代码
val nullableString: String? = null
val length = (nullableString?.length ?: 0)
println(length)  // 输出 0

3.链式调用:

kotlin 复制代码
data class Person(val name: String?, val address: Address?)
data class Address(val city: String?)

val person: Person? = Person("Alice", Address(null))
val city = person?.address?.city ?: "Unknown City"
println(city)  // 输出 "Unknown City"

4.执行计算或逻辑:

kotlin 复制代码
val nullableInt: Int? = null
val result = nullableInt ?: computeDefaultValue()
println(result)

fun computeDefaultValue(): Int {
    return 42
}

5.处理集合:

你可以用空合并操作符来处理可能为 null 的集合,并提供一个默认的空集合。

kotlin 复制代码
val list: List<String>? = null
val nonNullList = list ?: listOf()
println(nonNullList)  // 输出 []

5.异常

在 Kotlin 中,异常处理机制与 Java 类似,但有一些额外的特性和改进。Kotlin 使用 try, catch, finally 语句来处理异常,并且提供了一些额外的功能,如非局部返回和更简洁的语法。

kotlin 复制代码
fun main() {
    var number:Int? = null

    try {
        checkOperation(number)
        number!!.plus(1)
    }catch (e:Exception){
        println(e)
    }
}

fun checkOperation(number: Int?){
    number ?: throw UnskilledException()
}

class UnskilledException() : IllegalArgumentException("操作不当")

6.先决条件函数

先决条件函数 (precondition function)通常是指在执行某个操作之前必须满足的条件。这些条件用于确保函数在安全和正确的状态下运行。如果先决条件不满足,函数可以选择抛出异常、返回错误代码或以其他方式处理这种情况。

7.substring

字符串截取,substring函数支持IntRange类型(表示一个整数范围的类型)的参数。

8.split函数

split函数返回的是List集合数据,List集合又支持结构语法特性,它允许你在一个表达式里给多个变量赋值,解构常用来简化变量的赋值。

kotlin 复制代码
const val NAMES = "jacky,jackson,jack"

fun main() {
    val data = NAMES.split(",")

    val (origin,dest,proxy) = NAMES.split(",")
    println("$origin $dest $proxy")

    for (name in data) {
        println(name)
    }
}

9.replace

kotlin 复制代码
    val strt1 = "The people's Republic of China"
    val str2 = strt1.replace(Regex("[aeiou]")){
        when(it.value){
            "a" -> "*"
            "e" -> "*"
            "i" -> "*"
            "o" -> "*"
            "u" -> "*"
            else -> it.value
        }
    }
    println(strt1)
    println(str2)

10.字符串比较

在Kotlin中,用==检查两个字符串中的字符是否匹配,用===检查两个变量是否指向内存堆上同一对象,而在Java中==做引用比较,做结构比较时用equals方法。

kotlin 复制代码
    val str3 = "Jackon"
    val str4 = "jackon".capitalize()
    println("$str3   $str4")
    println(str3 == str4) // true
    println(str3 === str4) // false

11.安全转换函数

安全转换函数,如果数值不能正确转换,与其触发异常不如干脆返回null

kotlin 复制代码
    val number:Int = "9".toInt() // 转换为Int类型
    val number1 :Int? = "9.0".toIntOrNull() // null
    val number2 : Int = 9.87.roundToInt() // 10 四舍五入
    val number3 = "%.2f".format(9.8779000) // 9.88

12.标准库函数

1.apply
  • apply函数可以看做是一个配置函数,你可以传入一个接受者,然后调用一系列的函数来配置使用,如果提供lambda给apply函数执行,它会返回配置好的接受者。
  • apply 函数非常适合用于对象的初始化或配置,因为它允许你直接访问和修改对象的属性,而不需要显式地引用对象。
kotlin 复制代码
fun main(){
    val file1 = File("E://i have a dream_copy.txt")
    file1.setReadable(true)
    file1.setWritable(true)
    file1.setExecutable(true)
    
    val file2 = File("E://i have a dream_copy.txt").apply { 
        setReadable(true)
        setWritable(true)
        setExecutable(true)
    }
}
2.run

run 是一个作用域函数(scope function),它允许你在对象的上下文中执行一段代码块,并且可以返回该代码块的结果。run 函数非常适合用于初始化对象、配置对象或执行一系列操作并获取结果。

kotlin 复制代码
val result = objectInstance.run {
    // 在这里可以访问和修改 objectInstance 的属性
    // this 指代 objectInstance
    // 返回值是代码块的最后一个表达式的值
}
  • objectInstance 是你要操作的对象。
  • { ... } 是一个 lambda 表达式,在这个表达式中你可以直接访问和修改 objectInstance 的属性。
  • this 关键字在 lambda 表达式中指代 objectInstance。
  • run 函数返回 lambda 表达式的最后一个表达式的值。
kotlin 复制代码
fun main(){
    data class Person(var name: String, var age: Int)

    val person = Person("", 0).run {
        name = "Alice"
        age = 30
        this  // 返回当前对象
    }

    println(person)  // 输出 Person(name=Alice, age=30)
}
kotlin 复制代码
val result = "The people's Republic of China".run(::isLong)

fun isLong(name : String) = name.length > 10
3.with

with 函数是一个作用域函数(scope function),它允许你在给定对象的上下文中执行一系列操作。与 apply 和 run 不同的是,with 需要显式地传递一个接收者对象,并且它返回的是 lambda 表达式的最后一个表达式的值,而不是接收者对象本身。

kotlin 复制代码
val result = with(objectInstance) {
    // 在这里可以访问和修改 objectInstance 的属性
    // this 指代 objectInstance
    // 返回值是代码块的最后一个表达式的值
}
kotlin 复制代码
fun main(){
    data class Person(var name: String, var age: Int)

    val person = Person("Alice", 30)
    val updatedPerson = with(person) {
        name = "Bob"
        age = 25
        this  // 返回当前对象
    }

    println(updatedPerson)  // 输出 Person(name=Bob, age=25)
}
4.also

also 是一个作用域函数(scope function),它允许你在给定对象的上下文中执行一系列操作,并且最终返回该对象本身。alsoapply 类似,但主要的区别在于 also 的 lambda 表达式中使用的是 it 来引用接收者对象,而不是 this。

kotlin 复制代码
val result = value.also { it ->
    // 在这里可以使用 value
    // it 代表 value
}
kotlin 复制代码
fun main(){
    data class User(var name: String, var email: String, var age: Int)

    val user = User("", "", 0).also {
        it.name = "Alice"
        it.email = "alice@example.com"
        it.age = 30
    }

    println(user)  // 输出 User(name=Alice, email=alice@example.com, age=30)
}
5.takeIf

takeIf 是一个非常有用的标准库函数,它允许你根据给定的条件选择性地返回对象。如果条件满足,则返回该对象;如果不满足,则返回 null。这使得takeIf成为处理条件逻辑和避免空指针异常的强大工具。

kotlin 复制代码
val result = value.takeIf { condition }
  • value 是你要检查的对象。
  • { condition } 是一个 lambda 表达式,它接受 value 作为参数并返回一个布尔值。
  • 如果 condition 为 true,则 takeIf 返回 value;否则返回 null。

条件过滤

kotlin 复制代码
fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val evenNumbers = numbers.filter { it.takeIf { it % 2 == 0 } != null }

    println(evenNumbers)  // 输出 [2, 4]
}

安全访问

kotlin 复制代码
val nullableString: String? = "  Hello, World!  "
val trimmedString = nullableString?.takeIf { it.isNotBlank() }?.trim()

println(trimmedString)  // 输出 "Hello, World!"
6.takeUnless

takeUnless takeIf 的反向操作。takeUnless 函数允许你根据给定的条件选择性地返回对象。如果条件不满足(即条件表达式的结果为 false),则返回该对象;如果条件满足(即条件表达式的结果为 true),则返回 null。这使得 takeUnless 成为处理否定条件逻辑和避免空指针异常的强大工具。

相关推荐
阿巴斯甜1 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android