Rechercher
 

Les instructions du langage Java

Les opérateurs Programmation Orientée Objet



Accès rapide :
   Les blocs d'instructions
   L'instruction if
   L'instruction switch

Dans le chapitre précédent, nous avons vu ce qu'étaient les expressions : celles-ci permettent de calculer des valeurs. Parallèlement, nous avons les instructions (statements en anglais) qui permettent de lancer des actions. En composant les instructions on défini ainsi le comportement que le programme devra adopter. Pour mieux comprendre les choses, nous allons, tout au long de ce chapitre, étudier une à une toutes les instructions utilisables en Java. Ceux d'entre vous qui connaissent C, C++, ou bien encore Javascript, s'y retrouverons assez facilement (les syntaxes restant très proches les unes des autres). Pour les autres, il est temps d'apprendre à utiliser ces instructions.

Premier point de syntaxe : toute instruction se termine par un point-virgule. Attention, il ne s'agit pas d'un séparateur, mais bien d'un terminateur d'instruction : même la dernière instruction d'un bloc doit être terminée par ce caractère.

Les blocs d'instructions

Comme son nom le laisse présager, le bloc d'instructions peut contenir plusieurs instructions (il peut aussi en contenir qu'une unique). Le bloc commence par une accolade ouvrante et se termine par une accolade fermante. L'exemple ci-dessous montre un bloc d'instructions vous demandant de saisir votre nom. La seconde instruction du bloc permet de capturer dans une variable de type chaîne de caractères, la valeur que vous aurez saisi à partir du clavier. Enfin, la troisième instruction permet d'afficher la valeur saisie sur la console. Notez bien que chaque instruction est terminée, comme nous venons de le dire précédemment par un point virgule. Si vous ne respectez pas cette règle, une erreur de compilation vous sera retournée.

  
01 {
02     System.out.print( "Veuillez renseigner votre nom : " );
03     String nom = System.console().readline();
04     System.out.println( "Votre nom est : " + nom );
05 }

ATTENTION : la méthode statique System.console() n'est disponible que depuis le Java SE 6.0. De plus elle ne marche que si vous lancez l'application à partir d'une console shell. Si au contraire, vous lancer l'application utilisant ces lignes à partir de la console d'Eclipse, la valeur null vous sera retournée ce qui déclenchera une erreur.

