una ternario switch sola operador linea else ejemplos condiciones anidado java java-8 ternary-operator

ternario - if y switch en java



Operador ternario Java vs if/else en compatibilidad<JDK8 (4)

Recientemente estoy leyendo el código fuente de Spring Framework. Algo que no puedo entender va aquí:

public Member getMember() { // NOTE: no ternary expression to retain JDK <8 compatibility even when using // the JDK 8 compiler (potentially selecting java.lang.reflect.Executable // as common type, with that new base class not available on older JDKs) if (this.method != null) { return this.method; } else { return this.constructor; } }

Este método es miembro de la clase org.springframework.core.MethodParameter . El código es fácil de entender mientras que los comentarios son difíciles.

NOTA: ninguna expresión ternaria para retener la compatibilidad JDK <8 incluso cuando se utiliza el compilador JDK 8 (potencialmente seleccionando java.lang.reflect.Executable como tipo común, con esa nueva clase base no disponible en JDK anteriores)

¿Cuál es la diferencia entre usar expresiones ternarias y usar if...else... construct en este contexto?


Cuando piensa en el tipo de operandos, el problema se hace más evidente:

this.method != null ? this.method : this.constructor

tiene como tipo el tipo común más especializado de ambos operandos, es decir, el tipo más especializado común tanto para this.method como para this.constructor .

En Java 7 esto es java.lang.reflect.Member , sin embargo, la biblioteca de clases Java 8 introduce un nuevo tipo java.lang.reflect.Executable que es más especializado que el Member genérico. Por lo tanto, con una biblioteca de clases Java 8, el tipo de resultado de la expresión ternaria es Executable lugar de Member .

Algunas versiones (anteriores al lanzamiento) del compilador Java 8 parecen haber producido una referencia explícita a Executable dentro del código generado al compilar el operador ternario. Esto desencadenaría una carga de clase y, a su vez, una ClassNotFoundException en tiempo de ejecución cuando se ejecuta con una biblioteca de clases <JDK 8, porque el Executable solo existe para JDK ≥ 8.

Como señaló Tagir Valeev en esta respuesta , esto es realmente un error en las versiones preliminares de JDK 8 y desde entonces se ha solucionado, por lo que tanto la solución alternativa como el comentario explicativo ahora son obsoletos.

Nota adicional: Se podría llegar a la conclusión de que este error del compilador estaba presente antes de Java 8. Sin embargo, el código de bytes generado para el ternario por OpenJDK 7 es el mismo que el código de bytes generado por OpenJDK 8. De hecho, el tipo de la expresión no se menciona por completo en tiempo de ejecución, el código es realmente solo prueba, ramificación, carga, devolución sin realizar ninguna comprobación adicional. Así que tenga la seguridad de que esto ya no es un problema (y de hecho) parece haber sido un problema temporal durante el desarrollo de Java 8.


El tipo de valor de retorno en una expresión ternaria se ve afectado por las clases primarias, que cambiaron como se describe en Java 8.

Es difícil ver por qué no se pudo haber escrito un elenco.


Esto se introdujo en una confirmación bastante antigua el 3 de mayo de 2013, casi un año antes del lanzamiento oficial de JDK-8. El compilador estaba bajo un fuerte desarrollo en esos momentos, por lo que podrían surgir problemas de compatibilidad. Supongo que el equipo de Spring acaba de probar la compilación JDK-8 e intentó solucionar problemas, aunque en realidad son problemas de compilación. Por el lanzamiento oficial de JDK-8 esto se volvió irrelevante. Ahora el operador ternario en este código funciona bien como se esperaba (no hay referencia a la clase Executable en el archivo compilado .class).

Actualmente aparecen cosas similares en JDK-9: algunos códigos que pueden compilarse bien en JDK-8 fallan con JDK-9 javac. Supongo que la mayoría de estos problemas se solucionarán hasta el lanzamiento.


La principal diferencia es que un bloque if else es una declaración, mientras que el ternario (más conocido como operador condicional en Java) es una expresión .

Una declaración puede hacer cosas como return a la persona que llama en algunas de las rutas de control. Se puede usar una expresión en una tarea:

int n = condition ? 3 : 2;

Por lo tanto, las dos expresiones en el ternario después de la condición deben ser en mayúsculas al mismo tipo. Esto puede causar algunos efectos extraños en Java, particularmente con el auto-boxeo y la transmisión automática de referencias: esto es a lo que se refiere el comentario en su código publicado. La coerción de las expresiones en su caso sería un tipo java.lang.reflect.Executable (ya que es el tipo más especializado ) y que no existe en versiones anteriores de Java.

Estilísticamente, debe usar un bloque if else si el código tiene forma de declaración y un ternario si tiene forma de expresión.

Por supuesto, puede hacer que un bloque if else se comporte como una expresión si usa una función lambda.