Kotlin百问

02

表达式和语句的差别?

  1. 表达式有返回值,语句没有
  2. 表达式可以成为另一个表达式的一部分,而语句是并列关系

延伸:
根据上述差异可知,if,when是表达式,for, while循环结构和赋值操作是语句。利用表达式有返回值,可以用来替换函数里出现的return,通过kotlin类型推导也可以省略函数返回类型的声明,或者变量的类型声明

补充:
Java中的赋值操作是表达式,赋值表达式的值等于要赋的值

在Kotlin中,不可变性体现在哪些方面?

变量声明分为:val不可变引用,var可变引用

集合声明分为:可变性集合和不可变集合,不可变集合在集合初始化的时候填充数据,不支持add/remove方法。可变性集合通过mutable打头的方法声明

成员方法默认是不能被重写的,需要方法的关键词fun前增加open关键词改变

类默认是不能被继承的,需要在class关键词前添加open关键词改变

延伸:
Kotlin上述的设计,符合Effective Java2中第15条:使可变性最小。不可变引用,不可变对象和无副作用的函数让代码更接近函数式编程

补充:
对象不可变性给编码带来如下影响:

  1. 易于逻辑维护,对象只有单一的初始化状态
  2. 满足线程安全的
  3. 构成函数式编程的要素之一
  4. 对每个不同的值都要一个单独的对象,因此有可能存在潜在的性能问题

Kotlin为什么不区分受检异常和非受检异常?

对于这个问题,我希望Kotlin能支持受检异常,王垠在这篇文章Kotlin 和 Checked Exception提到,我表示赞同。

补充:
Java异常继承体系:
第一层Throwable,

第二层:Exception, Error

Exception分为两类:受检异常(checkedException)和运行时异常(RuntimeException),运行时异常也叫非受检异常。

编程人员必须强制处理(捕获或者抛出)受检异常,不要求强制处理非受检异常(可处理也可以不处理,不处理有可能崩溃)。

常见的受检异常
Exception, FileNotFoundException, IOException, SQLException

常见的未检查异常
NullPointerException, ClassCastException, ArrayIndexsOutOfBoundsException, ArithmeticException, NumberFormatException

03

Kotlin里没有static修饰词,如何实现静态方法或者属性呢?

有两种方式实现:

  1. 顶层函数和顶层属性
  2. 类的匿名伴生对象companion object

为什么扩展函数不能被子类重写?

因为扩展函数不是真的类的成员函数,扩展函数的本质是:接收者对象作为第一个参数的静态函数,所以不能被子类重写。

增加类的能力,什么情况下使用成员函数,什么情况下使用扩展函数?

这个新增的能力只需要访问public的成员和函数,同时不想修改这个类的源代码,同时不属于成员函数的考虑范围的,使用扩展函数。比如对第三方类库的拓展
能力

需要在子类重写这个函数,把这个函数纳入到继承体系里时,使用成员函数。

什么情况需要引入局部函数?

逻辑复用的作用域只在某个函数体内时,在这个函数里定义局部函数