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í


¿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 
}

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-> {}
}

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)
}

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
  }
}

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 */
}

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 */
}

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
   }

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!"


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()) {
..
}

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;
}

-1

Puede hacerlo con el operador seguro "let"

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}

Esto simplemente no es cierto, y volverá en una excepción que se lanza.
nhaarman

Edité mi respuesta según el comentario anterior
finalpets
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.