Ответ
Nothing в Kotlin — это тип, который означает "никогда не завершается нормально". Используется в случаях:
- Функции, которые всегда выбрасывают исключение:
fun fail(message: String): Nothing {
throw IllegalStateException(message)
}
- Бесконечные циклы:
fun infiniteLoop(): Nothing {
while (true) {
println("Running...")
}
}
- В качестве аргумента для обобщенных типов, когда нужно указать, что возврата не будет:
fun <T> emptyList(): List<T> = throw Exception()
// Более точно:
fun <T> emptyList(): List<T> = fail("Empty")
- В ветках
whenилиif, которые должны охватывать все случаи, но не возвращают значение:
val result = when (value) {
is String -> value.length
else -> throw Exception() // Тип Nothing
}
Nothing помогает компилятору понять, что выполнение не продолжится после вызова, что полезно для анализа потока управления.
Ответ 18+ 🔞
Давай разберемся с этим Nothing, а то народ пугается, как чёрт ладана. Представь себе тип, который говорит: "всё, приехали, дальше пути нет". Это не null, это даже не "ой, ошибка". Это полный, окончательный тупик.
Вот смотри, зачем эта штука нужна.
Первое — функции, которые навсегда уходят в запой. Ну, то есть всегда кидают исключение или впадают в бесконечный цикл. Компилятору надо как-то пометить, что отсюда возврата нет.
fun fail(message: String): Nothing {
throw IllegalStateException(message) // Всё, приплыли. Возвращаться не планирую.
}
Или вот, классика — вечный двигатель:
fun watchServerLogs(): Nothing {
while (true) {
println("Всё ещё жив...") // И так до скончания времён, ёпта.
}
}
Второе — хитрый трюк с дженериками. Допустим, у тебя есть функция, которая по идее должна вернуть список List<T>, но по факту она всегда сдохнет. Чтобы не врать компилятору, мы говорим: "окей, в теории я верну List<T>, но на практике это будет Nothing".
fun <T> iWillNeverWork(): List<T> = throw RuntimeException("Да пошло оно всё")
// Но элегантнее так:
fun <T> iWillNeverWorkProperly(): List<T> = fail("Забей, не будет тут списка")
Третье — когда надо успокоить компилятор в when или if. Он иногда паникует: "а вдруг не все ветки покрыты, а?". А мы ему подсовываем Nothing в else — и он сразу успокаивается, понимая, что сюда выполнение всё равно не дойдёт.
val length = when(value) {
is String -> value.length // Вот тут всё ок
else -> throw Exception("Не, это не строка") // А тут — Nothing. Всё, точка, конец света.
}
В чём прикол-то? А в том, что Nothing — это подтип всех других типов в Котлине. Звучит как ересь, но это гениально. Потому что если функция объявлена как возвращающая Nothing, то её результат можно подставить куда угодно: и в String, и в Int, и в твой кастомный класс УльтраМегаДвигатель. Компилятор знает, что выполнение всё равно прервётся, так что ему похуй на несоответствие типов. Волнение ебать, нулевое.
Короче, Nothing — это не ошибка, это заявление о намерениях. Явная пометка в коде: "здесь дорога обрывается, готовь парашют". Очень полезная штука для анализа потока управления, чтобы умный компилятор не дрочил тебя лишними предупреждениями и понимал, когда можно смело считать код недостижимым.