O que é o operador Kotlin double-bang (!!)?

177

Estou convertendo Java para Kotlin com o Android Studio. Eu recebo double bang após a variável de instância. Qual é o estrondo duplo e, mais importante, onde isso está documentado?

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

Respostas:

205

Esta é T?uma conversão de tipo anulável inseguro ( ) para um tipo não anulável ( T), !!será lançada NullPointerExceptionse o valor for null.

Está documentado aqui, juntamente com os meios de segurança nula da Kotlin.

tecla de atalho
fonte
1
o que significa quando !!está no final de uma declaração? A conversão automática de IJ para Kotlin fez isso por mimval price = sale.latest!!
ycomp 23/02
7
@ycomp, significa que sale.latestpode conter null; a atribuição será bem-sucedida somente se sale.latestnão for nula e lançará o NPE caso contrário. Isso fornece segurança nula para val price: seu tipo será não nulo. Veja kotlinlang.org/docs/reference/null-safety.html
hotkey
1
@hotkey: Então, qual é a diferença entre obter o NPE - aqui OU quando o método mais recente é acessado no objeto nulo?
Aada 13/08/19
2
@ Aada, é um problema comum depurar um NPE e é difícil localizar o caminho de linha / execução que define o valor como nulo. Essa atribuição nula pode acontecer em um contexto, classe ou mesmo dia diferente! Ao usar, !!você pode executar uma falha rápida e localizar a causa raiz de um NPE. Eu gostaria que o Java tivesse um recurso semelhante (ou seja, sem ifdeclarações e / ou assertíons feios ).
Cascader
82

Aqui está um exemplo para tornar as coisas mais claras. Digamos que você tenha essa função

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

Isso produzirá o seguinte erro de compilação.

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

Agora você pode impedir isso adicionando um ponto de interrogação ao Stringtipo para torná-lo anulável.

Então nós temos

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

Isso produz um resultado de

null

Agora, se queremos que a função gere uma exceção quando o valor do email for nulo, podemos adicionar duas exclamações no final do email. Como isso

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

Isso lançará um KotlinNullPointerException

Alf Moh
fonte
5
Então, por que as pessoas usariam '!!' mesmo que não seja seguro porque um aplicativo será encerrado quando essa variável for nula?
Sam
3
@ David você pode usá-lo apenas quando estiver 100% de certeza que a variável não é nulo (por exemplo, você verificou-lo explicitamente) e você precisa variável não-nulo
FMK
7
@ FMK eu entendi, obrigado! Eu entendo que double bang é usado para possibilitar que os valores da variável de tipo anulável entrem na variável de tipos não anuláveis, certo?
Sam
2
@ David sim, exatamente.
FMK
10

O operador de golpe duplo é uma excelente opção para os fãs de NullPointerException(ou NPE, para abreviar).

O operador de asserção não nulo !! converte qualquer valor em um tipo não nulo e lança uma exceção se o valor for nulo.

val nonNull = a!!.length

Portanto, você pode escrever a!!e isso retornará um valor não nulo de a(um Stringaqui por exemplo) ou lançará um NPE sea for nulo.

Se você deseja um NPE, pode obtê-lo, mas precisa solicitá-lo explicitamente. Esse operador deve ser usado nos casos em que o desenvolvedor está garantindo - o valor nunca será nulo .

Andy Fedoroff
fonte
2
Perguntando como iniciante: por que eu gostaria de converter qualquer valor em um tipo não nulo?
#
4
@ Wolf359 Permite-lhe ter 100% de certeza de que o seu valor não é nulo. ("é problema comum depurar um NPE e é difícil localizar o caminho de linha / execução que define o valor como nulo. Essa atribuição nula pode acontecer em um contexto, classe ou mesmo dia diferente!" por Cascader)
reduzindo a atividade