kotlin基础知识七: kotlin类型系统(type system)

一、为空性(Nullability)

Kotlin类型系统的为空性(Nullability)可能帮助你避免NullPointerException错误,比如"An error has occurred: java.lang.NullPointerException"或者"Unfortunately, the application X has stopped",现代语言(包括kotlin在内)的解决方法是把这些问题由运行时错误(runtime errors )转变为编译时错误(compile-time errors)。

1.1 可空类型(Nullable types)

Kotlin显式支持nullable types, 这是Kotlin与Java类型系统的第一个、可能也是最重要的不同点。Kotlin中的nullable类型和non-null类型是不同的。
举例:

fun strLen(s: String) = s.length

如果调用strLen(null)就会报错。

>>> strLen(null)
ERROR: Null can not be a value of a non-null type String
image.png

注意:nullable类型和non-null类型的对象在运行期是一样的,一个nullable类型并不是对non-null类型的wrapper,所有的checks都是在编译期执行的,因此在kotlin中使用nullable类型是没有运行期开销(runtime overhead)的。

1.2 Safe call 操作符: “?.”

表达式s?.toUpperCase()等价于if (s != null) s.toUpperCase() else null.


image.png

多个Safe call操作符的链式调用:

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 {
    return company?.address?.country ?: "Unknown"
}

fun main(args: Array) {
    val person = Person("Dmitry", null)
    println(person.countryName()) //null
}

1.3 Elvis操作符: “?:”

含义:为null提供一个默认值,它是Java中三元运算符的一个缩写。
举个例子:

fun strLenSafe(s: String?): Int = s?.length ?: 0

等价于Java的

int strLenSafe(String s) {
    return s != null ? s.length : 0;
}

也可以在Evlis操作符也可以与抛出异常结合使用。

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 printShippingLabel(person: Person) {
    val address = person.company?.address
        ?: throw IllegalArgumentException("No address")
    with (address) {
        println(streetAddress)
        println("$zipCode $city, $country")
    }
}

fun main(args: Array) {
    val jetbrains = Company("JetBrains", null)
    val person = Person("Dmitry", jetbrains)
    printShippingLabel(person)
}

输出:
Exception in thread "main" java.lang.IllegalArgumentException: No address

1.4 Safe casts操作符:“as?”

image.png

举例:
使用safe cast实现equals方法

class Person(val firstName:String, val lastName:String) {
    override fun equals(other: Any?): Boolean {
        val otherPerson = other as? Person ?: return false

        return otherPerson.firstName == firstName &&
                otherPerson.lastName == lastName
    }
}

1.5 Not-null assertions:“!!”

image.png

使用非空断言其实是告诉编译器:
“I know the value isn’t null, and I’m ready for an exception if it turns out I’m wrong.”

二、类型参数的为空性

2.1 处理可为空类型的参数

class MyService {
    fun performAction(): String = "foo"
}

fun  printHashCode(t: T) {
    println("type: " + t + ", hashCode: " + t.hashCode())
}

fun main(args: Array) {
    val myService: MyService? = null
    printHashCode(myService) //"T" is inferred as "Any?".
}

输出结果:
type: null, hashCode: 0

2.2 处理非空类型的参数

class MyService {
    fun performAction(): String = "foo"
}

//“T” can’t be nullable.
fun  printHashCode(t: T) {
    println(t.hashCode())
}

fun main(args: Array) {
    val myService: MyService? = null
    printHashCode(myService) //compile-error: Type mismatch: inferred type is MyService? but TypeVariable(T) was expected
}

Any和Any?: the root types

Any是所有类型的父类型,包括原始类型(primitive type)在内。
注意Any是一个非空类型(non-nullable type),也就意味着它不能持有null,如果需要的话,需使用Any?。
举例:

val answer: Any = 42 //42会被自动装箱(automatically boxed), 因为Any是一个引用类型.

Unit: kotlin中的void

Nothing

你可能感兴趣的:(kotlin基础知识七: kotlin类型系统(type system))