Unit
和Nothing
这两种类型都表示不返回任何内容的函数。它们之间有什么区别?
答案 0 :(得分:72)
Unit
是一种只有一个值的类型 - 请参阅Unit type。另一方面,Nothing
没有可能的值 - 请参阅Bottom type。
不返回任何内容的函数必须具有返回类型Unit
。如果是Nothing
则函数无法返回结果。退出函数的唯一方法是异常。
Nothing
以不同的方式使用。它的特点是两个属性:
Nothing
是所有其他类型的子类型(包括Null
)。什么时候有用?考虑None
:
object None extends Option[Nothing]
由于Option
在其类型参数中是协变的,而Nothing
是所有内容的子类型,因此Option[Nothing]
是每种类型Option[A]
的{{1}}子类型。因此,我们可以为每个A
创建一个None
对象,它是Option[A]
的子类型。这是合理的,因为A
无法实例化,因此Nothing
将始终没有值。类似地
Option[Nothing]
object Nil extends List[Nothing]
对应逻辑true,Unit
对应Curry-Howard isomorphism下的逻辑假,我们将类型视为命题和函数作为证据,
答案 1 :(得分:20)
Unit
意味着(a)功能具有输入和输出等副作用,(b)这些副作用是该功能的主要目标。当然,即使函数的类型与Unit
不同,函数也会产生副作用。
Nothing
是Scala中的一种特殊类型,因为(a)它没有值(Unit只有一个值 - ()
),所以你不能返回类型Nothing
的值和(b)它是所有其他类型的子类型。这意味着,如果某些内容具有类型Nothing
,则可以在需要其他类型的每个位置使用它,但它不会产生任何结果。这用于处理异常 - throw
表达式的类型为Nothing
,因此它基本上可以在程序的任何位置使用。
简单地说,Nothing
表示存在错误且未返回任何内容,而Unit
表示存在副作用。
Programming in Scala对此有一个很好的解释。
答案 2 :(得分:6)
为Petr的回复添加一个方面:Nothing
在类型层次结构中扮演重要角色。这是一种底部类型。这意味着它是每个其他类型的子类型,它与Any
的相反,它是一切的超类型。你可以找到一个很好的解释here。
答案 3 :(得分:0)
单位
单位与Java的 void 相同。 Java中的void是关键字,而Kotlin中的Unit是对象。
现在,如果函数在Kotlin中返回Unit,则意味着它不返回任何有意义的东西,该函数仅执行一堆代码并返回执行流。
没什么
没有什么是完全不同的。您无法将其与Java中的任何内容相关联。 在Java中什么都没有。
什么都不表示执行结束。如果函数返回Nothing,则实际上不返回任何内容。甚至没有执行流程。
没有什么像黑洞,没有任何东西进来,甚至没有光(这里的光是“执行流”)。在单元的情况下,最少的光会射出。
因此,如果一个函数返回Nothing,则代码流到此为止,之后写的任何内容不可达。
现在查看下面的代码,
fun main() {
unitFun()
println("after unit")
nothingFun()
println("after nothing") //you get warning here saying "unreachable code"
}
fun nothingFun(): Nothing {
println("inside nothing")
throw Exception()
}
fun unitFun(): Unit {
println("inside unit")
}
输出将为
inside unit
after unit
inside nothing
Exception in thread "main" java.lang.Exception
注意:,您在写信时会收到警告
println("after nothing") UnReachable Code
您知道原因,这是因为nothingFun甚至没有发回执行流。
要完成此操作的另一件事是,任何返回Nothing的函数都必须抛出任何类型的异常。
原因::如果您编写一些常规语句(而不抛出异常),则该函数将匹配返回类型,并且我们没有返回Nothing的任何东西,这意味着我们没有任何会吸引执行流并且永不将其返回的东西。一切都会返回某些东西,即使单位也是如此。
现在,可以说Nothing是一个类,因此我们可以使它成为对象并返回它本身。不,不?一个很大的nohhhh?
没有任何一个类具有构造函数,但是它是私有的,因此您甚至不能创建它的对象。
最后一位
在后台,单位会在反编译后的字节码中转换为void(small v),而什么都不会转换为Void(capital V)。
请参见以下代码,
var user = null //First
var user : User? =null //Second
在这里,第二条语句显示 user 为Nullable-User类型。 第一条语句的用户是什么类型?
有任何猜想吗?
这是 Nullable-Nothing 类型。
尝试将第一个语句视为
var user : Nothing? = null
现在引擎盖下发生了什么
Void user = (Void)null; //First
User user = (User)null; //Second