Почему "возвращение" возвращает "возвращение" в Котлин?

Вопрос может звучать глупо, но в нем нет опечатки.

fun test(): Any {
    return return true
}

Это действительно возможно в Котлине. Хотя компилятор предупреждает о

Недоступный код

для внешнего возврата. Но это всего лишь предупреждение.

Я не хочу сравнивать Java с Kotlin, но мне было интересно, будет ли то же самое работать на Java.

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

Это не так!

/Test.java:8: ошибка: незаконный запуск выражения
      return return 1;
                  ^
/Test.java:8: ошибка: не утверждение
      return return 1;
                            ^
2 ошибки

Почему Котлин разработал этот способ?

Ответ 1

return является выражением в Kotlin, с типом возвращаемого значения Nothing, типом, который действует как подтип всех других типов. Это позволяет вам, например, делать это безопасным способом и без дополнительных строк null проверяет:

fun getInt(): Int? = ...

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

Тип getInt() ?: return может быть Int здесь, потому что тот самый близкий общий супертип двух сторон оператора Элвиса, благодаря Nothing является подтипом Int.

То же самое относится и к throw, которое также можно использовать с оператором Elvis, чтобы указать, что вы хотите отменить выполнение по значению null, не беспокоясь о типах позже.

Это приводит к нечетной причуде, где такие вещи, как

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

являются допустимым синтаксисом, потому что тип Nothing делает каждое из выражений действительным, читаемым справа налево. На самом деле произойдет то, что return 0 будет выполняться, а остальная часть кода никогда не будет достигнута, как предупреждает компилятор.

Ответ 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"