Я специально прошу тип необнуляемыйNothing.
Я знаю, что Nothing? позволяет нам, например, фильтровать null, чтобы сделать перегрузку однозначной, но я изо всех сил пытаюсь придумать случаи, когда Nothing было бы полезно.
Nothing? может иметь ровно одно значение, null. Так что Nothing может не иметь абсолютно никакого значения. В чем смысл? Почему бы просто не использовать Unit?
Ответ Вилли ниже - отличный ответ. Немного математики, если вам интересно: Nothing — это тип, у которого нет значений, это пустой набор. Пустое множество (Nothing) является подмножеством все других множеств (типов). Вот почему тип Nothing присваивается всем другим типам ==> Nothing является подклассом всех других типов. ? означает «или-ноль». Вот почему тип Nothing? имеет одно значение: null (пустое множество + null).
@StreetsOfBoston Приятно видеть это с этой точки зрения :)





Nothing является аналогом Any?Точно так же, как Any? является базовым типом любого другого типа, Nothing является подтипом любого другого типа (даже тех, которые допускают значение NULL).
Зная это, становится ясно, что s будет иметь тип String в следующем примере, данное имя является String?.
val s = name ?: throw IllegalArgumentException("Name required")
Выражение throw возвращает Nothing, а общий базовый тип String и Nothing — String. Это то, что мы хотим, потому что это тип, с которым мы хотим работать.
Если бы мы использовали Unit вместо Nothing, общим базовым типом был бы Any, что, конечно, не то, что нам нужно, потому что впоследствии потребовалось бы приведение к String.
Это тоже имеет смысл, потому что, если будет выдано исключение, выполнение не может продолжаться там, поэтому s в любом случае больше не будет использоваться.
Nothing помечает места кода, которые никогда не будут доступныfun foo() {
throw IllegalArgumentException("...")
println("Hey") // unreachable code
}
Если null используется для инициализации значения предполагаемого типа и нет другой информации для определения более конкретного типа, предполагаемым типом будет Nothing?.
val x = null // 'x' has type `Nothing?`
val l = listOf(null) // 'l' has type `List<Nothing?>
Спасибо. Небольшая поправка: Any? является супертипом ВСЕХ типов, допускающих значение NULL или нет, а Nothing (не Nothing?) является подтипом ВСЕХ типов, допускающих значение NULL или нет. Не имеет смысла рассматривать типы с нулевым и ненулевым значением как две отдельные вещи, как предлагает ваша сноска.
@ User1291 Извините, если мой ответ недостаточно ясен. Вот что я имею в виду: Any является супертипом всех ненулевых типов, а Any? является супертипом ВСЕХ типов. То же самое относится и к Ничто/Ничто? а как подвид. Взгляните сюда: pl.kotl.in/SoUPnvW6E Таким образом, различие имеет смысл.
Я понял тебя с первого раза. Вы все еще ошибаетесь, когда говорите, что «Nothing? является подтипом любого другого типа». Nothing? является подтипом всех типов обнуляемый. Nothing является подтипом всех типов, не допускающих значение NULL, И подтипом Nothing? и, следовательно, подтипом всех других типов, допускающих значение NULL или нет.
Nothing используется, чтобы сообщить компилятору, что он никогда не вернется. Например,
fun main() {
var name: String? = null
val notNullName = name ?: fail("name was null")
println(notNullName)
}
fun fail(message: String): Nothing {
throw RuntimeException(message)
}
fun infiniteLoop(): Nothing {
while (true) {
// Nothingness
}
}
И какую ценность дает «сказать компилятору, что он никогда не вернется»? (Очевидно, кроме вывода типа.)
Официальные документы есть, что сказать о нем: kotlinlang.org/docs/reference/exceptions.html#the-nothing-ty ре