存在String,其实不存在String?这个类,这是编译器做的功课。所以?可空类型的类型系统是隐含的。
Unit也是被编译器特殊对待的,Unit作为函数返回值的话,可以不用显式返回。

Unit 和 Nothing 填补了原本 Java 当中的类型系统,让 Kotlin 的类型系统更加全面,也让大部分的“语句”可以当作“表达式”来用。

子类是从父类继承属性和方法的一个类,而继承则是实现这种子类和父类之间的关系的一种方式,它只是一种方式。String和String?是父子类关系,但不是用继承来实现的,而是靠编译器。

从Java过来Kotlin,会有一种思维,以Java的眼光来看Kotlin的类型系统,去想这个Kotlin类在Java中代表了什么。

现在我认为这是不必要的。Kotlin的抽象性,新的类型系统正是让开发者更好地写代码。它们之间的对照关系、翻译关系,了解即可。写代码时要想着Kotlin的类型系统。

Any

Any?可以看作Any的父类,虽然它们之间没有继承关系。在Kotlin基于JVM系统中,Any会被翻译为Object并根据有无“?”来加上 @Nullable@NotNull

在Kotlin类型系统中,Any是所有类型的 super class,而Any?也可以看作 Any 的父类。

Unit

Unit类在Kotlin中是一个单例。

1
2
3
public object Unit {
override fun toString() = "kotlin.Unit"
}

它的作用主要是

  1. 特殊的编译器处理。返回值为Unit不用显式返回。不用写 return
  2. 方便构建 函数式编程。让 () -> Unit 这种函数类型成为可能。

Unit? 没有什么应用场景,而且使用它还消除了 隐式return 的功能,要显式写return了。

Nothing

Nothing类是所有类型的子类,Nothing 的概念与“Any?”恰好相反。“Any?”是所有的 Kotlin 类型的父类,Nothing 则是所有类型的子类。像 Nothing 这样的概念,在函数式编程当中,也被叫做底类型(Bottom Type),因为它位于整个类型体系的最底部。

1
public class Nothing private constructor()

可以看到,Nothing的构造函数是私有的。目前据我了解,返回 Nothing的表达式只有 报错相关 的。

比如

1
2
3
4
5
fun calculate(): Nothing = throw NotImplementedError()

fun getUser(request: Request): User {
return request.user ?: error("User not found")
}

所以 Nothing 帮助编译器进行函数流程的判断,一般返回了Nothing的表达式后面的代码都不会执行。

作为返回值

指示函数永远不会正常返回,因为里面有报错语句。

1
2
3
fun calculate(): Nothing {
throw NotImplementedError()// 注释掉 或 用try/catch包住都会编译器报错
}

作为函数参数

指示该函数永远不能使用,因为无法构造 Nothing

1
2
3
4
// 这是一个无法调用的函数,因为找不到合适的参数
fun show(msg: Nothing) {
}
show(throw Exception()) // 虽然不报错,但方法仍然不会调用

Nothing?没有想到什么应用场景。

stackflow参考