web-dev-qa-db-fra.com

Quelle construction "si" est plus rapide - déclaration ou opérateur ternaire?

Il existe deux types d'instructions if dans Java - classic: if {} else {} et sténographie: exp ? value1 : value2. Est-ce que l'un est plus rapide que l'autre ou sont-ils les mêmes?

déclaration:

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

opérateur ternaire:

int x = (expression) ? 1 : 2;
81
Rogach

Il n'y a qu'un seul type de "si" déclaration là. L'autre est une expression conditionnelle. Pour ce qui est de savoir lequel fonctionnera le mieux: ils pourraient compiler dans le même bytecode, et je m'attendrais à ce qu'ils se comportent de manière identique - ou si proches que vous ne voudriez certainement pas choisir l'un par rapport à l'autre en termes de performances.

Parfois, une instruction if sera plus lisible, parfois l'opérateur conditionnel sera plus lisible. En particulier, je recommanderais d'utiliser l'opérateur conditionnel lorsque les deux opérandes sont simples et sans effets secondaires, alors que si l'objectif principal des deux branches est leurs effets secondaires, j'utiliserais probablement une déclaration if.

Voici un exemple de programme et de bytecode:

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 décompilé avec 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
}

Comme vous pouvez le constater, il existe une légère différence de bytecode ici - que le istore_1 se produit dans les règles ou non (contrairement à ma précédente tentative très imparfaite :) mais je serais très surpris que JITter se retrouve avec un code natif différent.

105
Jon Skeet

Vos deux exemples seront probablement compilés en bytecode identique ou presque identique, il ne devrait donc pas y avoir de différence de performances.

S'il y avait eu une différence de vitesse d'exécution, vous devriez toujours utiliser la version la plus idiomatique (qui serait la deuxième pour assigner une seule variable basée sur une condition simple et deux sous-expressions simples, et la première pour effectuer des opérations plus complexes ou des opérations qui ne tiennent pas sur une seule ligne).

10
Victor Nicollet

Ce sont les mêmes. Les deux sont assez rapides, généralement autour de 10-30 nanosecondes. (selon le modèle d'utilisation) Ce délai est-il important pour vous?

Vous devriez faire ce que vous croyez le plus clair.

8
Peter Lawrey

Juste pour ajouter à toutes les autres réponses:

La deuxième expression est souvent appelée opérateur/instruction tertiaire/ternaire. Cela peut être très utile car cela retourne une expression. Parfois, cela rend le code plus clair pour les déclarations courtes typiques.

4
Secko

ni - ils seront compilés à la même chose.

3
Freddie