为什么"返回"会在Kotlin中返回"回归"?

Wil*_*zel 12 java return kotlin

这个问题可能听起来很愚蠢,但其中没有错字.

fun test(): Any {
    return return true
}
Run Code Online (Sandbox Code Playgroud)

这在Kotlin实际上是可能的.虽然编译器警告说

无法访问的代码

对于外部回归.但这只是一个警告.

我不想将Java与Kotlin进行比较,但我感兴趣的是它是否适用于Java.

public class Test {
  // ...
  static int test() {
    return return 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

它不是!

/Test.java:8:错误:非法启动表达式
      返回1;
                 ^
/Test.java:8:错误:没有语句
      返回1;
                           ^
2错误

为什么Kotlin这样设计?

zsm*_*b13 16

return是Kotlin中的一个表达式,其返回类型Nothing为所有其他类型的子类型.例如,这使您能够以类型安全的方式执行此操作,而无需额外的null检查:

fun getInt(): Int? = ...

fun printInt() {
    val int: Int = getInt() ?: return
    println(int)
}
Run Code Online (Sandbox Code Playgroud)

类型getInt() ?: return可以在Int这里,因为这是Elvis运算符两边最接近的常见超类型,这要归功于Nothing它的子类型Int.

同样的事情适用于throw您,您也可以使用Elvis运算符整齐地指示您要取消对null值的执行,而不必担心以后的类型.

这导致了奇怪的怪癖

fun x(): Int {
    return return throw return throw throw return 0
}
Run Code Online (Sandbox Code Playgroud)

是有效的语法,因为该Nothing类型使每个表达式从右到左有效读取.实际发生的是return 0将执行,并且永远不会达到其余代码,正如编译器警告的那样.

  • 实际上最后一部分 `throw throw return 0` 没有被标记为无法访问 (2认同)

s1m*_*nw1 9

因为该return语句是一个返回的表达式Nothing.因此,以下还编译:

fun main(args: Array<String>) {
    val r = return
}
Run Code Online (Sandbox Code Playgroud)

它在文档中说明:

Kotlin有三个结构跳转表达式:

  • return.默认情况下,从最近的封闭函数或匿名函数返回.[...]

所有这些表达式都可以用作较大表达式的一部分:

val s = person.name ?: return
Run Code Online (Sandbox Code Playgroud)

这些表达式的Nothing类型是类型.

既然Nothing是任何其他类型的子类型,它有能力制作奇怪的陈述,就像你问题中的陈述一样有效,尽管它们看起来非常错误......

在KotlinConf上实际上有一个有趣的话题,看看有趣的事情,如下所示:

fun getText(): String {
  val s = return throw return "Hello"
}

println(getText())
//prints "Hello"
Run Code Online (Sandbox Code Playgroud)