75

Hay dos tipos de declaraciones if en java - clásico: if {} else {} y abreviatura: exp ? value1 : value2. ¿Es uno más rápido que el otro o son iguales?¿Qué construcción "si" es más rápida - declaración o operador ternario?

declaración:

int x; 
if (expression) { 
    x = 1; 
} else { 
    x = 2; 
} 

operador ternario:

int x = (expression) ? 1 : 2; 
+33

Supongo que no hay absolutamente ninguna diferencia. Es solo sintaxis. A menos que los compiladores sean algo malvados (o algo más) y estoy equivocado – sinelaw

+4

¿Lo (micro) comparaste? Comparte los resultados. – BalusC

+3

Ambos recibirán jit'ed. No habrá ninguna diferencia en absoluto. Y no te molestes en descompilar las cosas.Lo primero que hace HotSpot es eliminar ** todas ** las optimizaciones que javac aplicó. –

Respuesta

93

Solo hay un tipo de instrucción "if" allí. La otra es una expresión condicional. En cuanto a cuál funcionará mejor: podrían compilar al mismo código de bytes, y esperaría que se comporten de manera idéntica, o tan cerca que definitivamente no querría elegir uno sobre el otro en términos de rendimiento.

A veces una declaración if será más legible, a veces el operador condicional será más legible. En particular, recomendaría usar el operador condicional cuando los dos operandos son simples y libres de efectos secundarios, mientras que si el propósito principal de las dos ramas es sus efectos secundarios, probablemente usaría una declaración if.

Aquí hay un ejemplo de programa y el código de bytes:

public class Test { 
    public static void main(String[] args) { 
     int x; 
     if (args.length > 0) { 
      x = 1; 
     } else { 
      x = 2; 
     } 
    } 

    public static void main2(String[] args) { 
     int x = (args.length > 0) ? 1 : 2; 
    } 
} 

Bytecode descompilada con javap -c Test:

public class Test extends java.lang.Object { 
    public Test(); 
    Code: 
     0: aload_0 
     1: invokespecial #1 
     4: return 

    public static void main(java.lang.String[] 
    Code: 
     0: aload_0 
     1: arraylength 
     2: ifle   10 
     5: iconst_1 
     6: istore_1 
     7: goto   12 
     10: iconst_2 
     11: istore_1 
     12: return 

    public static void main2(java.lang.String[ 
    Code: 
     0: aload_0 
     1: arraylength 
     2: ifle   9 
     5: iconst_1 
     6: goto   10 
     9: iconst_2 
     10: istore_1 
     11: return 
} 

Como se puede ver, hay una ligero diferencia en el código de bytes de aquí - si se produce la istore_1 dentro de la brance o no (a diferencia de mi intento anterior muy defectuoso :) pero estaría muy sorprendido si el JITter terminara con un código nativo diferente.

+0

s/declaración condicional/expresión condicional/ –

+0

@Laurence: Doh - gracias, corregido. –

+1

Supongo que no querías que tanto 'main' como' main2' fueran exactamente iguales. – ColinD

4

ni - que serán compilados a la misma.

10

Ambos ejemplos probablemente se compilarán con un bytecode idéntico o casi idéntico, por lo que no debería haber diferencia en el rendimiento.

Si hubiera habido una diferencia en la velocidad de ejecución, debería seguir utilizando la versión más idiomática (que sería la segunda para asignar una sola variable basada en una condición simple y dos subexpresiones simples, y la primera para realizando operaciones u operaciones más complejas que no caben en una sola línea).

+0

-1 Por estar equivocado. Si va a reclamar que dos piezas de código se compilarán en el mismo bytecode sin siquiera proporcionar un calificador como "probablemente" o "creo", al menos podría verificar que lo hagan. Aunque incluso si * compilan * con el mismo bytecode, eso no garantizaría que otras versiones del compilador de Java no se compilarían en códigos de bytes diferentes. – Brian

+0

@Brian: tienes razón. Edité mi respuesta. –

+5

OK, eliminé mi -1 :) – Brian

7

Estos son lo mismo. Ambos son bastante rápidos, típicamente alrededor de 10-30 nano segundos. (según el patrón de uso) ¿Es este marco de tiempo importante para usted?

Debe hacer lo que cree que es más claro.

3

sólo para añadir a todas las otras respuestas:

La segunda expresión es a menudo llamado terciario/operador ternario/comunicado. Puede ser muy útil porque devuelve una expresión. Algunas veces hace que el código sea más claro para declaraciones cortas típicas.

+3

Gran ejemplo de esto en la práctica: en Java, si tengo que hacer un final de cadena basado en el resultado de una expresión, puedo usar el sintaxis ternaria final Cadena whichTable = (Integer.parseInt (clientId)> 500)? "serverClients": "offlineClients"; Entonces puedo usar el valor de la expresión en lugares donde whichTable debe ser final. Lo siguiente sería ilegal: final String whichTable = ""; if (Integer.parseInt (clientId)> 500) { whichTable = "serverClients"; } else { whichTable = "offlineClients"; } –

+0

@JamesPerih Exactamente. – Secko

Cuestiones relacionadas