可空性(空安全)
- 帮助解决NullPointerException , 解决问题的方法:把运行时错误转变成编译期错误 ;
- Kotlin通常要求你在构造方法中初始化所有属性,如果某个属性是非空类型,你就必须提供非空的初始化值,否则你就必须使用可空类型;
- Kotlin对可空类型的显式支持 ,允许在程序中指出哪些变量和属性允许为Null,如果一个变量为null,那么对它的调用就是不安全的;
- 在传递参数的过程中,可空类型的值不能传递给非空的参数;
- 允许变量为null : ?
- 没有问号的类型表示这种类型的变量的不能存储Null引用,说明所有常见类型默认都是非空的;
- 如果一个可空类型的值,对它的操作会受到限制(需要使用?.或者!!.或者使用if null来判断)调用,也不能把它赋值给非空类型的变量;
- 什么叫类型? 类型就是数据的分类,决定了该类型可能的值,以及该类型的值上可以完成的操作;
- Java对可控性的检查: @Nullable and @NotNull , Java8引入了Optional类型的特殊包装类型
- 安全调用运算符: ?. 该符号只会调用非空值的方法或属性
- 替代null的默认值(Elvis运算符): ?: 接受收两个运算数,不为Null就是第一个运算数,为Null就是第二个;经常和?.符号一起使用;
特殊的使用场景: ?:的右边返回一个异常throw…
- 安全转换 as? 常规的转换类型符 as
常见的模式: 安全转换和Elvis运算符结合
- 非空断言 !!. 把任何值转换成非空类型,如果为Null则抛出异常
- let函数
结合安全调用的语法,可以把调用它的对象变成lambda表达式的参数;它能有效的把调用let函数的可空对象,转变成非空类型; 如果为null则不会执行lambda,不会抛出异常;**如果在一个可空类型上直接调用let函数,而没有使用安全调用符,那么lambda的实参将会是可空的,会提示错误;
- 延迟初始化:lateinit ,所有延迟初始化的属性都是var ;
- 可空类型的扩展 允许接收者为null的(扩展函数)的调用;
String类型的扩展函数 :- isEmpty (检查字符串是否是一个空的字符串"") 【String类型的接收者】
- isBlank(判断字符串是否是空的或者是它只包含空白字符)【String类型的接收者】
- isEmptyOrNull 【String?类型的接收者】会处理可能的Null值
- isBlankOrNull【String?类型的接收者】会处理可能的Null值
定义一个可空类型的扩展函数的时候,需要在函数中显式地检查可控性;
- 类型参数的可空性:Kotlin中所有泛型和泛型函数的类型参数都是可空的;
要使类型参数非空,必须要为它指定一个非空的上界;
- 可空性与Java
平台类型:平台类型的本质就是Kotlin不知道可空性信息的类型,既可以把它当作可空类型处理,也可以把它当作非空类型处理;需要自己处理可空性;
在Kotlin中重写Java方法时,可以选择把参数和返回值类型定义成可空的,也可以定义成非空的;
基本数据类型和其他数据类型
- Kotlin不区分基本数据类型和包装类型;可以对一个数字类型的值直接调用方法;
基本数据类型不能存储Null
Kotlin的处理方式:在大多数情况下——对于变量,属性,参数和返回类型,Kotlin的Int类型会被编译成Java基本数据类型int, 唯一不可行的例外是泛型类,比如集合,这个时候基本数据类型会被编译成对应的Java的包装类型; - 可空的基本数据类型及其他 : Int? , Boolean? …在Java中对应Integer, Boolean类…
- 数字转换
Kotlin不会自动地把数字从一种类型转换成另外一种,即使是转换成范围更大的类型;
转换必须是显式的
每一种基本数据类型(Boolean除外)包括字符串,都定义有转换函数:toByte(), toShort(), toChar()…既可以把小范围转换到大范围,也可以把大范围转换成小范围; - 根类型:Any , Any?
Any类型(非空类型)是Kotlin所有非空类型的超类型(非空类型的根),包括基本数据类型;注意:不可持有null值;
如果需要可以持有任何可能值的变量,包括null在内,必须使用Any?类型;
Kotlin中所有的类都包含三个方法:toString(), equals(), hashCode() - Unit类型:Kotlin的void
Kotlin中的Unit和Java中的void的区别?Unit是一个完备的类型,可以作为类型参数,而void不行;
- Nothing类型:“这个函数永不返回”
Nothing类型没有任何值,只有被当作函数返回值 使用或者被当作泛型函数返回值的类型参数使用才会有意义;
**知道函数永远不会正常终止:- 抛出带有特定消息的异常来让当前测试失败;
- 一个包含无限循环的函数永远不会成功地结束;**
集合和数组
- 可空性和集合:
Kotlin完全支持类型参数的可空性
List<Int?> () 集合可以持有Int类型或者null
注意:变量自己的可空性和用作类型参数的类型的可空性是有区别的;
- 只读集合与可变集合
Kotlin的集合设计和java不同的另一项重要特质是:Kotlin把访问集合数据的接口和修改集合数据的接口分开 ;
kotlin.collections.Collection 该接口可以遍历集合中的元素、获取集合的大小、判断集合中是否包含某个元素;
但是该接口中没有任何添加和移除元素的方法;
kotlin.collections.MutableCollection接口可以修改集合中的数据;
注意:- 只读集合不一定是不可变的;
- 只读集合并不总是线程安全的;
- 只读集合不一定是不可变的;
- Kotlin集合和Java
- 对象和基本数据类型的数组
创建数组的方法:- arrayOf(vararg elements: T)
- arrayOfNulls(size : Int) 创建给定大小的数组,包含的是null元素
- Array构造方法 Array(size){ index -> }
把存储在集合(list, set)中的数据转换到数组:toTypedArray()
Array 包含装箱整型的数组
创建没有装箱的基本数据类型的数组:IntArray, ByteArray, CharArray, BooleanArray等,这些类型会被编译成普通的的Java基本数据类型,比如int[] , byte[]
数组支持的操作:
- 基本操作(获取数组的长度,获取或者设置元素);
- 支持和集合相同的扩展函数(filter, map等)这些方法的返回值是列表不是数组;
- forEachIndexed按照下标进行循环