Kotlin核心编程-类型系统

1.Java如何解决NPE问题

  • 函数内对于无效值,更倾向于抛异常处理。
  • 采用 @NotNull/@Nullable 标注。
  • 使用专门的 Optional 对象对可能为 null 的变量进行装箱。

2.Java8 中的 Optional

  • Optional 提供了 map、flatMap、filter等方法,帮忙从对象中提取信息。
  • Optional 是一个包含类型 T 引用的泛型类,在使用的时候多创建了一次对象,有性能问题。

3.Kotlin的可空类型:在任何类型后面加上 ?

  • 安全的调用 ?.
  • Elvis操作符 ?:
  • 非空断言 !!.
  • Kotlin如何实现类型的可空性:在方法参数上标注了 @Nullable,在实现上采用 if..else 对可空情况进行判断。

let的概念:调用某对象的 let 函数,该对象是作为函数的参数,在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定 return 表达式。

public inline fun  T.let(block: (T) -> R): R = block(this)

4.类型检查:Kotlin 使用 is 代替 instanceof。

5.智能类型转换

Smart Casts 可以将一个变量的类型转变为另一种类型,它是隐式完成的。当类型需要强制转换时,可以使用 as 操作符实现。

6.Any:非空类型的根类型;Any?:所有类型的根类型

7.Nothing 与 Nothing?

Kotlin类型层级结构的最底层是 Nothing 类型。Nothing 类型的表达式不会产生任何值。任何返回值为 Nothing 的表达式之后的语句都是无法执行的。

8.自动装箱与拆箱

  • Kotlin 中的 Int 类型等同于 int;
  • Kotlin 中的 Int? 等同于 Integer。

9.“新”的数组类型

Kotlin 中 Array 并不是一种原生的数据结构,而是一种 Array 类,甚至可以将 Kotlin 中的 Array 视作集合类的一部分。

10.泛型:类型安全的利刃

泛型有以下几点优势:

  • 类型检查,能在编译时检查出错误;
  • 更加语义化;
  • 自动类型转换,获取数据时不需要进行类型强制转换;
  • 能写出更加通用化的代码。

11.在Kotlin中使用泛型:

12.类型约束:设定类型上界

Java 使用 extends 关键字,而 Kotlin 使用 : 实现类型泛型约束。

13.泛型的背后:类型擦除

Q:为什么Java无法声明一个泛型数组?
A:原因是数组是协变的,而List是不变的。简单来说,就是 Object[] 是所有对象数组的父类,而 List 却不是 List 的父类。

Q:为什么在Kotlin和Java中泛型通过擦除实现?
A:原因是需要向后兼容,在编译后擦除泛型类型,在代码中强制类型转换。

Q:如何在运行时获取泛型类型参数?
主动指定参数类型;
使用匿名内部类。

Q:为什么匿名内部类能在运行时获取泛型参数类型?
A:泛型类型擦除并不是真的将全部的类型信息擦除,还是会将类型信息放在对应class的常量池中。

Q:为什么内联函数可以获取泛型类型?
A:Kotlin中的内联函数在编译的时候编译器会将相应函数的字节码插入调用的地方,即参数类型也会被插入字节码中,因此可以获取参数类型。

14.支持协变的List

在定义的泛型类和泛型方法的泛型参数前面加上 out 关键词,说明这个泛型类及泛型方法是协变,简单来说类型A是类型B的子类型,那么 Generic 也是 Generic 的子类型。

支持协变的List只能读取,不可以添加。

15.支持逆变的Comparator

跟 out 一样,关键字 in 使泛型支持逆变。如果类型A是类型B的子类型,那么 Generic 反过来是 Generic 的子类型。

16.协变和逆变

协变 逆变 不变
Kotlin 实现方式:,只能作为消费者,只能读取不能添加 实现方式:,只能作为生产者,只能添加,读取受限 实现方式:,既可以添加,又可以读取
Java 实现方式:,只能作为消费者,只能读取不能添加 实现方式:,只能作为生产者,只能添加,读取受限 实现方式:,既可以添加,又可以读取

你可能感兴趣的:(Kotlin核心编程-类型系统)