La solution pour « faire pleurer vos collègues »

Après quelques jours d’attente, je me lance et vous propose une solution.

La question était posée ici

Pour rappel il fallait dire ce que fait le code suivant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test  
public void testCalcul1() {  
  int i;  
  i = i++;  
  System.out.println(i);  
}  
 
@Test  
public void testCalcul2() {  
  int i = 0;  
  i = i++;  
  System.out.println(i);  
}  
 
@Test  
public void testCalcul3() {  
  int i = 1;  
  i = 1 + i++;  
  System.out.println(i);  
}  
 
@Test  
public void testCalcul4() {  
  int i = 1;  
  i = 1 + ++i + i++;  
  System.out.println(i);  
}

Commençons par la méthode « testCalcul1″. Elle ne compile tout simplement pas puisque la variable « i » n’a pas été initialisée explicitement. Contrairement aux variables de classes qui sont auto initialisées (warning compilation incomplète) avec les valeurs par défaut (zéro pour un int), les variables de méthodes doivent être explicitement initialisées avant de pouvoir être utilisées. On a néanmoins le droit de ne pas initialiser une variable sous resserve de ne pas l’utiliser. Du coup elle ne sert à rien…

La méthode « testCalcul2″ écrit « 0 » (zéro). Instinctivement on se doute bien que ça allait écrire soit 0 soit 1. Ici la clé de l’énigme est l’ordre de priorité du « = » et du « ++ ». Pour nous aider à bien comprendre, créons la méthode suivante.

1
2
3
4
5
6
7
8
9
10
11
@Test  
public void testCalcul2b() {  
  int i = 0;
  int j = 0;
  j = i++;  
  System.out.println("i=" + i);  
  System.out.println("j=" + j);  
}  
 
// --> i=1
// --> j=0

On voit bien, grace à l’instruction « j = i++ » que l’opérateur d’affectation « = » est prioritaire à la post-incrémentation « ++ ». Du coup, si on revient à « testCalcul2″, la variable « i » va donc prendre la valeur « 0 ». Mais me direz-vous, que devient le « ++ » mis en attente ? Et ben il est effectivement réalisé, mais sur une autre variable « i » qui, pour le coup, est perdue même si elle reste présente en mémoire.

La méthode « testCalcul3″ écrit « 2 ». C’est le même raisonnement que pour « testCalcul2″ mais avec des conditions initiales légèrement différentes.

Quant à « testCalcul4″, elle écrit « 5 ». Je l’ai programmer pour rigoler au départ et, finalement, je me suis rendu compte qu’elle était intéressante, pas seulement pour avoir une écriture super complexe mais aussi pour bien voir les priorités. Pour la comprendre, on peut commencer par la simplifier comme suit.

1
2
3
4
5
6
7
8
@Test  
public void testCalcul4b() {  
  int i = 1;  
  i = 1 + ++i ;  
  System.out.println(i);  
}
 
// --> 3

En fait le « ++i » passe en premier, du coup « i = 1 + ++i » est équivalent à « i = 1 + 2″, donc « i » vaut « 3 » à la fin. Et pour la même raison, l’instruction « i = 1 + ++i + i++ » revient à « i = 1 + 2 + 2++ » or comme vu dans « testCalcul2″, le « ++ » va passer après le « = » et donc on obtient seulement « 1 + 2 + 2 = 5″…

CQFD… Bonne partie de casse-tête !

Laisser un commentaire