Il faut de plus savoir qu'un bloc d'instructions impose une durée de vie aux variables qui sont déclarées à l'intérieur de ce bloc. En fait une telle variable (dite locale) est stockée dans un espace de mémoire particulier appelé la pile d'exécution (ou stack, en anglais). L'état de la pile évolue au cours du temps en fonction des variables de l'on défini. Il faut aussi savoir une chose très importante : la taille de la pile d'exécution est limitée. Si vous saturez cette pile d'exécution, une erreur FATALE sera déclenchée. L'erreur produite sera plus précisément de type StackOverflowError. En réalité, un programme Java complexe n'a pas qu'une unique pile d'exécution. Effectivement, cette notion de pile est en fait liée à la notion de threads (aussi appelé fil d'exécution) : il existe donc une pile d'exécution par thread.


Evolution de la pile d'exécution au cours du temps

Le diagramme ci-dessus vous montre comment les variables naissent, évoluent et meurent au cours de l'exécution séquentielle de vos instructions. Au final de l'exécution des lignes de code proposées à titre d'exemple, l'état de la pile sera donc revenue dans son état initiale, et les variables locales manipulées seront donc définitivement perdues. Notez bien qu'à partir de la ligne 6, la variable b est perdue et ne sera donc plus accessible. Si vous tentez néanmoins de la manipuler, le compilateur Java vous renverra une erreur de compilation.

L'instruction if

L'instruction if permet de déclencher des traitements en fonction du résultat calculé par une expression de test. Contrairement à certains langages (Pascal notamment), il n'y a pas de mot clé then utilisé en Java. Du coup, pour séparer la condition du code à exécuter, il faut complétement parenthéser la condition (si vous ne respectez pas cette règle, une erreur vous sera retournée). Vous pouvez passer un bloc d'instruction à$ exécuter dans le cas ou la condition est vrai. Vous pouvez aussi, mais cela est facultatif, pas un bloc d'instructions à exécuter dans le cas ou la condition est fausse. Dans ce cas, séparer les deux blocs d'instruction via le mot clé else. Voici quelques exemples d'utilisation de l'instruction if.

 
01 // Un exemple sans partie else
02 System.out.print( "Veuillez saisir une valeur : ");
03 int a = Integer.parseInt( System.console().readLine() );
04 if ( a < 0 ) {
05     System.out.println( "La valeur est négative" );
06 }
07 
08 
09 // Un exemple avec une partie else
10 System.out.print( "Veuillez saisir une valeur : ");
11 int a = Integer.parseInt( System.console().readLine() );
12 if ( a < 0 ) {
13     System.out.println( "La valeur est négative" );
14 } else {
15     System.out.println( "La valeur est positive" );
16 }

RAPPEL : la méthode System.console().readLine() ne fonctionnera pas si vous lancez l'application directement à partir de l'atelier Eclipse (l'appel à console() renverra null). Il vous faut donc tester ce type de code directement à partir d'un console shell.

ATTENTION : si vous êtes déjà programmeur C ou C++, faites bien attention à un point de détails qui pourrait néanmoins vous bloquer quelques instants. En C (et donc en C++) il n'y a pas de type booléen à proprement parlé. En fait un booléen est un entier. Si la valeur vaut 0, on assimile cette valeur à l'état faux et toutes les autres valeurs représentent alors l'état vrai. Il est donc courant de voir en C des instructions if dont la condition de test calcule une donnée entière. Cela ne marche pas en Java. Le contrôle de typage effectué par le compilateur étant plus stricte, la condition du if doit obligatoirement renvoyer soit la valeur true, soit la valeur false. Dans tout autre cas, une erreur de compilation sera générée.

Notez un point de syntaxe, que nous ne recommandons néanmoins pas ! Mais il est possible, et ce pour les deux blocs d'instructions portés par le if et le else, de ne pas utiliser les caractères { et } dès lors qu'il y a qu'une unique instruction par bloc. Ainsi, le code proposé ci-dessus pourrait aussi s'écrire :

  
01 System.out.print( "Veuillez saisir une valeur : ");
02 int a = Integer.parseInt( System.console().readLine() );
03 if ( a < 0 )
04     System.out.println( "La valeur est négative" );
05 else
06     System.out.println( "La valeur est positive" );

Mais si une deuxième instruction doit être ajoutée au if ou au else, les accolades redeviennent obligatoire (Sans quoi des erreurs de compilations, ou pire, d'exécution, peuvent en résulter). En conséquence, et pour plus d'évolutivité, nous vous conseillons de toujours mettre les accolades. Notez aussi que l'utilisation des tabulations (retrait sur la droite) est importante pour une meilleure assimilation des lignes de code proposées. Néanmoins, si vous n'utilisez pas de tabulations, le code s'exécutera tout aussi bien.

Petit complément d'information pour les utilisateur de l'IDE (Integrated development environment) Eclipse : cet atelier, mais aussi certains autres, fourni le concept de template (à ne pas confondre avec les templates C++). Un template est un modèle de code qui est enregistré dans l'IDE. Ce modèle de code est associé à un nom et il sera possible, durant l'édition de vos codes, d'utiliser ce nom pour y injecter la séquence de code associé. Il vous est, de plus, possible de définir vos propres templates (modèles) de code. Pour obtenir la boîte de dialogue de configuration des templates, ouvrez le menu "Window", puis cliquez sur "Preferences". La boîte de dialogue d'édition des préférences s'ouvre : dans l'arborescence (partie gauche), sélectionnez le noeud "Java/Editor/Templates". Vous pourrez y voir les templates déjà existant (syse, syso, main, if, ifelse, ...) et ajouter les votre. La capture d'écran ci-dessous vous montre les deux définitions de templates relatives à l'instruction if.


Les templates de code de l'IDE Eclipse

Donc pour injecter le squelete d'une instruction if avec une partie else, placez-vous à l'endroit souhaité, tapez-y le nom du template souhaité (ici ifelse) puis appuyez simultanément sur les touches CTRL et ESPACE. Ce nom du template doit normalement être remplacé par le code Java équivalent.

L'instruction switch

L'instruction switch permet elle aussi de déclencher des traitements en fonction d'une condition (d'un test). D'un certain point de vue, cette instruction est similaire à plusieurs if imbriqués. Néanmoins les performances sont souvent meilleures avec un switch (un tableau de pointeurs d'adresses de code à exécuter est calculé une fois pour toute). Du moins s'il y a plus de deux cas distincts.

La sélection du bloc d'instruction à exécuter s'effectue grâce à la valeur d'une expression. Cette expression doit calculer une valeur dont le type fait partie de la liste suivante : byte, short, int, long ou type énumérés. Notez qu'une valeur de type boolean n'est pas autorisée. Notez aussi que le bloc d'instruction à exécuter ne nécessite pas d'accolades.

L'utilisation de l'instruction switch est souvent couplée à l'instruction break. Effectivement, si un bloc d'instructions est exécuté et si celui-ci ne se temine pas par l'instruction break, alors l'exécution du bloc suivant (dans l'ordre de déclaration) sera lancé et ainsi de suite. Cela est pratique pour définir un même traitement pour plusieurs cas. Voici un petit exemple d'utilisation d'un switch.

  
01 public class TestStatements {
02 
03     public static void main( String[] args ) {
04         
05         for( int i = 0; i < 10; i++ ) {
06             switch( i ) {
07                 case 9:
08                     System.out.println( "Neuf" );
09                     break;
10                 case 8:
11                     System.out.print( "Huit" );
12                     System.out.println( "" );
13                     break;
14                 case 7:
15                     System.out.print( "Sept" );
16                     System.out.println( "" );
17                     break;
18                 case 6:
19                     System.out.print( "Six " );
20                 case 5:
21                     System.out.println( "Cinq" );
22                     break;
23                 case 4:
24                 case 3:
25                     System.out.print( "Quatre Trois " );
26                 case 2:
27                     System.out.println( "Deux" );
28                     break;
29                 case 1:
30                     System.out.println( "Un" );
31                     break;
32                 default:
33                     System.out.println( "Zero" );
34                     break;
35             }
36         }
37     }
38 }
39 
40 /*
41  * Les résultats produits sont les suivants :
42  * 
43  *  $> javac Switch.java
44  *  $> java Switch 
45  *  Zero
46  *  Un
47  *  Deux
48  *  Quatre Trois Deux
49  *  Quatre Trois Deux
50  *  Cinq
51  *  Six Cinq 
52  *  Sept
53  *  Huit
54  *  Neuf
55  *  $>
56  */

Petit complément d'information pour les utilisateur de l'IDE Eclipse : tout comme pour l'instruction if, il existe un template permettant de générer un squelete d'instruction switch. Pour obtenir cette possibilité, commencez à tapez le mot switch à l'endroit souhaité puis, encore une fois, appuyez simultanément sur CTRL et ESPACE : vous devriez pouvoir activer le template et générer la séquence de code souhaitée.

Les instructions liées aux boucles

Comme nous allons maintenant le voir, il existe quelques instructions qui nous permettent de mettre en place des boucles (ou des itérations, c'est la même chose) et d'en contrôler leurs exécutions. Trois styles de boucles sont utilisables, et deux instructions permettent de débrancher l'exécution à l'intérieur d'une boucle. Etudions cela de plus près

La boucle for

Cette deuxième instruction permet de définir ce que l'on appelle des boucles. Pour un peu mieux comprendre les choses, je vais tenter de vous expliquer ce qu'est une boucle en informatique. Certaines actions nécessite un traitement dit itératif (c'est à dire répétitif) : une même action doit être appliquée jusqu'à obtention d'une condition d'arrêt (on ne voudrais pas que le traitement soit de durée infinie). Pour imager le concept, imaginons une personne sur une chaîne de fabrication qui attends désespérément l'heure de rentrer chez elle. De manière analogue, un programme peut avoir besoin d'effectuer une itération sur un traitement, et comme le programme doit se terminer, il nous faut matérialiser un cas d'arrêt. L'instruction for permet de réaliser cela très simplement. D'autres instructions permettent aussi de créer des boucles, nous les verrons après.

Pour en revenir au for, son utilisation est vraiment très simple. Vous introduisez l'instruction par le mot clé for, puis vous devez fournir trois expressions (elles seront toutes les trois séparées les unes des autres par des points-virgules, et mises entre parenthèses) suivies d'une instruction qui constituera le traitement à répéter. Pour ce qui est des trois expressions, pas de panique : c'est vraiment simple. Elles servent à manipuler des variables qui vont être utiles pour la boucle. La première sert à initialiser ces variables. Pour ceux qui se demandent comment initialiser trois variables avec une expression, rappelez vous que l'on a la possibilité de construire une expression à partir de sous expressions grâce au séparateur d'expressions. La deuxième permet de déterminer la condition de rebouclage à partir de l'état des variables utilisées : si cette condition n'est pas réalisée, on stop l'itération. Enfin, la dernière sert à modifier l'état des variables après chaque itérations.

Fichier "Essai.java"
public class Essai {
    public static void main(String args[]) {
	// On veut réaliser 10 affichages

	for(int i=0;i<10;i++) System.out.println("i vaut : " + i);
    }
}

Remarquez que le dernier exemple sert à définir une boucle infinie : cela peut être utile dans certains cas très particuliers. Autre remarque devant être signalée, la deuxième expression est forcément de type booléenne, la valeur false assurant la sortie de la boucle. A titre d'exemple, voici un petit programme qui calcul la somme des dix premiers entiers positifs et l'affiche. Certes on aurait pu mettre que somme valait 1+2+3+4+5+6+7+8+8+9+10, mais imaginez vous l'expression que vous auriez du donner si j'avais demandé la somme des dix mille premiers entiers. Une boucle est alors la seule alternative sérieuse.

Fichier "TenCounter.java"
public class TenCounter {
    public static void main(String args[]){
        int somme=0;

        for(int indice=1;indice<=10;indice++) somme += indice;
        
        String str = "La somme des dix premiers entiers positifs est : ";
        System.out.println(str + somme);
    }
}

La boucle while

Cette instruction permet elle aussi de définir des boucles, mais la syntaxe diffère. Pour ceux qui se demandent pourquoi avoir plusieurs constructions possibles pour les boucles, je répondrais que selon les cas il y en a qui sont plus adaptées que les autres. La syntaxe du while est la suivante : l'instruction commence par le mot clé while suivie d'une expression booléenne parenthésée et d'une instruction. L'expression sert à déterminer s'il faut encore effectuer une itération, ou bien passer à l'instruction suivant la boucle. L'instruction de la boucle, elle est exécutée à chaque étape de la boucle. Pour mieux voir les choses, reprenons l'exemple précédent (la somme des dix premiers entiers positifs), et réécrivons le avec le while. En voici le code.

Fichier "TenCounter.java"
public class TenCounter {
    public static void main(String args[]){
        int somme=0, indice=1;

        while(indice<=10) somme += indice++;

        String str = "La somme des dix premiers entiers positifs est : ";
        System.out.println(str + somme);
    }
}

Dans tout les cas, on retrouve l'initialisation de la variable indice, mais elle est située en dehors de la boucle, on retrouve aussi l'incrémentation, mais celle-ci est maintenant placée dans la partie des choses à faire à chaque tour de boucle. Le résultat lui reste strictement le même.

La boucle do while

Cette instruction a un fonctionnement quasi identique à la précédente. La différence essentielle réside dans le fait que l'on commence par calculer l'expression correspondante au test ou bien que l'on commence à exécuter l'instruction. Au point de vue de la syntaxe, on introduit l'instruction par le mot clé do que l'on fait suivre d'une instruction (le corps de la boucle, qui sera la première chose qui sera lancée), puis du mot clé while, lui même suivit d'une expression parenthésée. Cette dernière constitue la condition de rebouclage (la valeur false assurant la fin de la boucle). A titre d'exemple voici encore un programme calculant la somme des dix premiers entiers positifs.

Fichier "TenCounter.java"
public class TenCounter {
    public static void main(String args[]){
        int somme=0, indice=1;

        do 
	    somme+=indice++;
        while(indice<=10);

        String str = "La somme des dix premiers entiers positifs est : ";
        System.out.println(str + somme);
    }
}

Nous en avons maintenant finit des instructions de boucles. Cependant, deux autres instructions sont tout de même très pratiques pour contrôler ce qui se passe durant l'exécution d'une boucle. Il s'agit de continue et de break dont une petite description suit.

L'instruction continue

L'instruction continue permet d'arrêter le traitement pour l'itération en cours, et d'en recommencer immédiatement une nouvelle. Passons tout de suite à un exemple, histoire de mieux comprendre les choses. Supposons que l'on ait besoin de calculer la somme des dix premiers entiers positifs, excepté pour l'entier 5. Un code Java possible est alors ...

Fichier "TenCounterMinusFive.java"
public class TenCounterMinusFive {
    public static void main(String args[]){
        int somme=0, indice=1;

        while(indice<11) {
	     if (indice==5) { indice++;   continue; }
             else somme += indice++;
        }

        String str = "La somme des dix premiers entiers positifs (privé de 5) est : ";
        System.out.println(str + somme);
    }
}

Si vous exécutez ce code, le résultat affiché vaudra 50 (soit 55 moins la valeur du cinquième entier, soit 5). Il faut bien comprendre deux choses. Premièrement, quoi que l'on puisse mettre après le continue, ce code ne sera pas exécuté. Deuxièmement, un continue doit forcément être placé dans une branche d'un test conditionnel, sans quoi ça n'a pas de sens. Pour mieux comprendre ce dernier point, méditez sur le bout de programme suivant.

while(a<1000) {
    a++;
    continue;
   
    // Tout le code qui suit ne sera JAMAIS exécuté.
    // Alors pourquoi l'avoir mit ?? Il est donc clair que ce
    // programme ne compilera pas.
    b = a+2;
}

On peut encore faire plus compliqué avec cette instruction. Elle peut permettre de reprendre l'exécution en un point précis du programme. De tels points d'un programme sont nommés des labels (ou étiquettes). Au point de vue de la syntaxe, on définit un label par un identificateur immédiatement suivit d'un deux-points (par exemple, labelName:). Le programme suivant à pour but de mieux vous faire comprendre ce qui se passe (un exemple d'exécution y est joint).

Fichier "Continue.java"
public class Continue {
    public static void main(String args[]){
        int a, b=0, s=0;

        while(b < 5) {
            a=0;   b++;
            while(a < 5) {
                a++;
                if (a == 3) continue;
                else s++;
            }
        }
	System.out.println("Somme calculée avec \"continue;\" : " + s);

        b = s = 0;
label1: while(b < 5) {
            a=0;   b++;
            while(a < 5) {
                a++;
		if (a==3) continue label1;
		else s++;
	    }
	}
	System.out.println("Somme calculée avec \"continue label1:\" : " +s);
    } 
}
Résultats
> javac Continue.java
> java Continue
Somme caculée avec "continue;" : 20
Somme caculée avec "continue label1;" : 10
>

Le résultat obtenu était tout à fait prévisible. En effet, dans le premier cas, on esquive seulement cinq incrémentations de la variable s. Dans le second bloc de boucles, les choses se compliquent, car dés lors que a vaut 3, on esquive toutes les incrémentations suivantes pour l'itération sur b en cours. Du coup, le résultat en est sévèrement altéré. Il existe une autre instruction qui permet d'effectuer un débranchement au sein des boucles en voici une brève présentation.

L'instruction break

Cette instruction permet donc aussi de faire un débranchement au sein d'une boucle, mais contrairement à l'instruction précédente, l'exécution se poursuit non pas par une nouvelle itération, mais par l'instruction suivant la boucle. Elle sert donc purement et simplement à stopper la boucle de façon définitive. Le programme suivant illustre mes propos.

Fichier "Break.java"
public class Break {
    public static void main(String args[]){
        int somme=0, indice=1;

        while(indice<=10) {
	    if (indice==5) break;
	    somme += indice++;
	}

	System.out.println("Le résultat vaut : "+somme);
    }
}

Le résultat vaut bien évidement 10. Dernière remarque au sujet de cette instruction : on peut aussi interrompre une boucle et reprendre au label spécifié (de même que l'instruction continue).



Les opérateurs Programmation Orientée Objet