Kotlin 学习笔记06

210 阅读5分钟

Kotlin的类型系统

可空类型 需要显式的指出那些是可以为空的类型

fun strLength(string: String) = string.length
//调用
strLenght(null)//这样调用,IDE会报错,因为函数声明的是不可空类型

如果可可以传入null类型的需要在类型后面加?应该这样

fun strLength(string: String?) = string.length//报错

如果是可空类型不能直接调用调用其方法,需要经过if判断,或者(?.)判断又或者!!断言比如上面的例子应该这样调用

fun strLength(string: String?) = string?.length//如果为空则会返回null

类型的定义

什么是类型?
为什么变量拥有类型?
类型就是数据的分类,决定了该类型可能拥有的值,以及能调用的方法

安全调用运算符 ?.

foo?.bar() //等价于
if(foo!=null) bar() else null

图解

Elvis运算符 ?:

当你值为空时候不想返回null值使用

val f = foo?:bar

elivs云算符经常和安全云算符一起调用,比如:

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

fun printShoppingLabel(person: Person){
    person.company?.address?:throw IllegalArgumentException("No city")
}

安全转换云算符 as?

class Person(private val firstName: String, private val lastName: String) {
    override fun equals(other: Any?): Boolean {
        val person = other as? Person ?: return false //直接返回
        return person.firstName == firstName && person.lastName == lastName
    }

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

非空断言 !!

let 函数

处理可空表达式更容易 当我们需要把一个可空类型传递给一个非空类型

fun sendEmail(name: String) = {}

val email: String?
sendEmail(email)//报错

正确的做法

val email: String? = "Kotlin@yy.com"
email?.let { sendEmail(it) } 

当需要检查多个值是否为空,可以用嵌套多个let,不过推荐使用if,因为简洁

延时初始化属性

比如:在JUnit中

class MyTest {
    private var myService: MyService? = null //这里看起来很多余
    @Before
    fun setUp() {
        this.myService = MyService() //JUnit 要求需要把初始化的属性放到 @Before注解里面
    }
    fun testAction() {
        myService!!.performClick() //不需要检测null直接访问属性
    }
}

这里可以用lateinit 延迟初始化

private var myService: MyService

可空类型的拓展

比如String?函数 可以直接调用 isEmpty() 或者 isBlank()方法判断是否为空类型
这里使用的就是拓展函数 自己也可以定义一个拓展函数,isEmptyOrNull()isNullOrBlank()

fun String?.isEmptyOrNull(): Boolean = this == null || this.isEmpty()

//调用
var lateinit email:String?
if(email.isEmptyOrNull){
    /**do something**/
}

类型参数的可空性

kotlin中,所有泛型参数或者泛型类型都是可空类型

fun <T> printHandler(t: T) {
    print(t.hashCode())
}   
//如果是1.3以下标准库这里会报错,
//1.3kotlin标准库已经对Any类进行了拓展,不会报错 
//如下
@SinceKotlin("1.3")
@InlineOnly
public inline fun Any?.hashCode(): Int = this?.hashCode() ?: 0

可空性和Java识别

Java是不支持可空类型的,这里主要通过Java中的注解识别可空的类型 @Nullable String 会被Kotlin识别为String? @NotNull String => String

Java Kotlin
@Nullable String String?
@NotNull String String

在Kotlin处理Java类型,可以是可空也可以处理成非空类型

使用Java API需要注意,大部分库都没有注解可空性,所有类型都解释为非空,会容易出错。

interface StringProcress{
    void procress(String value)
}

使用Kotlin重新上面Java代码

class StringPrinter: StringProcress{
    @Override procress(value: String){
        println(value)
    }
}
class StringPrinter: StringProcress{
    @Override procress(value: String?){
        if(value!=null){
            println(value)
        }
    }
}

用Kotlin调用Java方法,需要自己判断类型是否为可空类型

基本数据类型和其他类型

Kotlin并不区分基本类型和他们的包装类型

  • 基本数据类型:Int、Boolean及其他
    Kotlin和Java对应的数据类型
类型 Kotlin Java
整数类型 Byte、Short、Int、Long
浮点数据类型 Float、Double
字符类型 Char
布尔类型 Boolean

可空的基本数据类型

Kotlin中可空类型不能使用Java的基本数据类型表示,因为null只能被存储到Java的引用类型变量中。这意味着任何时候使用了基本数据类型的可空版,就会编译成对应的包装类。

数字转换

  • Kotlin不会自动把一种数据类型转换成另外一种。如果是转换成范围更大的类型需要手动转换,比如:
val i = 1
val i: Long = 1 //报错

vali = 1
val i: Long = i.toLong() //另外听过了toByte() toInt() toChar()等

基本数据类型书面值

类型 类型 字面值 例子
Long 后缀L 123L
浮点数Double 字面值 0.12、2.0
Float 后缀F 123.4F 123.4f
16进制 前缀0x 0xCAFEBABE
2进制 前缀0b 0x000000101

Any Any?根类型

和Object作为Java类层级结构差不多
把基本类型赋值给Any会自动装箱,跟Java一样。

val num: Any = 3 //这里会自动装箱

Unit类型:Kotlin的“void”

fun f():Unit{/**空返回值**/}

Unit类型和Java中“void”的区别:Unit可以作为参数类型,void不能作为参数类型


集合和数组

  • 可空值得集合 遍历使用filterNotNull
list.filterNotNull()
  • 只读集合与可变集合 Kotlin集合把访问集合数据接口和修改集合数据接口分开。 Collection 只读 MutableCollection 可写
    如下图显示

通常只需要使用只读接口,只需要在代码需要修改集合的地方使用可变集合 就像val和var分开一样
只读接口不一定是不可变的 比如:
两个不同的引用,一个只读、一个可变,指向同一个集合对象 当并行的运行了这样的代码有可能会发生concurrentModificationExcepiton错误, 只读集合并不总是线程安全的

  • Kotlin集合和Java
    Kotlin中集合的层级关系:

创建集合:

集合类型 只读 可变
List listOf mutableListOf、arrayListOf
Set setOf mutibleSetOf、hashSetOf、linkedSetOf、soredSetOf
Map mapOf mutibleMapOf、hashMapOf、linkedMapOf、soredMapOf
  • 作为平台类型的集合(Kotlin把定义在Java代码中的类型看出平台类型) 在Kotlin中需要考虑
  1. 集合是否可空?
  2. 集合中元素是否可空?
  3. 你的方法会不会修改集合?
  • 对象和基本数据类型的数组

End