Les conditions

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Nous abordons ici l'un des chapitres les plus importants : les conditions sont une autre notion fondamentale de la programmation. En effet, ce qui va être développé ici s'applique à énormément de langages de programmation, et pas seulement à Java.

Dans une classe, la lecture et l'exécution se font de façon séquentielle, c'est-à-dire ligne par ligne. Avec les conditions, nous allons pouvoir gérer différents cas de figure sans pour autant lire tout le code. Vous vous rendrez vite compte que tous vos projets ne sont que des enchaînements et des imbrications de conditions et de boucles (notion que l'on abordera au chapitre suivant).

Assez de belles paroles ! Entrons tout de suite dans le vif du sujet.

La structure if… else

Avant de pouvoir créer et évaluer des conditions, vous devez savoir que pour y parvenir, nous allons utiliser ce qu'on appelle des « opérateurs logiques ». Ceux-ci sont surtout utilisés lors de conditions (si [test] alors [faire ceci]) pour évaluer différents cas possibles. Voici les différents opérateurs à connaître :

  • « == » : permet de tester l'égalité.
  • « != » : permet de tester l’inégalité.
  • « < » : strictement inférieur.
  • « <= » : inférieur ou égal.
  • « > » : strictement supérieur.
  • « >= » : supérieur ou égal.
  • « && » : l'opérateur ET. Il permet de préciser une condition
  • « || » : le OU. Même combat que le précédent.
  • «  ? : » : l'opérateur ternaire. Pour celui-ci, vous comprendrez mieux avec un exemple qui sera donné vers la fin de ce chapitre.

Comme je vous l'ai dit dans le chapitre précédent, les opérations en Java sont soumises à des priorités. Tous ces opérateurs se plient à cette règle, de la même manière que les opérateurs arithmétiques…

Imaginons un programme qui demande à un utilisateur d'entrer un nombre entier relatif (qui peut être soit négatif, soit nul, soit positif). Les structures conditionnelles vont nous permettre de gérer ces trois cas de figure. La structure de ces conditions ressemble à ça :

1
2
3
4
5
6
7
8
if(//condition)
{
  //Exécution des instructions si la condition est remplie
}
else
{
  //Exécution des instructions si la condition n'est pas remplie
}

Cela peut se traduire par « si… sinon… ».

Le résultat de l'expression évaluée par l'instruction if sera un boolean, donc soit true, soit false. La portion de code du bloc if ne sera exécutée que si la condition est remplie. Dans le cas contraire, c'est le bloc de l'instruction else qui le sera. Mettons notre petit exemple en pratique :

1
2
3
4
5
6
int i = 10;

if (i < 0)
  System.out.println("le nombre est négatif");
else
  System.out.println("le nombre est positif");

Essayez ce petit code, et vous verrez comment il fonctionne. Dans ce cas, notre classe affiche « le nombre est positif ». Expliquons un peu ce qui se passe.

  • Dans un premier temps, la condition du if est testée : elle dit « si i est strictement inférieur à 0 alors fais ça ».
  • Dans un second temps, vu que la condition précédente est fausse, le programme exécute le else.

Attends un peu ! Lorsque tu nous as présenté la structure des conditions, tu as mis des accolades et là, tu n'en mets pas. Pourquoi ?

Bien observé. En fait, les accolades sont présentes dans la structure « normale » des conditions, mais lorsque le code à l'intérieur de l'une d'entre elles n'est composé que d'une seule ligne, les accolades deviennent facultatives.

Comme nous avons l'esprit perfectionniste, nous voulons que notre programme affiche « le nombre est nul » lorsque i est égal à 0 ; nous allons donc ajouter une condition. Comment faire ? La condition du if est remplie si le nombre est strictement négatif, ce qui n'est pas le cas ici puisque nous allons le mettre à 0. Le code contenu dans la clause else est donc exécuté si le nombre est égal ou strictement supérieur à 0. Il nous suffit d'ajouter une condition à l'intérieur de la clause else, comme ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int i = 0;
if (i < 0)
{
  System.out.println("Ce nombre est négatif !");
} 
else
{
  if(i == 0)
    System.out.println("Ce nombre est nul !");

  else
    System.out.println("Ce nombre est positif !");

}

Maintenant que vous avez tout compris, je vais vous présenter une autre façon d'écrire ce code, avec le même résultat : on ajoute juste un petit « sinon si… ».

1
2
3
4
5
6
7
8
9
int i = 0;
if (i < 0)
  System.out.println("Ce nombre est négatif !");      

else if(i > 0)
  System.out.println("Ce nombre est positif !");           

else  
  System.out.println("Ce nombre est nul !");

Alors ? Explicite, n'est-ce pas ?

  • si i est strictement négatif alors le code de cette condition est exécuté.
  • sinon si i est strictement positif alors le code de cette condition est exécuté.
  • sinon i est forcément nul alors le code de cette condition est exécuté.

Il faut absolument donner une condition au else if pour qu'il fonctionne.

Ici, je vais très fortement insister sur un point : regardez l'affichage du code et remarquez le petit décalage entre le test et le code à exécuter. On appelle cela l'indentation !

Pour vous repérer dans vos futurs programmes, cela sera très utile. Imaginez deux secondes que vous avez un programme de 700 lignes avec 150 conditions, et que tout est écrit le long du bord gauche. Il sera difficile de distinguer les tests du code. Vous n'êtes pas obligés de le faire, mais je vous assure que vous y viendrez.

Avant de passer à la suite, vous devez savoir qu'on ne peut pas tester l'égalité de chaînes de caractères ! Du moins, pas comme je vous l'ai montré ci-dessus. Nous aborderons ce point plus tard.

Les conditions multiples

Derrière ce nom barbare se cachent simplement plusieurs tests dans une instruction if (ou else if). Nous allons maintenant utiliser les opérateurs logiques que nous avons vus au début en vérifiant si un nombre donné appartient à un intervalle connu. Par exemple, on va vérifier si un entier est compris entre 50 et 100.

1
2
3
4
5
int i = 58;
if(i < 100 && i > 50) 
  System.out.println("Le nombre est bien dans l'intervalle.");
else
  System.out.println("Le nombre n'est pas dans l'intervalle.");

Nous avons utilisé l'opérateur &&. La condition de notre if est devenue : « si i est inférieur à 100 ET supérieur à 50 ».

Avec l'opérateur « && », la clause est remplie si et seulement si les conditions la constituant sont toutes remplies ; si l'une des conditions n'est pas vérifiée, la clause sera considérée comme fausse.

Cet opérateur vous initie à la notion d'intersection d'ensembles. Ici, nous avons deux conditions qui définissent un ensemble chacune :

  • i < 100 définit l'ensemble des nombres inférieurs à 100 ;
  • i > 50 définit l'ensemble des nombres supérieurs à 50.

L'opérateur « && » permet de faire l'intersection de ces ensembles. La condition regroupe donc les nombres qui appartiennent à ces deux ensembles, c’est-à-dire les nombres de 51 à 99 inclus. Réfléchissez bien à l'intervalle que vous voulez définir. Voyez ce code :

1
2
3
4
5
int i = 58;
if(i < 100 && i > 100) 
  System.out.println("Le nombre est bien dans l'intervalle.");
else
  System.out.println("Le nombre n'est pas dans l'intervalle.");

Ici, la condition ne sera jamais remplie, car je ne connais aucun nombre qui soit à la fois plus petit et plus grand que 100 ! Reprenez le code précédent et remplacez l'opérateur « && » par « || » (petit rappel, il s'agit du OU). À l'exécution du programme et après plusieurs tests de valeur pour i, vous pourrez vous apercevoir que tous les nombres remplissent cette condition, sauf 100.

La structure switch

Le switch est surtout utilisé lorsque nous voulons des conditions « à la carte ». Prenons l'exemple d'une interrogation comportant deux questions. Pour chacune d'elles, on peut obtenir uniquement 0 ou 10 points, ce qui nous donne au final trois notes et donc trois appréciations possibles, comme ceci :

  • 0/20 : tu dois revoir ce chapitre !
  • 10/20 : je crois que tu as compris l'essentiel ! Viens relire ce chapitre à l'occasion.
  • 20/20 : bravo !

Dans ce genre de cas, on utilise un switch pour éviter des else if à répétition et pour alléger un peu le code. Je vais vous montrer comment se construit une instruction switch ; puis nous allons l'utiliser tout de suite après.

Syntaxe

1
2
3
4
5
6
7
8
switch (/*Variable*/)
{
  case /*Argument*/:
    /*Action*/;
    break;        
  default:
    /*Action*/;             
}

Voici les opérations qu'effectue cette expression :

  • La classe évalue l'expression figurant après le switch (ici /*Variable*/).
  • Si la première languette (case /*Valeur possible de la variable*/:) correspond à la valeur de /*Variable*/, l'instruction figurant dans celle-ci sera exécutée.
  • Sinon, on passe à la languette suivante, et ainsi de suite.
  • Si aucun des cas ne correspond, la classe va exécuter ce qui se trouve dans l'instruction default:/*Action*/;. Voyez ceci comme une sécurité.

Notez bien la présence de l'instruction break;. Elle permet de sortir du switch si une languette correspond. Pour mieux juger de l'utilité de cette instruction, enlevez tous les break; et compilez votre programme. Vous verrez le résultat… Voici un exemple de switch que vous pouvez essayer :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int note = 10; //On imagine que la note maximale est 20

switch (note)
{
  case 0:
    System.out.println("Ouch !");
    break;
  case 10:
    System.out.println("Vous avez juste la moyenne.");
    break;
  case 20:
    System.out.println("Parfait !");
    break;
  default:
    System.out.println("Il faut davantage travailler.");
}

Je n'ai écrit qu'une ligne de code par instruction case, mais rien ne vous empêche d'en mettre plusieurs.

Si vous avez essayé ce programme en supprimant l'instruction break;, vous avez dû vous rendre compte que le switch exécute le code contenu dans le case 10:, mais aussi dans tous ceux qui suivent ! L'instruction break; permet de sortir de l'opération en cours. Dans notre cas, on sort de l'instruction switch, mais nous verrons une autre utilité à break; dans le chapitre suivant.

Depuis la version 7 de Java, l'instruction switch accepte les objets de type String en paramètre. De ce fait, cette instruction est donc valide :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
String chaine = "Bonjour";

switch(chaine) {
  case "Bonjour":
    System.out.println("Bonjour monsieur !");
    break;
  case "Bonsoir":
    System.out.println("Bonsoir monsieur !");
    break;
  default:
    System.out.println("Bonjoir ! :p");
}

La condition ternaire

Les conditions ternaires sont assez complexes et relativement peu utilisées. Je vous les présente ici à titre indicatif. La particularité de ces conditions réside dans le fait que trois opérandes (c'est-à-dire des variables ou des constantes) sont mis en jeu, mais aussi que ces conditions sont employées pour affecter des données à une variable. Voici à quoi ressemble la structure de ce type de condition :

1
2
int x = 10, y = 20;
int max = (x < y) ? y : x ; //Maintenant, max vaut 20

Décortiquons ce qu'il se passe :

  • Nous cherchons à affecter une valeur à notre variable max, mais de l'autre côté de l'opérateur d'affectation se trouve une condition ternaire…
  • Ce qui se trouve entre les parenthèses est évalué : x est-il plus petit que y ? Donc, deux cas de figure se profilent à l'horizon :
    • si la condition renvoie true (vrai), qu'elle est vérifiée, la valeur qui se trouve après le ? sera affectée ;
    • sinon, la valeur se trouvant après le symbole: sera affectée.
  • L'affectation est effective : vous pouvez utiliser votre variable max.

Vous pouvez également faire des calculs (par exemple) avant d'affecter les valeurs :

1
2
int x = 10, y = 20;
int max = (x < y) ? y * 2 : x * 2 ; //Ici, max vaut 2 * 20 donc 40

N'oubliez pas que la valeur que vous allez affecter à votre variable doit être du même type que votre variable. Sachez aussi que rien ne vous empêche d'insérer une condition ternaire dans une autre condition ternaire :

1
2
3
4
5
6
7
8
int x = 10, y = 20;

int max = (x < y) ? (y < 10) ? y % 10 : y * 2 : x ; //Max vaut 40

//Pas très facile à lire…
//Vous pouvez entourer votre deuxième instruction ternaire par des parenthèses pour mieux voir :

max = (x < y) ? ((y < 10) ? y % 10 : y * 2) : x ; //Max vaut 40

  • Les conditions vous permettent de n'exécuter que certains morceaux de code.
  • Il existe plusieurs sortes de structures conditionnelles :
    • la structure if... elseif... else ;
    • la structure switch... case... default ;
    • la structure  ? :.
  • Si un bloc d'instructions contient plus d'une ligne, vous devez l'entourer d'accolades afin de bien en délimiter le début et la fin.
  • Pour pouvoir mettre une condition en place, vous devez comparer des variables à l'aide d'opérateurs logiques.
  • Vous pouvez mettre autant de comparaisons renvoyant un boolean que vous le souhaitez dans une condition.
  • Pour la structure switch, pensez à mettre les instructions break; si vous ne souhaitez exécuter qu'un seul bloc case.