Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解

简介: Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解

一、Kotlin的可空性

null 在java中我们司空见惯的空指针异常NullPointerException,带给了我们很多麻烦。

Kotlin作为更强大的语言,势必会基于以往的语言设计经验对其进行改良。Kotlin更多

地把运行时可能会出现的null问题,以编译时错误的方式,提前在编译期强迫我们重视起来,

而不是等到运行时报错,防范于未然,提高了我们的程序的健壮性。

二、Kotlin中的安全调用操作符,非空断言操作符,空合并操作符的详解,代码中已经给出详细注释

fun main() {
    /**
     * 可空性:?
     * 对于null值问题,Kotlin反其道而行之,除非另有规定,变量不可为null值,这样一来,
     * 运行时崩溃问题从根源上得到解决。
     *
     * Kotlin的null类型:
     * 为了避免NullPointerException,Kotlin的做法是不让我们给非空类型变量赋null值,
     * 但null在Kotlin中依然存在。
     */
    var str: String? = "butterfly"
    str = null
    println(str)
    /**
     * null安全:
     * 1.Kotlin区分可空类型和非可空类型,所以,你要一个可空类型变量运行,而它又可能
     * 不存在,对于这种潜在危险,编译器时刻警惕着。为了应对这种风险,Kotlin不允许你在
     * 可空类型值上调用函数,除非你主动接收安全管理。
     */
    /**
     * 选项一: 安全调用操作符:?.
     * 这次Kotlin不报错了,编译器看到有安全调用操作符,所以它知道如何检查null值。如果
     * 遇到null值,它就跳过函数调用,而不是返回null。
     */
    println(str?.capitalize())
    str = "butterfly"
    str = str?.let {
        //非空白的字符串
        if (it.isNotBlank()) {
            it.capitalize()
        } else {
            "butterfly test"
        }
    }
    println(str)
    /**
     * 选项二:使用非空断言操作符:
     * 1.!!.又称感叹号操作符,当变量值为null时,会抛出KotlinNullPointerException
     */
//    str = null
//    println(str!!.capitalize())
    /**
     * 选项三:使用if判断null值情况
     * 我们可以使用if判断,但是相比之下安全调用操作符用起来更灵活,代码也更简洁,我们
     * 可以用安全操作符进行多个函数的链式调用。
     */
    if (str != null) {
        str.capitalize()
    } else {
        println("str 是空的")
    }
    str = str?.capitalize()?.plus(" is great.")
    println(str)
    /**
     * 使用空合并操作符
     * ?:操作符的意思是,如果左边的求值结果为null,就使用右边的结果值
     */
    str = null
    println(str ?: "str is null")
    /**
     * 空合并操作符也可以和let函数一起使用来代替if/else语句
     */
    str = null
    str = str?.let {
        it.capitalize()
    } ?: "butterfly"
    println(str)
}

输出结果如下:

null
null
Butterfly
Butterfly is great.
str is null
butterfly

三、异常处理和自定义异常,先决条件函数

fun main() {
    var number: Int? = null
    try {
        checkOperation(number)
        number!!.plus(1)
    } catch (e: Exception) {
        println(e)
    }
}
fun checkOperation(number: Int?) {
//    number ?: throw UnSkilledException()
    /**
     * 先决条件函数
     * Kotlin标准库提供了一些便利函数,使用这些内置函数,你可以抛出带自定义
     * 信息的异常,这些便利函数叫做先决条件函数,你可以用它定义先决条件,条件必须满足
     * 目标代码才能执行。
     */
    checkNotNull(number) {
        "Something is not good"
    }
}
/**
 * 自定义异常
 * IllegalArgumentException 有一个是java.lang包下的
 * 另外一个是kotlin下面的,kotlin下面的其实只是一个别名等于java.lang包下的
 * @SinceKotlin("1.1") public actual typealias IllegalArgumentException = java.lang.IllegalArgumentException
 */
class UnSkilledException() : IllegalArgumentException("操作不当")

输出结果如下:

java.lang.IllegalStateException: Something is not good

先决条件函数有如下:

四、substring、split、replace,字符串遍历方法的使用

const val NAME = "I like Android development"
const val WORK = "I,like,Android,development"
fun main() {
    /**
     * substring
     * 字符串截取,substring函数支持IntRange类型(表示一个整数范围的类型)的参数,
     * util创建的范围不包括上限值
     */
    val substring = NAME.substring(7, 14)
    var str = NAME.substring(7 until 14)
    println(substring)
    println(str)
    /**
     * split
     * split函数返回的是list集合数据,List集合数据又支持解构语法特性,它允许你
     * 在一个表达式里给多个变量赋值,解构常用来简化变量的赋值。
     */
    val data = WORK.split(",")
    //data[0] 取集合中的元素
    /**
     * 这就是解构语法
     */
    val (origin, dest, proxy, detail) = WORK.split(",")
    println("$origin $dest $proxy $detail")
    val text = "The people's Republic of China"
    val text2 = text.replace(Regex("[aeiou]")) {
        when (it.value) {
            "a" -> "8"
            "e" -> "6"
            "i" -> "9"
            "o" -> "1"
            "u" -> "3"
            else -> it.value
        }
    }
    println(text)
    println(text2)
    /**
     * 遍历字符串
     */
    "The people's Republic of China".forEach {
        print("$it *")
    }
}

输出结果如下:

Android
Android
I like Android development
The people's Republic of China
Th6 p61pl6's R6p3bl9c 1f Ch9n8
T *h *e *  *p *e *o *p *l *e *' *s *  *R *e *p *u *b *l *i *c *  *o *f *  *C *h *i *n *a *

