¿Qué es el operador de doble golpe de Kotlin (!!)?

177

Estoy convirtiendo Java a Kotlin con Android Studio. Obtengo doble explosión después de la variable de instancia. ¿Cuál es el doble golpe y, lo que es más importante, dónde está documentado?

mMap!!.addMarker(MarkerOptions().position(london).title("Marker in London"))
mbr_at_ml
fuente

Respuestas:

205

Esta es T?una conversión de tipo anulable no segura ( ) a un tipo no anulable ( T), !!se lanzará NullPointerExceptionsi el valor es null.

Está documentado aquí junto con los medios de seguridad nula de Kotlin.

tecla de acceso directo
fuente
1
¿Qué significa cuando el !!está al final de una declaración? IJ se convirtió automáticamente a Kotlin lo hizo por míval price = sale.latest!!
ycomp
77
@ycomp, significa que sale.latestpuede contener null; la asignación tendrá éxito solo si sale.latestno es nula y de lo contrario arrojará NPE. Esto proporciona seguridad nula para val price: su tipo será no nulo. Ver kotlinlang.org/docs/reference/null-safety.html
tecla de
1
@hotkey: Entonces, ¿cuál es la diferencia entre obtener NPE, aquí O cuando se accede al último método en un objeto nulo?
Aada
2
@Aada, es un problema común depurar un NPE y tener dificultades para localizar la ruta de línea / ejecución que establece el valor en nulo. ¡Esta asignación nula podría ocurrir en un contexto, clase o incluso día diferente! Al usarlo !!, puede fallar rápidamente y localizar la causa raíz de un NPE. Desearía que Java tuviera una característica similar (es decir, sin ifdeclaraciones feas y / o assertiones).
Cascader
82

Aquí hay un ejemplo para aclarar las cosas. Digamos que tienes esta función

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

Esto producirá el siguiente error de compilación.

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

Ahora puede evitar eso agregando un signo de interrogación al Stringtipo para hacerlo anulable.

Entonces tenemos

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

Esto produce un resultado de

null

Ahora, si queremos que la función arroje una excepción cuando el valor del correo electrónico es nulo, podemos agregar dos exclamaciones al final del correo electrónico. Me gusta esto

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

Esto arrojará un KotlinNullPointerException

Alf Moh
fuente
55
Entonces, ¿por qué la gente usaría '!!' a pesar de que no es seguro porque una aplicación se cerrará cuando esa variable tenga nulo?
Sam
3
@david puede usarlo solo cuando esté 100% seguro de que la variable no es nula (por ejemplo, la verificó explícitamente) y necesita una variable no anulable
FMK
77
@FMK Lo entiendo, ¡gracias! Entiendo que la doble explosión se usa para hacer posible que los valores de la variable de tipo anulable entren en una variable de tipo no anulable, ¿verdad?
Sam
2
@ David sí, exactamente.
FMK
10

El operador de doble explosión es una excelente opción para los fanáticos de NullPointerException(o NPE para abreviar).

El operador de aserción no nulo !! convierte cualquier valor a un tipo no nulo y genera una excepción si el valor es nulo.

val nonNull = a!!.length

Entonces puede escribir a!!, y esto devolverá un valor no nulo de a(un Stringaquí, por ejemplo) o arrojará un NPE si aes nulo.

Si desea un NPE, puede tenerlo, pero debe solicitarlo explícitamente. Este operador debe usarse en casos en los que el desarrollador está garantizando: el valor nunca será nulo .

Andy Fedoroff
fuente
2
Preguntar como principiante: ¿por qué querría convertir cualquier valor a un tipo no nulo?
Wolf359
44
@ Wolf359 Le permite estar 100% seguro de que su valor no es nulo. ("es un problema común depurar un NPE y tener dificultades para localizar la ruta de línea / ejecución que establece el valor en nulo. ¡Esta asignación nula podría ocurrir en un contexto, clase o incluso día diferente!" por Cascader)
reducción de la actividad