为什么“返回”会在Kotlin中返回“回归”?

时间:2018-01-17 21:17:44

标签: java return kotlin

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

fun test(): Any {
    return return true
}

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

  

无法访问的代码

为外部回归。但这只是一个警告。

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

public class Test {
  // ...
  static int test() {
    return return 1;
  }
}

它没有!

  

/Test.java:8:错误:表达的非法开始
  返回1;
  ^
  /Test.java:8:错误:不是声明
  返回1;
  ^
  2个错误

为什么Kotlin这样设计?

2 个答案:

答案 0 :(得分:16)

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

fun getInt(): Int? = ...

fun printInt() {
    val int: Int = getInt() ?: return
    println(int)
}

此处getInt() ?: return的类型可以是Int,因为它是Elvis运算符双方最接近的常见超类型,这要归功于Nothing是其子类型Int

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

这导致奇怪的怪癖,例如

fun x(): Int {
    return return throw return throw throw return 0
}

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

答案 1 :(得分:9)

因为return语句是返回Nothing的表达式。因此,以下内容也会编译:

fun main(args: Array<String>) {
    val r = return
}

docs

中说明了这一点
  

Kotlin有三种结构跳跃表达式:

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

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

val s = person.name ?: return
     

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

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

KotlinConf实际上有一个有趣的话题,看看下面有趣的事情:

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

println(getText())
//prints "Hello"