Kotlin学习与实践 (十)Kotlin的可控性

可空类型

* 类型就是数据的分类。决定了该类型可能的值,以及在该类型值上可以完成的操作。

* 与Java不同,Kotlin对可空类型的显示的支持。可空类型是Kotlin类型系统中帮助避免NullPointException错误的特性。* 这是一种指出你的程序中那些变量和属性允许为null的方式。

* 可空类型和非可空类型的对象在运行时没有什么区别,可空类型并不是非空类型的包装。所有检查都是在编译时期,所以Kotlin的可空类型并不会在运行时带来额外的开销。先来看看Java中的空指针是怎么造成的


private int stringLen(String s){
    retrun s.length
}

当传入的参数s为null的时候就会发生空指针异常、。


* 使用Kotlin声明同样的方法不接收可能为null的参数,因为当如果传入可能会null的参数在编译器就会被标记成错误。* 这样就保证了strLen函数永远不会在运行的时候抛出NullPointException


fun strLen(s: String) = s.length //Kotlin默认s是不可为null的参数如果你传入一个可能为null参数,编译的时候就会报错



  如果你想要声明一个接收参数可能为null的参数,就需要将这个参数声明为可空类型的参数,而可控类型的参数声明起来也特别简单,只需要咋参数的类型之后加上?


* ?可以加载任意类型的后面来表示这个类型的变量可以存储null引用。如String? Int? MyCustomType?* Type ? = Type or null* 没有问号的类型表示这种类型的变量不能存储为null.这说明说有的常见类型都是默认为非空的,除非显示地把它标记为可空的* 可空类型的变量不能直接调用其方法、不能把它赋值给费空类型的变量、也不能把可空类型的值传递给拥有非空类型的参数的函数。* 再与null 进行比较之后,编译器就会记住,并且在这次比较发生的作用域内把这个值当错非空来对待


fun nullAbleStrLen(s: String?): Int = if (null != s) s.length else 0

 安全调用符 

* Kotlin提供了一种非常有用的工具:安全调用运算符"?"* 它允许你把一次对null的检查和一次方法调用合并成一个操作。例如:s?.toUpperCase() 等同于 if(s!=null) s.toUpperCase() else null* 如果你试图调用一个非空值的方法,这次方法调用就会被正常执行。但是如果是null 这次调用就不会发生,而整个表达式的值就为null
fun printAllCaps(s: String?) {
    //这里要注意 因为后面的表达式返回值可能为空,前面的对象类型声明的时候就要声明成可空类型
    val allCaps: String? = s?.toUpperCase()
    println(allCaps)
}
* 安全调用不光可以调用方法,也能用来访问属性* Kotlin 支持多个安全调用链接再一起使用
fun managerName(employee: Employee): String? = employee?.name

class Address(val streetAddress: String, val zipCode: Int, val city: String, val country: String)
class Company(val name: String, val address: Address?)
class Person(val name: String, val company: Company?)

fun Person.countryName(): String {
    val country = this.company?.address?.country
    return if (null != country) country else "Unknown"
}

 Elvis 运算符“?:”

* Elvis 运算符“?:”* Kotlin 有方便的运算符来提供null的默认值。它被称作Elvis运算符(或 null合并运算符) ->  ?:** Elvis运算符接收两个运算数,如果第一个运算数不为null,运算结果就是第一个运算数,如果第一个运算数为null,运算结果就是第二个运算数


fun foo(s: String?): String {
    val t: String = s ?: " "
    return t
}
* Elvis运算符经常和安全调用运算符一起使用,用一个值代替对null对象调用方法时返回的null
fun strLenSafe(s: String?): Int = s?.length ?: 0
* 上面获取countryName的方法就可以使用Elvis进一步简化
fun Person.getCountryName(): String = this.company?.address?.country ?: "Unknown"
* Kotlin中 Elvis和return 、 throw 表达式结合再一起使用会更加好使
fun printShippingLabel(person: Person) {
    val address = person?.company?.address ?: throw IllegalArgumentException("No address")
    with(address) {
        println(streetAddress)
        println("$zipCode $city $country")
    }
}

 安全转换 "as?"

* 常规的as运算符和Java中的类型转换一样转换对象的类型,如果被转换的值不是你试图转化的类型,就会抛出ClassCastException。Kotlin提供了一种安全的类型转化操作 as?* as?运算符尝试把值转换成指定的类型,如果值不是合适的类型就返回null ,经常会和Elvis “?:” 一起使用。
class Person1(val firstName: String, val lastName: String) {
    override fun equals(other: Any?): Boolean {
        //类型检查如果不匹配就返回false
        val otherPersion1 = other as?Person1 ?: return false
        //安全检查之后变量会被只能转换为Person1类型
        return otherPersion1.firstName == firstName && otherPersion1.lastName == lastName
    }

    override fun hashCode(): Int {
        return firstName.hashCode() * 37 + lastName.hashCode()
    }
}

 非空断言 “!!”

