Kotlin类型系统竟如此简单
作者:DROID 发布时间:2021-10-15 20:05:02
Quote
在学习 Kotlin 的过程中,对 Kotlin 的类型系统产生了好奇,Kotlin 是否存在类似于 Java 中 Object 的公共基类?Kotlin 中是否也有类似于 Java 基础类型这样的单独分支?在研究一番过后,博主发现相较于 Java,Kotlin 交出了更为满意的答案,而且出乎意外地简单,只需要遵循简单的规则,便能理解整个类型系统。
Any
Any 等同于 Java 中的 Object 的概念,Any 在注释中这么写到:
The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
我们来简单验证下 Any 是一切的基类。
class Fruit
fun main(args: Array<String>) {
println(Fruit() is Any)
}
在上面的代码中,我们新建了一个类,然后构造它的实例,看它是否为 Any,答案显而易见地为 true。
我们在看一些 kotlin 中的基础类型,也就是 Int、Double、Float、Byte 等等的父类是否也是 Any。
println(3.233F is Any)
println(2 is Any)
答案也是true。这里额外地解释下,Kotlin 并没有 Java 中基础类型和封装类型差异化处理,也没有拆箱和装箱的处理。基础类型就是基础类型,但它们也以Any作为父类。
Unit
再来看看 Unit 这个 Kotlin 中的特殊东西。
/**
* The type with only one value: the `Unit` object.
* This type corresponds to the `void` type in Java.
*/
public object Unit {
override fun toString() = "kotlin.Unit"
}
在 kotlin 中每个函数一定是有返回值的。
这里说明一下概念,也将会在后续的章节里面再次提到。kotlin 为了这个一定有返回值这个概念,做了很多工作,但好处是非常明显的,我们能够以统一的视角来看待 kotlin 的函数。
Unit 这个概念表征着什么都不做,但什么都不做确实也是一种返回值。如果我们不做任何声明,函数的返回值就是 Unit,表明我返回了一个什么都没做的东西。
我们来验证一下,声明一个空函数,然后打印它。(在 Java 中会编译不过)
fun justReturn() {
}
fun main(args: Array<String>) {
print(justReturn())
}
结果输出了kotlin.Unit,证明了返回值就是 Unit。
那么这里有一个疑问,就是 Unit 和 Any 什么关系?我们通过 is 关键字来看看。
fun main(args: Array<String>) {
print(justReturn() is Any)
}
恩恩,Unit 也是 Any 的子类!
Nothing
我们继续延展下kotlin 中每个函数一定是有返回值的这个概念。前面我们看的是正常返回的情况,那如果程序发生异常,也会有返回值吗?kotlin 对于这种情况,也是延续了一定有返回值这种概念。这个返回值叫做 - Nothing!
Nothing 意味着不可达,程序实际运行时不会产生任何一个 Nothing 类型对象,啥?!这怎么理解。kotlin 一旦发现返回了 Nothing,会保证后面的代码不再执行。
所以 Nothing 常用于 throw 这样异常退出的情况,这样后续的代码就不会被执行。我们看看 kotlin 中自身的例子。
/**
* Terminates the currently running process.
*
* @param status serves as a status code; by convention,
* a nonzero status code indicates abnormal termination.
*
* @return This method never returns normally.
*/
@kotlin.internal.InlineOnly
public inline fun exitProcess(status: Int): Nothing {
System.exit(status)
throw RuntimeException("System.exit returned normally, while it was supposed to halt JVM.")
}
注意啦,我们再看看 Nothing 在类型系统中的位置。Nothing 与 Any 相反,是一切类型的子类!也就是说 Nothing,是 Fruit、是 School、是 Money、也是 Any。Nothing 意味着不可达的状态,每一种类型都包含这种不可达的状态,因而这种状态 Nothing,是这些的子类。
注意上图中 Nothing 所处的位置。
Nullable
kotlin 的一大杀手锏就是这个可空类型,一种类型后面加上?,这种类型就可以为空了。我们来看看引入可空类型过后,类型系统是怎样的。
1、首先看看普通类和可空类型之间的关系。
class Fruit
fun main(args: Array<String>) {
print(Fruit() is Fruit?)
}
答案是true,这里很好理解,两者之间的区别在于是否可以为空,可以为空的自然而然是基类,不可为空的是可以为空下的一种派生。
2、Any 是否有可空类型
kotlin 最让人欣赏的地方在于一个概念贯彻到底。Any 在 kotlin 中也是有可空类型的。感官上 Any? 是 Any 的父类,Any 是不可空类型的父类,所以 Any? 也是不可空类型的父类吗?答案就是这样的,我们来验证下。
class Fruit
fun main(args: Array<String>) {
print(Fruit() is Any?)
}
3、Unit 是否有可空类型
是的,Unit 也有空类型 Unit?。但这是一个难理解的概念,其本身包含了两个值 Unit 和 null。这是 kotlin 为了延续统一的概念,很少会有场景使用到,但咱们得清楚。
4、Nothing 是否有可空类型
Nothing 当然也有可空类型 Nothing?,其本身有且仅有一个值 null,也就是说其就是 null。Nothing 本身不可达,不会有任何一个实例,那就只能是 null 了。
我们来验证一下
fun main(args: Array<String>) {
println(null is Nothing)
println(null is Nothing?)
println(null is Any)
println(null is Any?)
}
分别是 false、true、false 和 true。
总结
这里借用下 natpryce 的图,大家看一下这张图,这就是 kotlin 的类型系统。
咱们只需要理解一下几点,就完全弄明白 kotlin 类型系统。
Any 和 Nothing 分别是所有对象的基类和子类。
可空类型是不可空类型的父类。
当我们不清楚类型时,对照上面两个概念就能明白。
参考
Mistaeks I Hav Made: A Whirlwind Tour of the Kotlin Type Hierarchy
https://proandroiddev.com/nothing-else-matters-in-kotlin-994a9ef106fc
来源:https://woaitqs.cc/2019/09/06/kotlin-class-hierarchy/


