El ternario es un if-else que devuelve un valor. Esa es toda la diferencia, y también la razón por la que a veces encaja y a veces no.
También te puede interesar
De if a ternario
int i = 1, j = 2;
int mayor;
if (i > j) {
mayor = i;
} else {
mayor = j;
}Seis líneas para decidir un valor. Con el ternario:
int mayor = i > j ? i : j;
salidamayor: 2
La forma es siempre la misma: condición ? valor_si_es_cierto : valor_si_es_falso. Como el resultado es un valor, puede ir donde vaya un valor: en una asignación, en un argumento o dentro de una concatenación.
System.out.println(i > j ? "i es mayor" : "j es mayor");
salidaj es mayor
La diferencia que importa
Un if ejecuta sentencias; un ternario produce un valor. Por eso esto es válido y lo otro no:
int x = condición ? 1 : 2; // bien: las dos ramas son valores
// int y = condición ? System.out.println("hola") : 2; // no compila: println no devuelve nadaY de ahí sale la regla para decidir: si lo que quieres es elegir un valor, ternario; si lo que quieres es hacer dos cosas distintas, if. Forzar un ternario para provocar efectos secundarios se lee mal y a veces ni compila.
La trampa: int e Integer en la misma expresión
public class Trampa {
static Integer edad = null; // viene de una base de datos, por ejemplo
public static void main(String[] args) {
Object c = true ? edad : 0; // una rama Integer, la otra int
System.out.println(c);
}
}salidaException in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "Trampa.edad" is null at Trampa.main(Trampa.java:5)
Object. Parecería que ahí cabe un null sin problema, y sin embargo revienta. Lo que pasa es que el tipo del ternario se decide antes: al mezclar Integer con int, el lenguaje concluye que el resultado es int, y para eso tiene que desempaquetar el Integer llamando a intValue(). Sobre null, eso es un NullPointerException.La solución es no mezclar: que las dos ramas sean del mismo tipo.
Object c = true ? edad : (Integer) 0; // las dos Integer: no hay desempaquetado int d = (edad != null) ? edad : 0; // o compruebas antes, que es lo normal
salidac = null
Y conviene saber que esto no falla, aunque lo parezca:
int a = true ? 1 : edad; // la rama de edad no se evalúa
System.out.println("a = " + a);salidaa = 1
Solo se desempaqueta la rama que se ejecuta. Que falle o no depende de cuál sea, y por eso el fallo aparece en producción y no en las pruebas.
Cuándo no usarlo
// ilegible String r = a ? (b ? "uno" : "dos") : (c ? "tres" : "cuatro");
Un ternario dentro de otro se puede escribir, pero hay que leerlo tres veces. En cuanto hay más de una condición, un if o un switch con flecha se entienden a la primera. El ternario brilla en lo corto: un valor por omisión, un singular o plural, un signo.
String texto = n + " archivo" + (n == 1 ? "" : "s");
Más información en inglés: Ternary operator in Java.
Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.