为什么“返回”在Kotlin中返回“返回”?
这个问题可能听起来很愚蠢,但是没有错字。
fun test(): Any { return return true }
这在Kotlin中实际上是可能的。 虽然编译器警告
无法访问的代码
为外面的回报。 但这只是一个警告。
我不想比较Java和Kotlin,但我有兴趣是否可以在Java中使用。
public class Test { // ... static int test() { return return 1; } }
它不是!
/Test.java:8:错误:expression式的非法开始
返回1;
^
/Test.java:8:错误:不是一个语句
返回1;
^
2错误
为什么Kotlin是这样设计的?
return
是Kotlin中的一个expression式,其返回types为Nothing
,作为所有其他types的子types。 例如,这样可以以types安全的方式执行此操作,而不需要额外的null
行检查:
fun getInt(): Int? = ... fun printInt() { val int: Int = getInt() ?: return println(int) }
getInt() ?: return
的types可以是Int
,因为这是Elvis运算符两边最接近的常见超types,这要归功于Nothing
是Int
的子types。
同样的事情适用于throw
,你也可以使用Elvis
操作符来整齐地使用它来表示你想取消null
值的执行,而不用担心以后的types。
这导致了一个奇怪的怪事,像事情
fun x(): Int { return return throw return throw throw return 0 }
是有效的语法,因为Nothing
types使得每个expression式有效地从右向左读。 实际上会发生的是return 0
将会执行,其余的代码将永远不会被编译器警告。
因为return
语句是一个返回Nothing
的expression式。 结果,下面还编译了:
fun main(args: Array) { val r = return }
这是在文档中陈述:
Kotlin有三个结构跳跃expression式:
return
。 默认情况下从最近的封闭函数或匿名函数返回。 […]所有这些expression式都可以用作较大expression式的一部分:
val s = person.name ?: return
这些expression式的types是
Nothing
types。
由于Nothing
任何其他types的子types,它有权作出奇怪的声明,就像你的问题,有效,虽然他们似乎是非常错误的… …
在KotlinConf上实际上有一个有趣的谈话,看看下面这些有趣的事情:
fun getText(): String { val s = return throw return "Hello" } println(getText()) //prints "Hello"