* 非空断言是Kotlin提供的一种简单直率的处理可空类型值的工具。* 它使用双叹号表示,可以把任何值转化为非空类型,如果要转换的值是null,则会抛出NullPointException异常
fun ignoreNulls(s: String?) {
    val sNotNull: String = s!!
    println(sNotNull)
}
//注意当使用!!并且它的结果是异常时,异常调用栈的跟踪信息只会表明异常发生在哪一行,不会表明异常时由那个值引起的,所以尽量避免在一行使用多个非空断言// person!!.company!!.address!!.name  出现异常的时候不好查找引起的对象
 

原文地址:https://www.cnblogs.com/mauiie/p/kotlin_null.html

时间: 2024-07-30 08:50:36

Kotlin学习与实践 (十)Kotlin的可控性的相关文章

Kotlin学习与实践 (三)fun 函数

通过例子来学习如何高效的在Kotlin中定义使用函数. 1.命名参数.默认参数.顶层函数.扩展函数 * 展示几种创建集合类的方法和扩展的简单操作集合类的方法 fun createCollection() { val set = hashSetOf(1, 12, 26) println("hashSetOf -- > ${set.javaClass}") val list = arrayListOf(12, 24, 66) println("arrayListOf --

Kotlin学习与实践 (四)类、接口

1.类的继承结构 接口 * Kotlin的类和接口与Java的有些地方不一样:* Kotlin的声明默认是public final的.* Kotlin嵌套的类默认不是内部类:它没有包含对外部类的隐式引用 等* Kotlin也一样是使用interface来声明接口 * 如下: 声明一个简单的接口 interface Clickable { fun click() fun longPress() = println("longPress") //接口中的抽象方法也可以有默认的实现,有了默认

Kotlin学习与实践 (九)带接收者的lambda及Java的函数式接口

带接收者的lambda * 在lambda 函数体内可以调用一个不同对象的方法,而且无须借助任何额外限定符:这种能力再Java中是找不到的.* 这样的lambda叫做"带接收者的lambda" 先举个普通函数作为反例: fun alphabet(): String { val result = StringBuilder() for (letter in 'A'..'Z') { result.append(letter) } result.append("\nNow ,I k

Kotlin学习资料

欢迎关注本人Github:https://github.com/itgoyo 里边会时刻更新一些最新最潮的技术文章 2017-5-18 Google I/O 大会指定Kotlin成为Android的官方开发语言 本项目地址:https://github.com/kotlinandroid/kotlin-for-android 欢迎大家?????? 以下是收集整理的Kotlin资料 Kotlin官方资料Github地址: [https://github.com/JetBrains/kotlin](

一个Swifter的Kotlin学习——Kotlin 基本语法

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 一个Swifter的Kotlin学习--Kotlin 基本语法 - u012903898的博客 - 博客频道 - CSDN.NET u012903898的博客 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书讯]流畅的Python

Kotlin学习之函数

函数声明 在kotlin中用关键字fun声明函数: fun double(x:Int):Int{ } 其中Int是返回值类型,x指明参数类型是为Int 函数用法 通过传统方法调用函数: val result=double(2) 可以通过. 调用成员函数 Sample().foo() Sample()是Sample类的一个实例 Infix符号 当满足如下条件的时候函数被中缀表示法调用: 函数为成员函数或扩展函数 函数只有一个参数 函数用infix关键字标记 //Int的扩展函数 infix fun

Kotlin学习随笔一 - 简单需求和项目初始化

Kotlin是对Java的一个简练的封装,提供了很多便利性的语法,熟练使用后,会大大缩减代码的行数,提高编码的速度. 具体Kotlin的优劣,网上很多评论,有兴趣的可以去看看,我们开始我们简单的demo开发. 需求:最简单的用户的CRUD,提供REST服务 开发工具:IDEA Java框架:Springboot 数据库:Mysql ORM:Hibernate JPA 好,下面来感受一下Kotlin的魅力,首先我们用IDEA新建一个基于Kotlin的Springboot项目,Kotlin是Inte

Google App Engine 学习和实践

这个周末玩了玩Google App Engine,随手写点东西,算是学习笔记吧.不当之处,请多多指正. 作者:liigo,2009/04/26夜,大连 原创链接:http://blog.csdn.net/liigo/archive/2009/04/26/4127055.aspx 转载请注明出处:http://blog.csdn.net/liigo 一,怎么想起来玩Google App Engine了呢? 近期想写一个小程序,以便在公司的电脑和家里的电脑之间随时共享数据.但是没有现成的server

马哥学习笔记二十四——分布式复制快设备drbd

DRBD: 主从 primary: 可执行读.写操作 secondary: 文件系统不能挂载 DRBD: dual primay, 双主(基于集群文件系统的高可用集群) 磁盘调度器:合并读请求,合并写请求: Procotol:drbd数据同步协议 A: Async, 异步  数据发送到本机tcp/ip协议栈 B:semi sync, 半同步  数据发送到对方tcp/ip协议 C:sync, 同步  数据到达对方存储设备 DRBD Source: DRBD资源 资源名称:可以是除了空白字符外的任意