Co to jest operator podwójnego huku (!!) Kotlina?

177

Konwertuję Javę na Kotlin za pomocą Android Studio. Po zmiennej instancji pojawia się podwójny huk. Co to jest podwójny wybuch i co ważniejsze, gdzie jest to udokumentowane?

mMap!!.addMarker(MarkerOptions().position(london).title("Marker in London"))
mbr_at_ml
źródło

Odpowiedzi:

205

Jest to niebezpieczna T?konwersja typu ( ) dopuszczająca wartość null na typ ( T), !!która nie dopuszcza wartości null , zostanie zgłoszona, NullPointerExceptionjeśli wartość to null.

Jest to udokumentowane tutaj wraz ze środkami bezpieczeństwa zerowego Kotlin.

Klawisz skrótu
źródło
1
co to znaczy, gdy !!znajduje się na końcu oświadczenia? IJ auto-convert to Kotlin zrobił to za mnieval price = sale.latest!!
ycomp
7
@ycomp, to znaczy, że sale.latestmoże zawierać null; przypisanie powiedzie się tylko wtedy, gdy sale.latestnie jest zerowe, aw przeciwnym razie spowoduje zgłoszenie NPE. Daje to bezpieczeństwo null dla val price: jego typ będzie różny od null. Zobacz kotlinlang.org/docs/reference/null-safety.html
hotkey
1
@hotkey: Jaka jest więc różnica między pobieraniem NPE - tutaj LUB kiedy uzyskuje się dostęp do najnowszej metody na obiekcie null?
Aada
2
@Aada, debugowanie NPE jest częstym problemem i trudno jest znaleźć linię / ścieżkę wykonania, która ustawia wartość na null. To zerowe zadanie może się zdarzyć w innym kontekście, na zajęciach lub nawet w innym dniu! Używając !!możesz szybko zawieść i zlokalizować główną przyczynę NPE. Chciałbym, żeby Java miała podobną funkcję (to znaczy bez brzydkich ifinstrukcji i / lub assertjonów).
Cascader
82

Oto przykład, aby wszystko było jaśniejsze. Powiedz, że masz tę funkcję

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

Spowoduje to następujący błąd kompilacji.

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

Teraz możesz temu zapobiec, dodając znak zapytania do Stringtypu, aby nadać mu wartość null.

Więc mamy

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

Daje to wynik

null

Teraz, jeśli chcemy, aby funkcja rzucała wyjątek, gdy wartość wiadomości e-mail jest zerowa, możemy dodać dwa wykrzykniki na końcu wiadomości. Lubię to

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

Spowoduje to rzucenie KotlinNullPointerException

Alf Moh
źródło
5
Dlaczego więc ludzie mieliby używać „!!” nawet jeśli jest to niebezpieczne, ponieważ aplikacja zostanie zakończona, gdy ta zmienna ma wartość null?
Sam
3
@david możesz go używać tylko wtedy, gdy jesteś w 100% pewien, że zmienna nie jest pusta (np. jawnie ją zaznaczyłeś) i potrzebujesz zmiennej nieprzekraczającej wartości null
FMK
7
@FMK Rozumiem, dzięki! Rozumiem, że podwójny huk jest używany, aby umożliwić, że wartości zmiennej typu dopuszczającego wartość null przechodzą do zmiennej typów nie dopuszczających wartości null, prawda?
Sam
2
@david tak, dokładnie.
FMK,
10

Operator podwójnego huku to doskonała opcja dla fanów NullPointerException(w skrócie NPE).

Operatora stwierdzenie nie-zerowy !! przekształca każdą wartość do rodzaju nie zerowym i zgłasza wyjątek, że wartość ta jest zerowa.

val nonNull = a!!.length

Możesz więc pisać a!!, a to zwróci niezerową wartość a( Stringna przykład a tutaj) lub wyrzuci NPE, jeśli ajest null.

Jeśli chcesz NPE, możesz go mieć, ale musisz o to wyraźnie poprosić. Ten operator powinien być używany w przypadkach, gdy programista gwarantuje - wartość nigdy nie będzie zerowa .

Andy Fedoroff
źródło
2
Pytanie jako początkujący: dlaczego miałbym chcieć konwertować jakąkolwiek wartość na typ niezerowy?
Wolf359
4
@ Wolf359 Pozwala mieć 100% pewności, że jego wartość nie jest zerowa. („Debugowanie NPE jest częstym problemem i trudno jest znaleźć linię / ścieżkę wykonania, która ustawia wartość na null. To przypisanie o wartości null może się zdarzyć w innym kontekście, klasie lub nawet dniu!” autorstwa Cascader)
zmniejszenie aktywności