VI. Chapitre 4. Briques de base Java▲
Tu peux ajouter n'importe quels commentaires textuels à ton programme pour expliquer à quoi servent une ligne, une méthode ou une classe particulière. Tout d'abord, il arrive qu'on oublie pourquoi on a écrit un programme de cette façon. Ensuite, les commentaires aident les autres programmeurs à comprendre ton code.
VI-A. Commentaires de programme▲
Il y a trois types de commentaires différents :
- Si tes commentaires tiennent sur une ligne, commence-les par deux barres obliques (slashs) :
// Cette méthode calcule la distance
- Les commentaires s'étendant sur plusieurs lignes doivent être entourés par les symboles /* et */, par exemple :
/* les 3 lignes suivantes enregistrent
la position courante du Poisson.
*/
- Java est fourni avec un programme spécial, javadoc, qui peut extraire certains des commentaires de tes programmes dans un fichier d'aide séparé. Ce fichier peut être utilisé comme documentation technique de tes programmes. Ces commentaires sont entourés par les symboles /** et */. Seuls les commentaires les plus importants, comme la description d'une classe ou d'une méthode, devraient être repérés ainsi.
/** Cette méthode calcule la remise en fonction du prix.
Si le prix est supérieur à 100 €, la remise est de
20%, sinon, elle est seulement de 10%.
*/
A partir de maintenant, j'ajouterai des commentaires aux exemples de code pour que tu comprennes mieux comment et où les utiliser.
VI-B. Prises de décisions à l'aide de la clause if▲
Nous prenons sans arrêt des décisions dans la vie : Si elle me dit ceci, je lui répondrai cela ; sinon, je ferai autre chose. Java possède une clause qui évalue une expression donnée pour savoir si sa valeur est true ou false.
Selon la valeur de cette expression, l'exécution de ton programme prend une direction ou une autre ; seule la portion de code correspondante est exécutée. Par exemple, si l'expression Ai-je envie d'aller voir grand-mère ? retourne true, tourne à gauche, sinon, tourne à droite. |
Si l'expression retourne true, Java exécute le code compris entre les deux premières accolades, sinon, il va directement au code suivant la clause else. Par exemple, si un prix est supérieur à cent euros, donner une remise de 20%, sinon, ne donner que 10%.
// Les biens les plus chers donnent une remise de 20%
if
(
prix >
100
) {
prix =
prix *
0.8
;
System.out.println
(
"Tu as 20% de remise"
);
}
else
{
prix =
prix *
0.9
;
System.out.println
(
"Tu as 10% de remise"
);
}
Modifions la méthode plonger() de la classe Poisson pour que notre poisson ne puisse pas plonger plus profond que 100 mètres :
public
class
Poisson extends
AnimalFamilier {
int
profondeurCourante =
0
;
public
int
plonger
(
int
combienDePlus) {
profondeurCourante =
profondeurCourante +
combienDePlus;
if
(
profondeurCourante >
100
) {
System.out.println
(
"Je suis un petit "
+
" poisson et je ne peux pas plonger"
+
" plus profond que 100 mètres"
);
profondeurCourante =
profondeurCourante
-
combienDePlus;
}
else
{
System.out.println
(
"Plongée de "
+
combienDePlus
+
" mètres"
);
System.out.println
(
"Je suis à "
+
profondeurCourante
+
" mètres sous le niveau de la mer"
);
}
return
profondeurCourante;
}
public
String dire
(
String unMot) {
return
"Ne sais-tu pas que les poissons ne"
+
" parlent pas ?"
;
}
}
Effectuons ensuite une petite modification de MaîtrePoisson - laissons-le essayer de faire plonger notre poisson très profond :
public
class
MaîtrePoisson {
public
static
void
main
(
String[] args) {
Poisson monPoisson =
new
Poisson
(
);
// Essayons de plonger plus profond que 100 mètres
monPoisson.plonger
(
2
);
monPoisson.plonger
(
97
);
monPoisson.plonger
(
3
);
monPoisson.dormir
(
);
}
}
Exécute ce programme et il affichera ceci :
Plongée de 2 mètres
Je suis à 2 mètres sous le niveau de la mer
Plongée de 97 mètres
Je suis à 99 mètres sous le niveau de la mer
Je suis un petit poisson et je ne peux pas plonger plus profond que 100 mètres
Bonne nuit, à demain
VI-C. Opérateurs logiques▲
Parfois, pour prendre une décision, il peut être nécessaire de vérifier plus d'une expression conditionnelle. Par exemple, si le nom d'un état est "Texas" ou "Californie", ajouter la taxe d'état au prix de chaque article du magasin. C'est un cas d'emploi du ou logique (logical or ) - soit "Texas" soit "Californie". En Java, un ou logique est représenté par une ou deux barres verticales. Ca fonctionne comme ceci : si l'une quelconque des conditions est vraie, le résultat de l'expression dans son ensemble vaut true. Dans les exemples suivants, j'utilise une variable de type String. Cette classe Java possède une méthode equals() que j'utilise pour comparer la valeur de la variable état avec "Texas" ou "Californie" :
if
(
état.equals
(
"Texas"
) |
état.equals
(
"Californie"
))
Tu peux aussi écrire ceci en utilisant deux barres verticales :
if
(
état.equals
(
"Texas"
) ||
état.equals
(
"Californie"
))
La différence entre les deux est que, si tu utilises deux barres et que la première expression est vraie, la seconde expression ne sera même pas évaluée. Si tu ne mets qu'une seule barre, Java évalue les deux expressions.
Le et logique (logical and) est représenté par un ou deux "et commercial" (&&) et l'expression dans son ensemble vaut true si chacune de ses parties vaut true. Par exemple, imputer les taxes commerciales uniquement dans le cas où l'état est "New York" et où le prix est supérieur à 110. Les deux conditions doivent être vraies en même temps :
if
(
état.equals
(
"New York"
) &&
prix >
110
)
ou
if
(
état.equals
(
"New York"
) &
prix >
110
)
Si tu utilises un double "et commercial" et que la première expression vaut false, la seconde ne sera même pas évaluée, car l'expression entière vaudra false de toutes façons. Avec un simple "et commercial", les deux expressions seront évaluées.
Le non logique (logical not) est représenté par le point d'exclamation et donne à l'expression le sens opposé. Par exemple, si tu veux effectuer certaines actions uniquement si l'état n'est pas "New York", utilise cette syntaxe :
if
(!
état.equals
(
"New York"
))
Voici un autre exemple - les deux expressions suivantes produiront le même résultat :
if
(
prix <
50
)
if
(!(
prix >=
50
))
Le non logique est ici appliqué à l'expression entre parenthèses.
VI-D. Opérateur conditionnel▲
Il existe une autre forme de la clause if : l'opérateur conditionnel. On l'utilise pour affecter une valeur à une variable en fonction d'une expression terminée par un point d'interrogation. Si l'expression est vraie, la valeur suivant le point d'interrogation est utilisée ; sinon, la valeur suivant les deux points est affectée à la variable située à gauche du signe égal :
remise =
prix >
50
? 10
: 5
;
Si le prix est supérieur à 50, la variable remise prend la valeur 10 ; sinon, elle vaut 5. C'est juste un raccourci pour exprimer une clause if normale :
if
(
prix >
50
) {
remise =
10
;
}
else
{
remise =
5
;
}
VI-E. Utilisation de else if▲
Tu peux construire des clauses if plus complexes avec plusieurs blocs else if. Nous allons maintenant créer la classe BulletinAppréciation. Cette classe doit avoir la méthode main() ainsi qu'une méthode acceptant un argument - la note du devoir. En fonction du nombre, cette méthode affichera ton niveau sous la forme I (Insuffisant), P (Passable), A (Assez bien), B (Bien), T (Très bien) ou E (Excellent). Nous la nommerons convertirNiveaux().
public
class
BulletinAppréciation {
/**
* Cette méthode attend un argument entier - la note du devoir -
* et retourne une mention, I, P, A, B, T ou E, en fonction de sa valeur.
*/
public
char
convertirNiveaux
(
int
noteDevoir) {
char
niveau;
if
(
noteDevoir >=
18
) {
niveau =
'E'
;
}
else
if
(
noteDevoir >=
16
&&
noteDevoir <
18
) {
niveau =
'T'
;
}
else
if
(
noteDevoir >=
14
&&
noteDevoir <
16
) {
niveau =
'B'
;
}
else
if
(
noteDevoir >=
12
&&
noteDevoir <
14
) {
niveau =
'A'
;
}
else
if
(
noteDevoir >=
10
&&
noteDevoir <
12
) {
niveau =
'P'
;
}
else
{
niveau =
'I'
;
}
return
niveau;
}
public
static
void
main
(
String[] args) {
BulletinAppréciation convertisseur =
new
BulletinAppréciation
(
);
char
tonNiveau =
convertisseur.convertirNiveaux
(
17
);
System.out.println
(
"Ton premier niveau est "
+
tonNiveau);
tonNiveau =
convertisseur.convertirNiveaux
(
15
);
System.out.println
(
"Ton second niveau est "
+
tonNiveau);
}
}
Outre l'utilisation de la condition else if, cet exemple te montre aussi comment utiliser des variables de type char. Tu peux aussi voir que tu peux utiliser l'opérateur && pour vérifier si un nombre appartient à une plage de valeurs donnée. Tu ne peux pas écrire simplement if résultatTest entre 16 et 18, mais en Java nous écrivons que résultatTest doit être à la fois supérieur ou égal à 16 et inférieur à 18 :
résultatTest >=
16
&&
résultatTest <
18
Réfléchis à la raison pour laquelle nous ne pouvons pas utiliser l'opérateur || ici.
VI-F. Prises de décisions à l'aide de la clause switch ▲
La clause switch peut parfois être utilisée comme alternative à if. L'expression après le mot-clé switch est évaluée et le programme va directement au case (cas) correspondant :
public
static
void
main
(
String[] args) {
BulletinAppréciation convertisseur =
new
BulletinAppréciation
(
);
char
tonNiveau =
convertisseur.convertirNiveaux
(
15
);
switch
(
tonNiveau) {
case
'E'
:
System.out.println
(
"Excellent travail !"
);
break
;
case
'T'
:
System.out.println
(
"Très bon travail !"
);
break
;
case
'B'
:
System.out.println
(
"Bon travail !"
);
break
;
case
'A'
:
System.out.println
(
"Tu peux mieux faire !"
);
break
;
case
'P'
:
System.out.println
(
"Tu dois travailler plus !"
);
break
;
case
'I'
:
System.out.println
(
"Change d'attitude !"
);
break
;
}
}
N'oublie pas le mot-clé break à la fin de chaque cas - il faut que le code saute hors de la clause switch. Sans les instructions break, ce code imprimerait, par exemple, les quatre dernières lignes si la variable tonNiveau avait la valeur 'B'.
La clause switch Java a une limitation - l'expression à évaluer doit être de l'un de ces types :
char
|
VI-G. Quelle est la durée de vie des variables ? ▲
La classe BulletinAppréciation déclare la variable niveau dans la méthode convertirNiveaux(). Si tu déclares une variable à l'intérieur d'une méthode, cette variable est dite locale. Cela signifie que cette variable n'est accessible que pour le code à l'intérieur de cette méthode. Quand la méthode se termine, la variable est automatiquement effacée de la mémoire.
Les programmeurs utilisent aussi le mot portée (scope) pour préciser combien de temps une variable vivra. Par exemple, tu peux dire que les variables déclarées à l'intérieur d'une méthode ont une portée locale.
Si une variable doit être réutilisée par plusieurs appels de méthode, ou si elle doit être visible par plus d'une méthode d'une classe, il est préférable de la déclarer en dehors de toute méthode. Dans la classe Poisson, profondeurCourante est une variable membre (member). De telles variables sont "vivantes" tant que l'instance de l'objet Poisson existe en mémoire ; c'est pourquoi on les appelle des variables d'instance. Elles peuvent être partagées et réutilisées par toutes les méthodes de la classe et, dans certains cas, elles peuvent même être visibles depuis des classes extérieures. Par exemple, dans nos classes, l'instruction System.out.println() utilise la variable de classe out déclarée dans la classe System.
Attends une minute ! Pouvons-nous utiliser une variable membre de la classe System sans même avoir créé une instance de cette classe ? Oui, nous le pouvons, si cette variable a été déclarée avec le mot-clé static. Si la déclaration d'une variable membre ou d'une méthode commence par static, il n'est pas nécessaire de créer une instance de la classe pour l'utiliser. Les membres statiques d'une classe sont utilisés pour stocker les valeurs qui sont identiques pour toutes les instances d'une classe.
Par exemple, la méthode convertirNiveaux() peut être déclarée comme static dans la classe BulletinAppréciation, car son code n'utilise pas de variables membres pour lire ou stocker des valeurs spécifiques à une instance particulière de la classe. Voici comment on appelle une méthode statique :
char
tonNiveau =
BulletinAppréciation.convertirNiveaux
(
15
);
Voici un autre exemple : il y a en Java une classe Math qui contient plusieurs douzaines de méthodes mathématiques telles que sqrt() (racine carrée), sin(), abs() et autres. Toutes ces méthodes sont statiques et tu n'as pas besoin de créer une instance de la classe Math pour les appeler. Par exemple :
double
racineCarrée =
Math.sqrt
(
4.0
);
VI-H. Méthodes spéciales : constructeurs▲
Java utilise l'opérateur new (nouveau) pour créer des instances d'objets en mémoire. Par exemple :
Poisson monPoisson =
new
Poisson
(
);
Les parenthèses après le mot Poisson signifient que cette classe a une méthode nommée Poisson(). Oui, il y a des méthodes spéciales appelées constructeurs (constructors), qui ont les caractéristiques suivantes :
- Les constructeurs ne sont appelés qu'une fois au cours de la construction d'un objet en mémoire.
- Ils doivent avoir le même nom que la classe elle-même.
- Ils ne retournent pas de valeur ; il n'est même pas nécessaire d'utiliser le mot-clé void dans la signature d'un constructeur.
Toute classe peut avoir plusieurs constructeurs. Si tu ne crées pas de constructeur pour une classe, Java crée automatiquement, lors de la compilation, un constructeur sans argument par défaut. C'est pour cela que le compilateur Java n'a jamais réclamé une déclaration permettant d'écrire new Poisson(), alors que la classe Poisson ne définit aucun constructeur.
En général, les constructeurs sont utilisés pour affecter des valeurs initiales aux variables membres d'une classe. Par exemple, la version suivante de la classe Poisson a un constructeur mono-argument qui se contente d'affecter la valeur de l'argument à la variable d'instance profondeurCourante pour une utilisation ultérieure.
public
class
Poisson extends
AnimalFamilier {
int
profondeurCourante;
Poisson
(
int
positionDépart) {
profondeurCourante =
positionDépart;
}
}
Maintenant, la classe MaîtrePoisson peut créer une instance de Poisson et affecter la position initiale du poisson. L'exemple suivant crée une instance de Poisson "submergée" sous 20 mètres d'eau :
Poisson monPoisson =
new
Poisson
(
20
);
Si un constructeur avec arguments est défini dans une classe, il n'est plus possible d'utiliser le constructeur sans argument par défaut. Si tu souhaites avoir un constructeur sans argument, écris-en un.
VI-I. Le mot-clé this▲
Le mot-clé this est utile lorsque tu as besoin de te référer à l'instance de l'objet dans laquelle tu te trouves. Regarde cet exemple :
class
Poisson {
int
profondeurCourante ;
Poisson
(
int
profondeurCourante) {
this
.profondeurCourante =
profondeurCourante;
}
}
Tu verras un autre exemple important de l'utilisation du mot-clé this au Chapitre 6, dans la section Comment passer des données entre classes.
VI-J. Tableaux▲
Disons que ton programme doit stocker les noms de quatre joueurs. Au lieu de déclarer quatre variables de type String, tu peux déclarer un tableau (array) qui a quatre éléments de type String.
Les tableaux sont repérés par des crochets, placés soit après le nom de la variable, soit après le type de données :
String [] joueurs;
ou
String joueurs[];
Ces lignes indiquent juste au compilateur Java que tu as l'intention de stocker plusieurs chaînes de caractères dans le tableau joueurs. Chaque élément possède son propre indice partant de zéro. L'exemple suivant crée en fait une instance de tableau qui peut stocker quatre éléments de type String puis leur affecte des valeurs :
joueurs =
new
String [4
];
joueurs[0
] =
"David"
;
joueurs[1
] =
"Daniel"
;
joueurs[2
] =
"Anna"
;
joueurs[3
] =
"Gregory"
;
Tu dois connaître la taille du tableau avant d'affecter des valeurs à ses éléments. Si tu ne sais pas à l'avance combien d'éléments tu vas avoir, tu ne peux pas utiliser de tableaux ; tu devrais examiner d'autres classes Java, par exemple Vector (vecteur). Mais concentrons-nous pour l'instant sur nos tableaux.
Tous les tableaux ont un attribut nommé length (longueur) qui se "rappelle" le nombre d'éléments de ce tableau. Tu peux donc toujours savoir combien d'éléments il y a :
int
nombreJoueurs =
joueurs.length;
Si tu connais toutes les valeurs qui seront stockées dans le tableau au moment où tu le déclares, Java te permet de déclarer et d'initialiser le tableau d'un seul coup :
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
Imagine que le second joueur soit un gagnant et que tu souhaites lui faire part de tes félicitations. Si le nom des joueurs est stocké dans un tableau, nous avons besoin de son deuxième élément :
String leGagnant =
joueurs[1
];
System.out.println
(
"Félicitations, "
+
leGagnant +
" !"
);
Voilà ce qu'affiche ce code :
Félicitations, Daniel !
Sais-tu pourquoi le deuxième élément a l'indice [1] ? Bien sûr que tu le sais : l'indice du premier élément est toujours [0].
Le tableau de joueurs de notre exemple est unidimensionnel, car nous les stockons en quelque sorte en ligne. Si nous voulons stocker les valeurs sous forme de matrice, nous pouvons créer un tableau bidimensionnel. Java permet la création de tableaux multidimensionnels. Tu peux stocker n'importe quel objet dans un tableau ; je te montrerai comment au Chapitre 10.
VI-K. Répétition d'actions à l'aide de boucles▲
Les boucles (loops) sont utilisées pour répéter la même action plusieurs fois, par exemple si nous avons besoin de féliciter plusieurs joueurs.
Si tu sais à l'avance combien de fois l'action doit être répétée, utilise une boucle avec le mot-clé for (pour) :
int
nombreJoueurs =
joueurs.length;
int
compteur;
for
(
compteur =
0
; compteur <
nombreJoueurs; compteur++
) {
String leJoueur =
joueurs[compteur];
System.out.println
(
"Félicitations, "
+
leJoueur +
" !"
);
}
Java exécute chaque ligne entre les accolades puis retourne à la première ligne de la boucle, pour incrémenter le compteur et évaluer l'expression conditionnelle. Ce code signifie ceci :
Affiche la valeur de l'élément du tableau dont l'indice est identique à la valeur courante du compteur. Commence de l'élément 0 (compteur = 0) et incrémente de 1 la valeur du compteur (compteur++). Continue à faire ainsi tant que le compteur est inférieur à nombreJoueurs (compteur < nombreJoueurs).
Il y a un autre mot-clé permettant d'écrire des boucles - while (pendant). Avec ces boucles, il n'est pas nécessaire de savoir exactement combien de fois l'action doit être répétée, mais il faut tout de même savoir à quel moment terminer la boucle. Voyons comment nous pouvons féliciter les joueurs en utilisant une boucle while qui se terminera lorsque la valeur de la variable compteur sera égale à la valeur de nombreJoueurs :
int
nombreJoueurs =
joueurs.length;
int
compteur =
0
;
while
(
compteur <
nombreJoueurs) {
String leJoueur =
joueurs[compteur];
System.out.println
(
"Félicitations, "
+
leJoueur +
" !"
);
compteur++
;
}
Au Chapitre 9, tu apprendras comment enregistrer les données sur les disques et comment les recharger dans la mémoire de l'ordinateur. Si tu charges les scores du jeu à partir d'un fichier sur le disque, tu ne sais pas à l'avance combien de scores y ont été enregistrés. Il est fort probable que tu chargeras les scores à l'aide d'une boucle while.
Tu peux aussi utiliser deux mots-clés importants dans les boucles : break et continue.
Le mot-clé break est utilisé pour sortir de la boucle quand une condition particulière est vraie. Disons que nous ne voulons pas afficher plus de 3 félicitations, indépendamment du nombre de joueurs que nous avons. Dans l'exemple suivant, après avoir affiché les éléments 0, 1 et 2 du tableau, le break fera sortir le code de la boucle et le programme continuera à partir de la ligne suivant l'accolade fermante.
Dans cet exemple de code, il y a un double signe égale dans la clause if. Cela signifie que tu compares la valeur de la variable compteur avec le nombre 3. Un seul signe égale à cet endroit signifierait qu'on affecte la valeur 3 à la variable compteur. Remplacer == par = dans une instruction if est un piège très subtil, qui peut mener à des erreurs du programme imprévisibles et difficiles à trouver.
int
compteur =
0
;
while
(
compteur <
nombreJoueurs) {
if
(
compteur ==
3
) {
break
; // Sortie de la boucle
}
String leJoueur =
joueurs[compteur];
System.out.println
(
"Félicitations, "
+
leJoueur +
" !"
);
compteur++
;
}
Le mot-clé continue permet au code de sauter des lignes et de revenir au début de la boucle. Imagine que tu veuilles féliciter tout le monde sauf David - le mot-clé continue fait revenir le programme au début de la boucle :
while
(
compteur <
nombreJoueurs) {
compteur++
;
String leJoueur =
joueurs[compteur];
if
(
leJoueur.equals
(
"David"
)) {
continue
;
}
System.out.println
(
"Félicitations, "
+
leJoueur +
" !"
);
}
Il y a encore une autre forme de la boucle while, qui commence par le mot-clé do :
do
{
// Place ton code à cet endroit
}
while
(
compteur <
nombreJoueurs);
Une telle boucle évalue l'expression après avoir exécuté le code entre les accolades, ce qui signifie que le code à l'intérieur de la boucle est exécuté au moins une fois. Les boucles qui commencent par le mot-clé while peuvent ne pas être exécutées du tout si l'expression conditionnelle est fausse dès le début.
VI-L. Autres lectures▲
1. jGuru: Language Essentials. Short Course: (5)http://java.sun.com/ (...) /contents.html 2. Portée des variables:http://java.sun.com/ (...) /scope.html |
VI-M. Exercices▲
VI-N. Exercices pour les petits malins▲
As-tu remarqué que dans l'exemple avec le mot-clé continue nous avons remonté la ligne compteur++; ? Que ce serait-il passé si nous avions laissé cette ligne à la fin de la boucle comme dans l'exemple avec break ? |