这两种类型都Unit
表示Nothing
一个不返回任何内容的函数。他们之间有什么区别?
4 回答
Unit
是一种只有一个值的类型 - 请参阅Unit type。另一方面,Nothing
没有可能的值 - 请参阅底部类型。
不返回任何内容的函数必须具有返回类型Unit
。如果是,Nothing
则该函数无法返回结果。退出函数的唯一方法是通过异常。
Nothing
以不同的方式使用。它具有两个特性:
Nothing
是所有其他类型(包括Null
)的子类型。- 不存在这种类型的实例。
这什么时候有用?考虑None
:
object None extends Option[Nothing]
因为Option
它的类型参数是协变的,并且Nothing
是一切的子类型,是每个类型Option[Nothing]
的子类型。因此,我们可以创建一个对象,它是for each 的子类型。这是合理的,因为无法实例化,所以总是没有值。相似地Option[A]
A
None
Option[A]
A
Nothing
Option[Nothing]
object Nil extends List[Nothing]
Unit
对应于逻辑真,Nothing
对应于Curry-Howard 同构下的逻辑假,我们将类型视为命题,将函数视为证明,.
Unit
意味着(a)函数具有输入和输出等副作用,(b)这些副作用是函数的主要目标。当然,即使函数的类型不同于Unit
.
Nothing
是 Scala 中的一种特殊类型,因为 (a) 它没有值(Unit 只有一个值 - ()
),所以您不能返回 type 的值Nothing
,并且 (b) 它是所有其他类型的子类型。这意味着如果某物具有 type Nothing
,则可以使用它来代替任何其他类型(通过子类型化),但不会产生任何结果。这对于处理异常很有用——throw
表达式的类型为Nothing
,因此它可以在程序中的任何地方使用。
简而言之,Nothing
意味着程序发生错误或终止并且没有返回任何内容,而Unit
意味着有副作用,但执行正常结束而没有结果。
Scala 中的编程对此有很好的解释。
在 Petr 的回复中添加一个方面:Nothing
在类型层次结构中起着重要作用。是底型。这意味着它是所有其他类型的子类型,就像 的对立面一样Any
,它是一切的超类型。你可以在这里找到一个很好的解释。
单元
单位与Java的void相同。Java 中的 void 是关键字,但 Unit 在 Kotlin 中是对象。
现在如果一个函数在 Kotlin 中返回 Unit,这意味着它没有返回任何有意义的东西,该函数只是执行了一堆代码并返回了执行流程。
没有什么
没有什么是完全不同的。您无法将它与 Java 中的任何内容联系起来。在java中没有什么比如Nothing。
什么都没有意味着执行的结束。如果一个函数返回 Nothing,则意味着它实际上没有返回任何内容。甚至没有执行流程。
没有什么比得上黑洞,任何进去的东西都出不来,甚至连光也没有(光在这里是“执行流”)。在 Unit 的情况下,发出的光最少。
因此,如果一个函数返回 Nothing,则代码流到此结束,之后编写的任何内容都是Unreachable。
现在看下面的代码,
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 的内容,这意味着我们没有任何内容会影响执行流程并且永远不会返回它背部。一切都返回一些东西,甚至 Unit 也是一些东西。
现在,可以说 Nothing 是一个类,因此我们可以将其作为对象并返回它本身。唔唔唔唔?一个大的nohhh?
没有任何类有一个构造函数,但它是私有的,所以你甚至不能为它创建一个对象。
最后一点
在后台,Unit在反编译的字节码中被转换为void(small v),而Nothing被转换为Void(capital V)。
看下面的代码,
var user = null //First
var user : User? =null //Second
这里,第二条语句显示了 Nullable-User 类型的用户。第一条语句的用户类型是什么?
有什么猜测吗?
它是Nullable-Nothing类型。
尝试将第一个语句视为
var user : Nothing? = null
现在引擎盖下发生了什么,
Void user = (Void)null; //First
User user = (User)null; //Second