猜你喜欢
- 此篇博客实现的功能是:点击界面中的图片,跳出一个PopupWindow,PopupWindow中含有相应的文字和图标,并且在显示PopupW
- 前言公众号上有网友询问我如何生成 EMF 文件的问题:本以为非常简单,我快速给出了解决方案:var bitmap = new Bitmap(
- 下面是自己写的三个方法,直接类名.方法即可调用,注意此处未做异常处理.1.下划线转驼峰 lowerLineToHump()2.首字母大写 c
- 目录1、概念相关1.1、概念1.2、解决了什么:1.3、场景:2、简单实现2.1 代码3. netty中的责任链模式4、思考本文先介绍了责任
- 熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最
- 前言Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻
- Map简介将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。此接口取代 Dictionary 类,后者完全是一个抽象
- 使用Unity API PlayerBuildInterface.CompilePlayerScripts 将项目中的代码生成为 DLL 程
- 上一篇文章中主要讲了GridView的简单应用,以网格的形式展示了一些图片,对于图片也有点击监听操作。但是,如果我们在浏览图片的时候需要一些
- Spring Boot 2.7.6整合redis与低版本的区别最近在写程序的时候参考了之前写过的一篇文章spring boot整合redis
- 一、前言本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,
- 一. 泛型概念的提出(为什么需要泛型)?首先,我们看下下面这段简短的代码:public class GenericTest {public
- 本文实例讲述了C#实现json格式转换成对象并更换key的方法。分享给大家供大家参考。具体分析如下:由于是不标准的序列化对象类型,因此你无法
- & 按位运算符,逻辑运算符&& 逻辑运算符相同点:只要有一端为假,则语句不成立假设有三个参数int x = 1;in
- 源码:[StructLayout(LayoutKind.Explicit)] public struct IP {&nb
- 要获取Java中的当前时间戳:Timestamp timestamp = new Timestamp(System.currentTimeM
- // 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1。package demo;publ
- 本文实例为大家分享了java实现时间与字符串之间转换的具体代码,供大家参考,具体内容如下1. long字符串转换成yyyy-MM-dd HH
- 前言Java中URL传中文时乱码的问题相信不少朋友都遇到过,最近就遇到一个问题,就是在Action当中把一条中文信息绑定在URL的后面,Ac
- 使用Convert接口实现类型转换器在Spring3中引入了一个Converter接口,它支持从一个Object转为另一个Object。除了