五、- = =与===的比较

fun main() {
    /**
     * 字符串比较
     * 在kotlin中,用==检查两个字符串的字符是否匹配,用===检查两个变量是否
     * 指向内存堆上同一对象,而java中==做引用比较,做内容比较时用equals方法
     */
    val str1 = "Jason"
    val str2 = "jason".capitalize()
    println(str1 == str2) //true
    println(str1 === str2) //false
}

六、数字类型的安全转换函数,Double转Int类型、以及格式化

fun main() {
    /**
     * 数字类型
     * 和java一样,Kotlin中所有数字类型都是有符号的,也就是说既可以表示正数,也可以表示负数
     *
     */
    /**
     * 数字格式异常 NumberFormatException
     */
//    val number1: Int = "8.98".toInt()
    /**
     * 安全转换函数
     * Kotlin提供了toDoubleOrNull和toIntOrNull这样的安全转换函数,如果数值
     * 不能正确转换,与其触发异常不如干脆返回null值
     */
    val number: Int? = "8.9".toIntOrNull()
    println(number)
    val number2: Double? = "0.91".toDoubleOrNull()
    println(number2)
    val number3: Double? = "1.99".toDouble()
    println(number3)
    /**
     * Double转Int
     * 四舍五入
     */
    println(8.99.roundToInt())
    println(8.49.roundToInt())
    /**
     * Double转Int
     * toInt:精度损失
     */
    println(8.956.toInt())
    /**
     * 格式化字符串是一串特殊字符,它决定该如何格式化数据
     */
    val str = "%.2f".format(8.956)
    println(str)
}

输出结果如下:

null
0.91
1.99
9
8
8
8.96


目录
相关文章
|
23天前
|
缓存 数据处理 Android开发
Android经典实战之Kotlin常用的 Flow 操作符
本文介绍 Kotlin 中 `Flow` 的多种实用操作符,包括转换、过滤、聚合等,通过简洁易懂的例子展示了每个操作符的功能,如 `map`、`filter` 和 `fold` 等,帮助开发者更好地理解和运用 `Flow` 来处理异步数据流。
69 4
|
10天前
|
Java 调度 Android开发
Android经典实战之Kotlin的delay函数和Java中的Thread.sleep有什么不同?
本文介绍了 Kotlin 中的 `delay` 函数与 Java 中 `Thread.sleep` 方法的区别。两者均可暂停代码执行,但 `delay` 适用于协程,非阻塞且高效;`Thread.sleep` 则阻塞当前线程。理解这些差异有助于提高程序效率与可读性。
34 1
|
27天前
|
缓存 API Android开发
Android经典实战之Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate
本文介绍了Kotlin中`Flow`的`debounce`、`buffer`及`conflate`三个操作符。`debounce`过滤快速连续数据,仅保留指定时间内的最后一个;`buffer`引入缓存减轻背压;`conflate`仅保留最新数据。通过示例展示了如何在搜索输入和数据流处理中应用这些操作符以提高程序效率和用户体验。
30 6
|
7天前
|
安全 Java 编译器
深入浅出:Kotlin 中的空安全机制
【8月更文挑战第31天】
17 0
|
30天前
|
Java Android开发 开发者
Kotlin 循环与函数详解:高效编程指南
高效编程实践 • 避免不必要的循环 - 尽量使用集合操作如 map、filter 来减少显式的循环。 • 使用尾递归优化 - 对于需要大量递归的情况,考虑使用尾递归以优化性能。 • 内联函数 - 对于传递 Lambda 表达式的函数,使用 inline 关键字可以减少运行时开销。 通过上述指南,您应该能够更好地理解 Kotlin 中的循环和函数,并能够编写更加高效和简洁的代码。Kotlin 的设计哲学鼓励开发者编写易于理解和维护的代码,而掌握循环和函数是实现这一目标的关键步骤。 如果您想了解更多关于 Kotlin 的循环和函数的信息,以下是一些官方文档和资源,它们可以提供额外的参考
31 1
|
30天前
|
Java Kotlin
Kotlin 循环与函数详解:高效编程指南
Kotlin中的循环结构让你能轻松遍历数组或范围内的元素。使用`for`循环结合`in`操作符,可以简洁地访问数组中的每个项,如字符串数组或整数数组。对于范围,可以用`..`来定义一系列连续的值并进行迭代。此外,Kotlin支持通过`break`和`continue`控制循环流程。函数则允许封装可复用的代码块,你可以定义接受参数并返回值的函数,利用简写语法使代码更加紧凑。例如,`myFunction(x: Int, y: Int) = x + y`简洁地定义了一个计算两数之和的函数。
34 1
|
2月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin中常见作用域函数
**Kotlin作用域函数概览**: `let`, `run`, `with`, `apply`, `also`. `let`安全调用并返回结果; `run`在上下文中执行代码并返回结果; `with`执行代码块,返回结果; `apply`配置对象后返回自身; `also`附加操作后返回自身
36 8
|
2月前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
46 7
|
2月前
|
Android开发 Kotlin
Android面试题之kotlin中怎么限制一个函数参数的取值范围和取值类型等
在Kotlin中,限制函数参数可通过类型系统、泛型、条件检查、数据类、密封类和注解实现。例如,使用枚举限制参数为特定值,泛型约束确保参数为Number子类,条件检查如`require`确保参数在特定范围内,数据类封装可添加验证,密封类限制为一组预定义值,注解结合第三方库如Bean Validation进行校验。
45 6
|
3月前
|
Java Kotlin
Kotlin 中的 apply 函数详解
Kotlin 中的 apply 函数详解
212 0
下一篇
DDNS