Nous décrivons maintenant ce qui se trouve dans le corps des méthodes, c’est-à-dire le code qui fait le vrai travail. Le corps d’une méthode est une séquence d’instructions). Les instructions sont exécutées. Une instruction (par ex. une affectation) peut inclure une expression. Les expressions sont évaluées en un résultat.
La distinction entre expressions (dont l’évaluation produit un résultat) et instructions (dont l’exécution ne produit rien) est assez hypocrite, car toute expression suivie de « ; » devient une instruction (le résultat est jeté).
Les expressions les plus courantes sont :
1
(entier), true
(booléen),
"coucou !"
(chaîne), etc.
Une constante amusante est null
, qui est un objet sans champs
ni méthodes.this
désigne l’objet dont on a appelé la méthode.
Dans un constructeur, this
désigne l’objet en cours de construction.
Il en résulte que this
n’est jamais null
,
car si on en est arrivé à exécuter un corps de méthode, c’est bien
que l’objet dont a appelé la méthode existait.void
, son appel
n’est pas vraiment une expression, c’est une instruction.i+1
(addition) ou
i == 1 || i == 2
(opérateur égalité et opérateur ou logique).
Quelques opérateurs inattendus sont donnés en B.7.2.
Notons qu’un « opérateur » en informatique est simplement
une fonction dont l’application se fait par une syntaxe spéciale.
L’application des opérateurs est souvent infixe,
c’est-à-dire que l’opérateur apparaît entre ses arguments.
Mais elle
peut être préfixe, c’est-à-dire que l’opérateur est
avant son argument, comme dans le cas de la négation des
booléens !
; ou encore postfixe, comme pour
l’opérateur de post-incrément i++
.
En Java, comme souvent, les opérateurs eux-mêmes sont exclusivement
composés de caractères non alphabétiques (+, -, =, etc.).t[i]
, où t
est un tableau défini par ailleurs.
Il n’est pas surprenant que l’on puisse mettre une expression
à la place de i
. Il est
un peu plus surprenant que cela soit également le cas pour t
,
comme par exemple dans t[i][j]
, à comprendre comme
(t[i])[j]
(t
est un tableau de tableaux).i = 1
, l’expression à droite de
=
est calculée sa valeur est rangée dans la variable
donnée à gauche de =
. En fait, on peut trouver autre chose
qu’une variable à gauche de =
, on peut trouver tout ce qui
désigne une case de mémoire, par exemple, un élément de tableau
t[i]
ou une désignation de champ objet.x.L’affectation est une expression dont le résultat est la valeur
affectée. Ce qui permet des trucs du genre i = j = 0
, pour
initialiser i
et j
à zéro.
Cela se comprend si on lit cette expression comme
i = (j = 0)
.
(i == 1) || (i == 2)
, c’est peut-être plus lisible
que i == 1 || i == 2
.
Java a beaucoup emprunté au langage C, il reprend quelques expressions assez peu ordinaires.
i
variable de type entier (en fait, soit e désignation
de case mémoire qui contient un entier). Alors l’expression
i++
range i+1
dans i
et renvoie l’ancienne valeur
de i
. L’expression i--
fait la même chose avec
i-1
.
Enfin l’expression ++i
(resp. --i
) est similaire,
mais elle renvoie la valeur incrémentée (resp. décrémentée) de
i
en résultat.i
op=
expression est
sensiblement équivalente à i = i
op
expression.
Par exemple:
i
dans i
et renvoie donc
ce contenu doublé.
Les finauds noteront que ++i
est aussi i += 1
.
Ces expressions avancées sont géniales, mais il est de bon goût de les
employer avec parcimonie.
Que l’on essaie de deviner ce que fait t[++i] *= --t[i++]
et on
comprendra.
Les instructions les plus courantes sont les suivantes:
{
…}
.
La portée des déclaration internes au bloc s’éteint à la sortie du bloc.
Par exemple, le programme
i=1
puis une seconde i=0
.
Il faut bien comprendre que d’un affichage à l’autre l’usage de
variable « i
» ne fait pas référence à la même variable.
Lorsque l’on veut savoir à quelle déclaration correspond un usage, la
règle est de remonter le source du regard vers le haut, jusqu’à
trouver la bonne déclaration. C’est ce que l’on appelle parfois,
la portée lexicale.Attention, seule la portée des variables est limitée par les blocs, en revanche l’effet des instruction passe allègrement les frontières de blocs. Par exemple, le programme
affiche deux lignes i=1
.
return
expression;
»,
où expression est une expression dont le type est celui des
valeurs retournées par la méthode.Par exemple, la méthode twice qui double son argument entier s’écrit
Si la méthode ne renvoie rien, alors return
n’a pas
d’argument.
À noter que, si la dernière instruction d’une méthode est
return ;
(sans argument), alors on peut l’omettre. De sorte que
la méthode rien s’écrit aussi :
if
:
byte
à long
, mais aussi char
). Par
exemple :
i
on sélectionnera l’une des trois
clauses case
, ou la clause par défaut default
.
Il faut surtout noter le break
, qui renvoie le contrôle à
la fin du switch
. En l’absence de break
l’exécution se
poursuit en séquence, donc la clause suivante est exécutée.
Ainsi si on omet les break
et que i
vaut -1
on a
l’affichage
moins un zéro un beaucoupCette abominable particularité permet de grouper un peu les cas. Par exemple,
return
, alors
break
n’est pas utile.
while (
expression)
instruction,
on exécute expression, qui est une expression booléenne, si le
résultat est false
c’est fini, sinon on exécute
instruction et on recommence.boolean
,
c’est la condition testée avant chaque itération (y compris la
première), l’itération a lieu si econd
vaut true
.
Enfin, enext est évaluée à la fin de chaque
itération.
Autrement dit une boucle for
est presque la
même chose que la boucle while
suivante.
Ainsi pour rechercher si l’entier foo est présent dans le tableau t, on peut écrire
Ou encore, si on veut cette fois compter les occurrences de foo dans t, on peut écrire
Noter que dans les deux cas on fait des choses un peu compliquées. Dans le premier cas, on pourrait faire une méthode et utiliser return, ou une boucle while sur trouve. Dans le second cas, on pourrait écrire le test d’égalité. Dans certaines situations, ces instructions sont pratiques (break plus fréquemment que continue).