El uso de booleano? en la expresión if

130

Si tengo un nulo Boolean b, puedo hacer la siguiente comparación en Java:

Boolean b = ...;
if (b != null && b) {
   /* Do something */
} else {
   /* Do something else */
}

En Kotlin, puedo lograr lo mismo usando el !!operador:

val b: Boolean? = ...
if (b != null && b!!) {
   /* Do something */
} else {
   /* Do something else */
}

Sin embargo, el uso de me !!parece un poco incompleto, eludiendo el sistema de seguridad nulo.

¿Hay un enfoque más elegante para esto?


Editar Parece que me sobreexpliqué un poco. Para las variables locales, como muestra Banthar , funciona. Sin embargo, mi booleano bes en realidad una "propiedad con un campo de respaldo" (todavía no estoy al tanto de lo que esto impone). Este es el resultado:

ingrese la descripción de la imagen aquí

nhaarman
fuente
¿Por qué lo necesitas !!by no simplemente b? (No estoy tan familiarizado con Kotlin, solo curiosidades)
Maroun
1
@MarounMaroun Dado que bpuede ser nully una de las características de Kotlin es Null Safety , que proporciona errores de compilación al intentar evaluar referencias anulables. Por lo tanto, usar plain bda un error de compilación :)
nhaarman
¿Pero no b != nilcaptará eso antes de comprobar el lado derecho?
Maroun
Diría que sí, pero mi IDE dice lo contrario. Recuerdo que algo así debería funcionar, veré si puedo encontrar algo.
nhaarman
Creo que val r = b?doSomething() ?: doSomethingElse()debería funcionar.
Maroun

Respuestas:

183

Puede comparar booleanos anulables con true, falseo nullusando el operador de igualdad:

var b: Boolean? = null
if (b == true) {
    // b was not null and equal true
} 
if (b == false) {
   // b is false 
}
if (b != true) { 
   // b is null or false 
}
Ilya
fuente
44
nota: no parece funcionar con el operador inverso!
Richard
77
@Richard ayuda a pensar B como con 3 valores posibles: true, falseo null. Entonces, cuando lo haces if (b != true), solo sabes que b no es cierto, pero no sabes nada sobre falseonull
jivimberg
77
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac
Esta es la respuesta correcta y tiene sentido en Kotlin, pero viniendo de un entorno de Java puede parecer extraño comparar explícitamente con verdadero o falso o nulo dentro de una declaración if, lo que puede explicar por qué esta es una pregunta y respuesta tan popular.
Michael Peterson el
31

Si desea verificar limpiamente si Boolean?es trueo falsepuede hacer:

when(b) {
    true -> {}
    false -> {}
}

Si desea verificar si es así, nullpuede agregar eso (o else) como un valor en when:

when(b) {
    true -> {}
    false -> {}
    null -> {}
}

when(b) {
    true -> {}
    false -> {}
    else-> {}
}
Eliezer
fuente
22

Kotlin analizará estáticamente sus cheques nulos. Esto esta bien:

val b: Boolean? = null
if (b != null && b) {
    println(b)
}

Aunque esto falla con el error de tipo:

val b: Boolean? = null
if (b == null && b) {
    println(b)
}

Para obtener más información, consulte: http://kotlinlang.org/docs/reference/null-safety.html

También puede usar el "operador de fusión nula" (que funcionará para variables mutables):

val b: Boolean? = null
if (b ?: false) {
    println(b)
}
Piotr Praszmo
fuente
El análisis funciona solo para valores inmutables. Si necesita hacer esto en un campo mutable, guárdelo en una variable local temporal.
Piotr Praszmo
1
Eso tiene sentido, de hecho. El operador de fusión nula es probablemente lo que estaba buscando. ¡Gracias!
nhaarman
@Banthar que no es completamente correcto (su segundo ejemplo sería var?) ... si es un local, varentonces el compilador aún puede permitir el lanzamiento seguro. Para casos más especiales, lea stackoverflow.com/questions/34498562/…
Jayson Minard el
Elvis de fusión nula se puede mover a la asignaciónval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge
6

Por lo que he visto el booleano? es el resultado de un método que devuelve un valor booleano en un objeto que puede anularse

val person: Person? = null
....
if(person?.isHome()) { //This won't compile because the result is Boolean?
  //Do something
}

La solución que he estado usando es usar la letfunción para eliminar el posible valor nulo devuelto de esta manera

person?.let {
  if(it.isHome()) {
    //Do something
  }
}
DroidT
fuente
55
El primero se compila si reemplazas ifblock by person?.isHome() == true.
Hesam
2

En Kotlin, puedes hacer así:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}
ininmm
fuente
3
b != null && b == truees el mismo que b == true.
nhaarman
1

primero, agregue la función en línea personalizada a continuación:

inline fun Boolean?.ifTrue(block: Boolean.() -> Unit): Boolean? {
    if (this == true) {
        block()
    }
    return this
}

inline fun Boolean?.ifFalse(block: Boolean?.() -> Unit): Boolean? {
    if (null == this || !this) {
        block()
    }

    return this
}

entonces puedes escribir código como este:

val b: Boolean? = ...
b.ifTrue {
   /* Do something in true case */
}

//or

b.ifFalse {
   /* Do something else in false case */
}
zyc zyc
fuente
Sí, en el caso: b.ifTrue {...} o b.ifFalse {...} puede ser útil
zyc zyc
1

Para Kotlin lo que normalmente uso es

if (object?.booleanProperty ==true)
   { 
     //do stuff 
   }

esto solo funcionaría cuando la propiedad sea verdadera y el objeto no sea nulo. Por el reverso:

if (!object?booleanProperty !=true)
   { 
     //do Stuff
   }
Juan
fuente
0

Usemos una if-elsedeclaración con un Elvis Operator:

val a: Boolean?
val b: Boolean?

a = true
b = null

if (a != null ?: b) { 
    println("One of them isn't nullable...")
} else {
    println("Both are nullables!")
}

// Resultado: "Uno de ellos no es anulable ..."

a = null
b = null

if (a != null ?: b) { 
    println("One of them isn't nullable...")
} else {
    println("Both are nullables!")
}

// Resultado: "¡Ambos son anulables!"

Andy Fedoroff
fuente
0

Es bastante fácil agregar una función de extensión si eso te ayuda.

fun Boolean?.orDefault(default: Boolean = false): Boolean {
    if (this == null)
        return default
    return this
}

var x: Boolean? = null

if(x.orDefault()) {
..
}
Nic Bell
fuente
0

En caso de que desee realizar operaciones por igual containen una String, puede usar la verificación de igualdad como se muestra a continuación:

if (url?.contains("xxx") == true){
  return false;
}
Anoop M
fuente
-1

Puede hacerlo con el operador seguro "let"

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}
finalpets
fuente
Esto simplemente no es cierto, y volverá en una excepción que se lanza.
nhaarman
Edité mi respuesta según el comentario anterior
finalpets