【问题标题】:Why can "return" return a "return" in Kotlin?为什么在 Kotlin 中“return”可以返回一个“return”?
【发布时间】:2018-06-26 20:48:21
【问题描述】:

这个问题听起来很傻,但里面没有错字。

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?

【问题讨论】:

  • Kotlin 是基于表达式的,所以大多数东西都是表达式,可以用作其他表达式的参数,包括return。 Java是基于语句的,所以很多东西都是只能出现在顶层的语句。近年来,基于表达式的语言似乎出现了(非常偶然,恕我直言)趋势。

标签: java return kotlin


【解决方案1】:

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

fun getInt(): Int? = ...

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

getInt() ?: return 的类型在这里可以是 Int,因为这是 Elvis 运算符两侧最接近的公共超类型,这要归功于 NothingInt 的子类型。

同样的事情也适用于throw,您也可以巧妙地将其与Elvis 运算符一起使用,以指示您想取消对null 值的执行,而不必担心以后的类型。

这导致了一个奇怪的怪癖,比如

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

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

【讨论】:

  • 其实最后一部分throw throw return 0没有标记为不可访问
  • 其他Nothing 类型表达式为continuebreak
【解决方案2】:

因为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"

【讨论】:

  • 我知道“return”返回Nothing,这就是编译器说“Unreachable code”的原因。
  • 那么如果你已经明白了,你的问题到底是什么?
  • @SilvioMayolo 我知道我通常可以返回 Nothing,但这并不能解释为什么 return 本身应该返回 Nothing。另一方面,能够在表达式中使用 return 听起来是一个合理的解释。
  • @WilliMentzel 密切关注“使当前函数返回给定值”和“计算给定值”之间的区别。表达式return 1 的计算结果为Nothing,并且作为副作用,使当前函数返回值1。鉴于副作用的性质,任何代码都无法观察到评估 return 表达式的结果。
猜你喜欢
  • 1970-01-01
  • 2014-04-24
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 2022-12-09
  • 1970-01-01
  • 2012-03-26
  • 2011-04-07
相关资源
最近更新 更多