Что такое оператор двойного взрыва (!!) Kotlin?

178

Я конвертирую Java в Kotlin с помощью Android Studio. Я получаю двойной удар после переменной экземпляра. Что такое двойной взрыв и, что более важно, где это задокументировано?

mMap!!.addMarker(MarkerOptions().position(london).title("Marker in London"))
mbr_at_ml
источник

Ответы:

206

Это небезопасное T?преобразование типа null ( ) в ненулевой тип ( T), которое !!будет выдано, NullPointerExceptionесли значение равно null.

Это задокументировано здесь вместе со средствами нулевой безопасности Kotlin.

горячая клавиша
источник
1
что это значит, когда !!в конце утверждения? IJ val price = sale.latest!!
автоконвертировать
7
@ycomp, это означает, что sale.latestможет содержать null; назначение будет успешным, только если sale.latestоно не равно нулю, и в противном случае будет выбрасывать NPE. Это дает нулевую безопасность для val price: его тип будет ненулевым. См. Kotlinlang.org/docs/reference/null-safety.html
горячая клавиша
1
@hotkey: Так в чем же разница между получением NPE - здесь ИЛИ, когда к последнему методу обращаются к нулевому объекту?
Аада
3
@Aada, это общая проблема для отладки NPE и трудно найти строку / путь выполнения, который устанавливает значение в нуль. Это нулевое назначение может произойти в другом контексте, классе или даже дне! Используя его, !!вы можете быстро завершить работу и определить причину NPE. Я хотел бы, чтобы у Java была подобная особенность (то есть без уродливых ifзаявлений и / или assertионов).
Cascader
82

Вот пример, чтобы прояснить ситуацию. Скажем, у вас есть эта функция

fun main(args: Array<String>) {
    var email: String
    email = null
    println(email)
}

Это приведет к следующей ошибке компиляции.

Null can not be a value of a non-null type String

Теперь вы можете предотвратить это, добавив знак вопроса к Stringтипу, чтобы сделать его обнуляемым.

Итак, мы имеем

fun main(args: Array<String>) {
    var email: String?
    email = null
    println(email)
}

Это дает результат

null

Теперь, если мы хотим, чтобы функция генерировала исключение, когда значение email равно нулю, мы можем добавить два восклицания в конце письма. Как это

fun main(args: Array<String>) {
    var email: String?
    email = null
    println(email!!)
}

Это бросит KotlinNullPointerException

Альф Мох
источник
5
Итак, почему люди используют «!!» даже если это небезопасно, потому что приложение будет завершено, когда эта переменная имеет значение NULL?
Сэм
3
@ Давид, вы можете использовать его, только когда вы на 100% уверены, что переменная не равна нулю (например, вы явно проверили ее), и вам нужна переменная без нуля
FMK
7
@ ФМК Я понял, спасибо! Я понимаю, что двойной взрыв используется для того, чтобы значения переменной типа nullable могли попасть в переменную non-nullable types, верно?
Сэм
2
@ Давид да, именно так.
FMK
10

Оператор Double-Bang - отличный вариант для поклонников NullPointerException(или NPE для краткости).

Оператор утверждения not-null !! преобразует любое значение в ненулевой тип и выдает исключение, если значение равно null.

val nonNull = a!!.length

Таким образом, вы можете написать a!!, и это вернет ненулевое значение a( Stringнапример, здесь) или выбросит NPE, если aравно нулю.

Если вы хотите NPE, вы можете получить его, но вы должны явно запросить его. Этот оператор следует использовать в тех случаях, когда разработчик гарантирует - значение никогда не будет нулевым .

Энди Федоров
источник
2
На вопрос новичка: зачем мне преобразовывать любое значение в ненулевой тип?
Wolf359
4
@ Wolf359 Это позволяет вам быть на 100% уверены, что его значение не равно нулю. («Это общая проблема для отладки NPE, и ему трудно найти путь к строке / пути выполнения, который устанавливает значение в null. Это нулевое назначение может произойти в другом контексте, классе или даже дне!» от Cascader)
снижение активности