Vous êtes sur la page 1sur 70

INTRODUCTION

AU
LANGAGE JAVA
LICENCE 1, INFORMATIQUE, RESEAUX ET
TELECOMMUNICATIONS

GBEDEVI AKOUYO YVETTE


INGENIEUR LOGICIEL ET NLP | ESGIS
Objectifs

· Décrire les éléments-clé de la plate-forme Java


· Compiler et exécuter une application Java
· Comprendre et utiliser la documentation en ligne de Java
· Décrire la syntaxe du langage
· Comprendre le paradigme OO et utiliser Java pour le mettre en œuvre
· Comprendre et utiliser les exceptions

1
Chapitre 0
Présentation de Java
Après un très bref historique du langage Java montrant dans quel esprit il a été créé, nous en
présenterons les principales caractéristiques. Nous verrons tout d’abord que Java est un langage objet
et nous exposerons les concepts majeurs de la programmation orientée objet. Puis nous ferons la
distinction entre les programmes utilisant une interface console et les programmes utilisant une
interface graphique, ce qui nous amènera à parler des possibilités de programmation événementielle
qui sont offertes par Java sous la forme de classes standard. Enfin, nous montrerons que Java est le
premier langage à offrir une portabilité aussi avancée.

1. Petit historique du langage


On peut faire remonter la naissance de Java à 1991. À cette époque, des ingénieurs de chez SUN ont
cherché à concevoir un langage applicable à de petits appareils électriques (on parle de code
embarqué). Pour ce faire, ils se sont fondés sur une syntaxe très proche de celle de C++, en reprenant
le concept de machine virtuelle déjà exploité auparavant par le Pascal UCSD. L’idée consistait à
traduire d’abord un programme source, non pas directement en langage machine, mais dans un
pseudo langage universel, disposant des fonctionnalités communes à toutes les machines. Ce code
intermédiaire, dont on dit qu’il est formé de byte code, se trouve ainsi compact et portable sur
n’importe quelle machine ; il suffit simplement que cette dernière dispose d’un programme
approprié (on parle alors de machine virtuelle) permettant de l’interpréter dans le langage de la
machine concernée.
En fait, ce projet de langage pour code embarqué n’a pas abouti en tant que tel. Mais ces concepts
ont été repris en 1995 dans la réalisation du logiciel HotJava, un navigateur Web écrit par SUN en
Java, et capable d’exécuter des applets écrits précisément en byte codes.
Les objectifs de java sont d'être multi-plateformes et d'assurer la sécurité aussi bien pendant le
développement que pendant l'utilisation d'un programme java. Il est en passe de détrôner le langage
C++ dont il hérite partiellement la syntaxe mais non ses défauts. Comme C++ et Delphi, java est
algorithmique et orienté objet à ce titre il peut effectuer comme ses compagnons, toutes les tâches
d'un tel langage (bureautiques, graphiques, multimédias, bases de données, environnement de
développement, etc...). Son point fort qui le démarque des autres est sa portabilité due (en théorie) à

2
ses bibliothèques de classes indépendantes de la plate-forme, ce qui est le point essentiel de la
programmation sur internet ou plusieurs machines dissemblables sont interconnectées.
La réalisation multi-plateformes dépend en fait du système d'exploitation et de sa capacité à posséder
des outils de compilation et d'interprétation de la machine virtuelle Java.
En Java l'on développe deux genres de programmes :

● Les applications qui sont des logiciels classiques s'exécutant directement sur une plate-
forme spécifique soit à travers une machine virtuelle java soit directement en code
exécutable par le système d'exploitation. (code natif).
● Les applets sont des programmes java insérés dans un document HTML s'exécutant à
travers la machine virtuelle java du navigateur lisant le document HTML.
● Des applications pour appareils mobiles, avec J2ME ;
● et bien d'autres ! Java EE, JMF, J3D pour la 3D…

2. Java et la programmation objet


La P.O.O. (programmation orientée objet) possède de nombreuses vertus universellement
reconnues désormais. Notamment, elle ne renie pas la programmation structurée (elle se fonde sur
elle), elle contribue à la fiabilité des logiciels et elle facilite la réutilisation de code existant. Elle
introduit de nouveaux concepts, en particulier ceux d’objets, d’encapsulation, de classe et d’héritage.
2.1. Les concepts d’objet et d’encapsulation

En programmation structurée, un programme est formé de la réunion de différentes procédures et de


différentes structures de données généralement indépendantes de ces procédures.
En P.O.O., un programme met en œuvre différents objets. Chaque objet associe des données et des méthodes
agissant exclusivement sur les données de l’objet. Notez que le vocabulaire évolue quelque peu : on parlera de
méthodes plutôt que de procédures ; en revanche, on pourra utiliser indifféremment le mot données ou le mot
champ.
Mais cette association est plus qu’une simple juxtaposition. En effet, dans ce que l’on pourrait qualifier de
P.O.O. "pure", on réalise ce que l’on nomme une encapsulation des données. Cela signifie qu’il n’est pas
possible d’agir directement sur les données d’un objet ; il est nécessaire de passer par ses méthodes, qui jouent
ainsi le rôle d’interface obligatoire. On traduit parfois cela en disant que l’appel d’une méthode est en fait
l’envoi d’un message à l’objet.
Le grand mérite de l’encapsulation est que, vu de l’extérieur, un objet se caractérise uniquement par les
spécifications de ses méthodes, la manière dont sont réellement implantées les données étant sans importance.
On décrit souvent une telle situation en disant qu’elle réalise une abstraction des données (ce qui exprime bien
que les détails concrets d’implémentation sont cachés). À ce propos, on peut remarquer qu’en
programmation structurée, une procédure pouvait également être caractérisée (de l’extérieur) par ses
spécifications, mais que, faute d’encapsulation, l’abstraction des données n’était pas réalisée.

3
L’encapsulation des données présente un intérêt manifeste en matière de qualité de logiciel. Elle facilite
considérablement la maintenance : une modification éventuelle de la structure des données d’un objet n’a
d’incidence que sur l’objet lui-même ; les utilisateurs de l’objet ne seront pas concernés par la teneur de cette
modification (ce qui n’était bien sûr pas le cas avec la programmation structurée). De la même manière,
l’encapsulation des données facilite grandement la réutilisation d’un objet.
2.2. Le concept de classe
Le concept de classe correspond simplement à la généralisation de la notion de type que l’on
rencontre dans les langages classiques. En effet, une classe n’est rien d’autre que la descrip- tion d’un
ensemble d’objets ayant une structure de données commune et disposant des mêmes méthodes. Les
objets apparaissent alors comme des variables d’un tel type classe (en P.O.O., on dit aussi qu’un objet
est une instance de sa classe). Bien entendu, seule la structure est commune, les valeurs des champs
étant propres à chaque objet. En revanche, les métho- des sont effectivement communes à l’ensemble
des objets d’une même classe.
Lorsque, comme cela arrive parfois dans l’écriture d’interfaces graphiques, on est amené à ne créer
qu’un seul objet d’une classe donnée, la distinction entre les notions d’objet et de classe n’est pas
toujours très évidente.
En revanche, lorsque l’on dispose de plusieurs objets d’une même classe, le principe d’encapsulation
s’appliquera à la classe et non à chacune de ses instances, comme nous le verrons.
2.3. L’héritage
Un autre concept important en P.O.O. est celui d’héritage. Il permet de définir une nouvelle classe
à partir d’une classe existante (qu’on réutilise en bloc !), à laquelle on ajoute de nouvelles données et
de nouvelles méthodes. La conception de la nouvelle classe, qui hérite des propriétés et des aptitudes
de l’ancienne, peut ainsi s’appuyer sur des réalisations antérieures parfaitement au point et les
spécialiser à volonté. Comme on peut s’en douter, l’héritage facilite largement la réutilisation de
produits existants, d’autant plus qu’il peut être réitéré autant de fois que nécessaire (la classe C peut
hériter de B, qui elle-même hérite de A).
2.4. Le polymorphisme
En Java, comme généralement, en P.O.O., une classe peut "redéfinir" (c’est-à-dire modifier) certaines
des méthodes héritées de sa classe de base. Cette possibilité est la clé de ce que l’on nomme le
"polymorphisme", c’est-à-dire la possibilité de traiter de la même manière des objets de types
différents, pour peu qu’ils soient issus de classes dérivées d’une même classe de base. Plus
précisément, on utilise chaque objet comme s’il était de cette classe de base, mais son comportement
effectif dépend de sa classe effective (dérivée de cette classe de base), en particulier de la manière dont
ses propres méthodes ont été redéfinies. Le polymorphisme permet d’ajouter de nouveaux objets
dans un scénario préétabli et, éventuellement, écrit avant d’avoir connaissance du type exact de ces
objets.
2.5. Java est Presque un pur langage de POO

4
Certains langages ont été conçus pour appliquer à la lettre les principes de P.O.O. C’est notamment
le cas de Simula, Smalltalk et de Eiffel. Dans ce cas, tout est objet (ou instance de classe) et
l’encapsulation des données est absolue. Les procédures sont obligatoirement des méthodes, ce qui
revient à dire qu’il n’existe pas de procédures indépendantes, c’est-à-dire susceptibles de s’exécuter
indépendamment de tout objet.
D’autres langages, comme Pascal ou C++, ont cherché à appliquer une "philosophie objet" à un
langage classique. Les objets y cohabitent alors avec des variables usuelles. Il existe à la fois des
méthodes, applicables à un objet, et des procédures indépendantes. À la limite, on peut réaliser un
programme ne comportant aucun objet.
Java se veut un langage de la première catégorie, autrement dit un pur langage de P.O.O. Par nature,
un programme s’y trouvera formé d’une classe ou de la réunion de plusieurs classes et il instanciera
des objets. Il sera impossible de créer un programme n’utilisant aucune classe. Cependant, il faut
apporter quelques nuances qui troublent très légèrement la pureté du langage.
● Java dispose de types dits primitifs pour représenter les entiers, les flottants, les
caractères et les booléens. Les variables correspondantes ne sont pas des objets.
Certes, la plupart du temps, ces types primitifs seront utilisés pour définir les champs
d’une classe, donc finalement d’un objet ; cependant, il y aura des exceptions...
● Une classe pourra comporter des méthodes particulières dites méthodes de classe
(déclarées avec le mot-clé static) qui seront utilisables de façon indépendante d’un
objet. Comme ces méthodes peuvent déclarer localement des variables d’un type
primitif, on voit qu’on peut ainsi retrouver les possibilités des procédures ou des
fonctions des langages non objets. La seule différence (purement syntaxique) viendra
de ce que ces méthodes seront localisées artificiellement dans une classe (on verra
qu’il existe une telle méthode nommée main jouant le rôle de programme principal).
À la limite, on peut concevoir un programme ne comportant aucun objet (mais
obligatoirement au moins une classe). C’est d’ailleurs cette particularité que nous
exploiterons pour vous exposer les bases du langage, en dehors de tout contexte
objet.
● L’encapsulation se trouve naturellement induite par la syntaxe du langage mais elle
n’est pas absolue.

3. Java et la portabilité
Dans la plupart des langages, on dit qu’un programme est portable car un même code source peut
être exploité dans des environnements différents moyennant simplement une nouvelle compilation.
En Java, la portabilité va plus loin. En effet, comme nous l’avons évoqué précédemment, la
compilation d’un code source produit, non pas des instructions machine, mais un code
intermédiaire formé de byte codes. D’une part, ce code est exactement le même, quel que soit le
compilateur et l’environnement concernés. D’autre part, ces byte codes sont exécutables dans toute

5
implémentation disposant du logiciel d’interprétation nommé machine virtuelle ou, parfois, système
d’exécution Java.
De surcroît, Java définit exactement les caractéristiques des types primitifs servant à représenter les
caractères, les entiers et les flottants. Cela concerne non seulement la taille de l’emplacement
mémoire, mais aussi le comportement arithmétique correspondant. Ainsi, quelle que soit la
machine, une valeur de type float (réel) aura exactement la même taille, les mêmes limites et la même
précision. Java est ainsi le premier langage qui assure qu’un même programme, exécuté dans des
environnements différents, fournira les mêmes résultats.

6
Chapitre 1
Bases de Java
Ce chapitre constitue une première approche d’un programme Java, fondée sur quelques exemples
commentés. Vous y verrez, de manière informelle pour l’instant, comment configurer un
environnement pour faire du Java, comment s’expriment les instructions de base (déclaration,
affectation, écriture...). Cela nous permettra par la suite d’illustrer certaines notions par des
programmes complets, compréhensibles avant même que nous n’ayons effectué une étude détaillée
des instructions correspondantes.
Nous dégagerons ensuite quelques règles générales concernant l’écriture d’un programme. Enfin,
nous montrerons comment mettre en œuvre un programme Java, de sa saisie à son exécution, ce qui
vous permettra de vous familiariser avec votre propre environnement de développement.
Notez que nous exploiterons ici les possibilités de simplification présentées au chapitre précédent.
D’une part, nous nous limiterons à des programmes utilisant une interface de type console ; d’autre
part, nous ne ferons pas intervenir d’objets. Autrement dit, ce chapitre se bornera à vous montrer
comment s’expriment en Java des concepts que vous avez déjà rencontrés dans d’autres langages (C,
C++, Visual Basic, C#, PHP...).

1. Installation des outils de développement


1.1Installer le JDK ou JRE
Le JRE contient tout le nécessaire pour que vos programmes Java puissent être exécutés sur votre ordinateur ;
le JDK, en plus de contenir le JRE, contient tout le nécessaire pour développer, compiler…
Java permet de développer différents types d'applications ; il y a donc des environnements permettant de
créer des programmes pour différentes plates-formes :

● J2SE (Java 2 Standard Edition, celui qui nous intéresse dans cet ouvrage) : permet de développer des
applications dites « client lourd », par exemple Word, Excel, la suite OpenOffice.org… Toutes ces
applications sont des « clients lourds » . C'est ce que nous allons faire dans ce cours
● Java EE (Java Enterprise Edition) : permet de développer des applications web en Java. On parle aussi
de clients légers.
● J2ME (Java 2 Micro Edition) : permet de développer des applications pour appareils portables,
comme des téléphones portables, des PDA…
1.2 Les Environnements de développement intégrés (IDE)

7
❖ Eclispe IDE
« Eclipse IDE » est un environnement de développement libre permettant de créer des programmes dans de
nombreux langages de programmation (Java, C++, PHP…). C'est l'outil que nous allons utiliser pour
programmer.
Eclipse IDE est lui-même principalement écrit en Java.
La spécificité d'Eclipse IDE vient du fait que son architecture est totalement développée autour de la notion
de plugin. Cela signifie que toutes ses fonctionnalités sont développées en tant que plugins. Pour faire court,
si vous voulez ajouter des fonctionnalités à Eclipse, vous devez :

● télécharger le plugin correspondant ;


● copier les fichiers spécifiés dans les répertoires spécifiés ;
● démarrer Eclipse, et ça y est !

❖ Netbeans

❖ Intellij IDEA

2. Votre premier programme en Java


Les programmes Java sont, avant d'être utilisés par la machine virtuelle, précompilés en byte code
(par votre IDE ou à la main). Ce byte code n'est compréhensible que par une JVM, et c'est celle-ci
qui va faire le lien entre ce code et votre machine.
Un bytecode (il existe plusieurs types de byte code, mais nous parlons ici de celui créé par Java) n'est
rien d'autre qu'un code intermédiaire entre votre code Java et le code machine. Ce code particulier
se trouve dans les fichiers précompilés de vos programmes ; en Java, un fichier source a pour
extension .java et un fichier précompilé a l'extension .class : c'est dans ce dernier que vous trouverez
du byte code. Je vous invite à examiner un fichier .class à la fin de cette partie , mais c'est illisible !
Par contre, vos fichiers .java sont de simples fichiers texte dont l'extension a été changée. Vous pouvez
donc les ouvrir, les créer ou encore les mettre à jour avec le Bloc-notes de Windows, par exemple.
Cela implique que, si vous le souhaitez, vous pouvez écrire des programmes Java avec le Bloc-notes
ou encore avec Notepad++

Tous les programmes Java sont composés d'au moins une classe. Elle doit contenir une
méthode appelée main : ce sera le point de démarrage de notre programme.
Une méthode est une suite d'instructions à exécuter. C'est un morceau logique de notre
programme. Une méthode contient :

● un en-tête : celui-ci va être en quelque sorte la carte d'identité de la méthode ;

8
● un corps : le contenu de la méthode, délimité par des accolades ;
● une valeur de retour : le résultat que la méthode va retourner.

Hello World

Maintenant, essayons de taper le code suivant :

1 public static void main(String[] args){


2 System.out.print("Hello World !");
3 }

Expliquons un peu cette ligne de code.


Littéralement, elle signifie « la méthode print() va écrire « Hello World ! » en utilisant l'objet out
de la classe System » . Avant que vous arrachez les cheveux, voici quelques précisions :

● System : ceci correspond à l'appel d'une classe qui se nomme « System » . C'est une classe
utilitaire qui permet surtout d'utiliser l'entrée et la sortie standard, c'est-à-dire la saisie clavier
et l'affichage à l'écran.
● out : objet de la classe System qui gère la sortie standard.
● print : méthode qui écrit dans la console le texte passé en paramètre (entre les parenthèses).
Prenons le code suivant :

1 System.out.print("Hello World !");


2 System.out.print("Je suis");
3 System.out.print("Titi");

Lorsque vous l'exécutez, vous devriez voir des chaînes de caractères qui se suivent sans saut de
ligne. Autrement dit, ceci s'affichera dans votre console :

1 Hello World !Je suisTiti

9
Vous souhaitez insérer un retour à la ligne pour que votre texte soit plus lisible… Pour cela, vous
avez plusieurs solutions :

● soit vous utilisez un caractère d'échappement, ici \n ;


● soit vous utilisez la méthode println() à la place de la méthode print().
Donc, si nous reprenons notre code précédent et que nous appliquons cela, voici ce que ça
donnerait :

1 System.out.print("Hello World ! \n");


2 System.out.println("Je suis");
3 System.out.println("\nTiti");

Avec pour résultat :

1 Hello World !
2 Je suis
3
4 Titi

Vous pouvez voir que :

● lorsque vous utilisez le caractère d'échappement \n, quelle que soit la méthode appelée, celle-
ci ajoute immédiatement un retour à la ligne à son emplacement ;
● lorsque vous utilisez la méthode println(), celle-ci ajoute automatiquement un retour à la
ligne à la fin de la chaîne passée en paramètre ;
● un caractère d'échappement peut être mis dans la méthode println().
Deux autres caractères d’échappement:
1. \r va insérer un retour chariot, parfois utilisé aussi pour les retours à la ligne ;
2. \t va faire une tabulation.

3. Quelques instructions de base en Java


L’exemple du paragraphe 2 a permis de présenter le canevas général à utiliser pour écrire un programme en
Java. Voici maintenant un exemple un peu plus important, accompagné de ce que son exécution afficherait
dans la fenêtre console :

10
Figure 1: Exemple de Programme en Java

Bien entendu, nous avons utilisé le même canevas que précédemment avec un autre nom de classe (ici
Exemple) :

public class Exemple


{ public static void main (String[] args)
{ .....
}
}

Les deux premières instructions de notre fonction main sont des déclarations classiques :
int n;
double x ;

La première précise que la variable n est de type int, c’est-à-dire qu’elle est destinée à contenir des
nombres entiers (relatifs). Comme la plupart des langages, Java dispose de plusieurs types entiers. De
la même manière, la seconde instruction précise que x est une variable de type double, c’est-à-dire
destinée à contenir des nombres flottants en "double précision" (approximation de nombres réels).
Nous verrons que Java dispose de deux types de flottants, le second se nommant float (nous ne
l’avons pas utilisé ici car il aurait fait intervenir des pro- blèmes de conversion des constantes
flottantes).

11
Comme dans la plupart des langages modernes, les déclarations sont obligatoires en Java. Cependant,
il n’est pas nécessaire qu’elles soient regroupées en début de programme (comme cela est le cas en C
ou en Pascal) ; il suffit simplement qu’une variable ait été déclarée avant d’être utilisée.
Les instructions suivantes sont des affectations classiques :
n=5;
x=2*n+1.5;

Les deux instructions suivantes font appel à la fonction System.out.println déjà entrevue au
paragraphe 2 :
System.out.println ("n = " + n) ;
System.out.println ("x = " + x) ;
Mais cette fois, vous constatez que son argument ne se limite plus à une simple constante chaîne. En
Java, l’expression "n = " + n est interprétée comme la concaténation de la chaîne constante "n = "
avec le résultat de la conversion en chaîne de la valeur de la variable n. Une telle conversion fournit
en fait la suite de caractères correspondant à l’écriture du nombre en décimal.
La même remarque s’applique à l’expression "x = " + x. Nous verrons que l’opérateur + pos- sède une
propriété intéressante : dès que l’un de ses deux opérandes est de type chaîne, l’autre est converti en
chaîne.
La suite du programme est classique. On y note simplement une déclaration (tardive) de la variable
y. Elle est autorisée à ce niveau car y n’a pas été utilisée dans les instructions précédentes.
Remarques :
Avec une instruction telle que :
System.out.println ("resultats = ", a + b*x) ;
on affichera à la suite du texte "resultats = ", la valeur de a suivie de celle de b*x. Pour obtenir celle
de l’expression a + b*x, il faudra procéder ainsi :
System.out.println ("resultats = ", (a + b*x) ) ;

4. Règles générales d’écriture

Ce paragraphe expose un certain nombre de règles générales intervenant dans l’écriture d’un
programme Java. Nous aborderons en particulier ce qu’on nomme les identificateurs et les mots-clés,
le format libre dans lequel sont écrites les instructions, l’usage des séparateurs et des commentaires.
4.1. Les identificateurs
En Java comme dans la plupart des autres langages, un identificateur est formé de lettres ou de chiffres, le
premier caractère étant obligatoirement une lettre. Les lettres comprennent les majuscules A-Z et les
minuscules a-z, ainsi que le caractère "souligné" (_) et le caractère $. Voici quelques identificateurs corrects :
ligne clavier valeur_5 _total_56
Aucune limitation ne pèse sur le nombre de caractères, qui sont tous significatifs (en C, seuls les 32 premiers
l’étaient).

12
Compléments

Notez bien que, comme en C (et contrairement à Pascal), on distingue les majuscules des minuscules.
Ainsi, Ligne et ligne désignent deux identificateurs différents ; il en va de même pour PremProg et
Premprog.
Bien qu’elles ne soient nullement imposées par le langage, certaines règles sont traditionnellement
utilisées dans le choix des identificateurs d’un programme Java. Ainsi, les noms de variables et les
noms de fonctions sont écrits en minuscules, sauf s’ils sont formés de la juxtaposition de plusieurs
mots, auquel cas chaque mot sauf le premier comporte une majuscule, par exemple: valeur,
nombreValeurs, tauxEmprunt, nombreReponsesExactes. Les noms de classes suivent la même règle,
mais leur première lettre est écrite en majuscules : Clavier, PremProg. Les noms de constantes sont
écrits entièrement en majuscules. Notez que ces règles permettent de savoir que System est une classe
et que out n’en est pas une.
4.2. Les mots-clés
Certains mots-clés sont réservés par le langage à un usage bien défini et ne peuvent pas être utilisés
comme identificateurs. En voici la liste, par ordre alphabétique :

abstract short import


case this native
continue void protected
extends boolean super
goto char throws
int do while
null finally byte
return implements const
synchronized long else
try private for
assert static instanceof
catch throw new
default volatile public
final break switch
if class transient
interface double
package float

4.3. Les séparateurs

Dans notre langue écrite, les mots sont séparés par un espace, un signe de ponctuation ou une fin de
ligne.
Il en va quasiment de même en Java. Ainsi, dans un programme, deux identificateurs successifs entre
lesquels la syntaxe n’impose aucun signe particulier doivent impérativement être séparés soit par un
espace, soit par une fin de ligne. En revanche, dès que la syntaxe impose un séparateur quelconque,

13
il n’est pas nécessaire de prévoir d’espaces supplémentaires, bien qu’en pratique cela améliore la
lisibilité du programme.
Ainsi, vous ne pouvez pas remplacer :

int x,y
par
intx,y
En revanche, vous pourrez écrire indifféremment :
int n,compte,p,total,valeur ;
ou, plus lisiblement :
int n, compte, p, total, valeur ;
voire :
int n,
compte,
p,
total,
valeur ;
4.4. Les commentaires
Comme tout langage évolué, Java autorise la présence de commentaires dans les programmes source.
Ces textes explicatifs destinés aux lecteurs du programme n’ont aucune incidence sur sa compilation.
Java dispose de deux formes de commentaires :
• les commentaires usuels,
• les commentaires de fin de ligne,

4.4.1. Les commentaires usuels


Ce sont ceux utilisés en langage C. Ils sont formés de caractères quelconques placés entre les
caractères /* et */. Ils peuvent apparaître à tout endroit du programme où un espace est autorisé. En
général, cependant, on se limitera à des emplacements propices à une bonne lisibilité du programme.
En voici quelques exemples :

4.4.2. Les commentaires de fin de ligne

Ce sont ceux de C++. Ils sont introduits par le double caractère //. Tout le texte suivant jusqu’à la fin de la
ligne est considéré comme un commentaire. Cette nouvelle possibilité n’apporte qu’un surcroît de confort
et de sécurité. En effet, une ligne telle que :

System.out.println ("bonjour) ; // formule de politesse

peut toujours être écrite ainsi :

System.out.println ("bonjour) ; /* formule de politesse */

14
Vous pouvez mêler les deux formules. Notez que dans :

/* partie1 // partie2 */ partie3

le commentaire ouvert par /* ne se termine qu’au prochain */ ; donc partie1 et partie2 sont des
commentaires, tandis que partie3 est considéré comme appartenant aux instructions. De même, dans :
partie1 // partie2 /* partie3 */ partie4

Le commentaire introduit par // s’étend jusqu’à la fin de la ligne. Il couvre donc partie2, partie3 et partie4.

Compléments
On dit souvent que Java possède une troisième forme de commentaires dits de documentation. Il s’agit en fait
d’un cas particulier de commentaires usuels, puisqu’ils commencent par /** et qu’ils se terminent par */. Leur
seul intérêt est de pouvoir être extraits automatiquement par des programmes utilitaires de création de
documentation tels que Javadoc.

En résumé

● La JVM est le cœur de Java.


● Elle fait fonctionner vos programmes Java, précompilés en byte code.
● Les fichiers contenant le code source de vos programmes Java ont l'extension .java.
● Les fichiers précompilés correspondant à vos codes source Java ont l'extension .class.
● Le byte code est un code intermédiaire entre celui de votre programme et celui que votre machine
peut comprendre.
● Un programme Java, codé sous Windows, peut être précompilé sous Mac et enfin exécuté sous
Linux.
● Votre machine NE PEUT PAS comprendre le byte code, elle a besoin de la JVM.
● Tous les programmes Java sont composés d'au moins une classe.
● Le point de départ de tout programme Java est la méthode public static void main(String[] args).
● On peut afficher des messages dans la console grâce à ces instructions :
○ System.out.println, qui affiche un message avec un saut de ligne à la fin ;
○ System.out.print, qui affiche un message sans saut de ligne.

15
Chapitre 2
Les types des variables et les
opérateurs en Java
Dans les chapitres précédents, nous avons rencontré les types int et double. Java dispose d’un certain
nombre de types de base dits primitifs, permettant de manipuler des entiers, des flottants, des
caractères et des booléens. Ce sont les seuls types du langage qui ne sont pas des classes. Mais ils seront
utilisés pour définir les champs de données de toutes les classes que vous serez amenés à créer.
Avant de les étudier en détail, nous effectuerons un bref rappel concernant la manière dont
l’information est représentée dans un ordinateur et la notion de type qui en découle.

1. Les types primitifs


1.1. La notion de type
La mémoire centrale est un ensemble de "positions binaires" nommées bits. Les bits sont regroupés
en octets (8 bits), et chaque octet est repéré par ce qu’on nomme son adresse.
Compte tenu de sa technologie (actuelle !), l’ordinateur ne sait représenter et traiter que des
informations exprimées sous forme binaire. Toute information, quelle que soit sa nature, devra être
codée sous cette forme. Dans ces conditions, on voit qu’il ne suffit pas de connaître le contenu d’un
emplacement de la mémoire (d’un ou de plusieurs octets) pour pouvoir lui attribuer une
signification. Il faut également connaître la manière dont l’information qu’il contient a été codée. Il
en va de même en général pour traiter cette information. Par exemple, pour additionner deux valeurs,
il faudra savoir quel codage a été employé afin de pouvoir mettre en œuvre les bonnes instructions
en langage machine.
D’une manière générale, la notion de type, telle qu’elle existe dans les langages évolués, sert (entre
autres choses) à régler les problèmes que nous venons d’évoquer.
Les types primitifs de Java se répartissent en quatre grandes catégories selon la nature des
informations qu’ils permettent de représenter :
● nombres entiers,
● nombres flottants,
● caractères,
● booléens.
1.2. Les types entiers
Ils servent à représenter des nombres entiers relatifs.

16
1.2.1. Représentation mémoire
Un bit est réservé au signe (0 pour positif et 1 pour négatif). Les autres servent à représenter :
● la valeur absolue du nombre pour les positifs,
● ce que l’on nomme le complément à deux du nombre, pour les négatifs.
Examinons cela plus en détail, dans le cas de nombres représentés sur 16 bits (ce qui correspondra
finalement au type short de Java).

1.2.1.1. Cas d’un nombre positif


Sa valeur absolue est donc écrite en base 2, à la suite du bit de signe. Voici quelques exemples de
codages de nombres. À gauche, le nombre en décimal ; au centre, le codage binaire correspondant ;
à droite, le même codage exprimé en hexadécimal :

1 0000000000000001 0001
2 0000000000000010 0002
3 0000000000000011 0003
16 0000000000010000 00F0
127 0000000001111111 007F
255 0000000011111111 00FF

1.2.1.2. Cas d’un nombre négatif


Sa valeur absolue est codée suivant ce que l’on nomme la technique du complément à deux. Pour ce
faire, cette valeur est d’abord exprimée en base 2, puis tous les bits sont inversés (1 devient 0 et 0
devient 1) ; enfin, on ajoute une unité au résultat. Voici quelques exemples (avec la même
présentation que précédemment) :

-1 1111111111111111 FFFF
-2 1111111111111110 FFFE
-3 1111111111111101 FFFD
-4 1111111111111100 FFFC
-16 1111111111110000 FFF0
-256 1111111100000000 FF00

1.2.2. Les différents types d’entiers

Java dispose de quatre types entiers, correspondant chacun à des emplacements mémoire de taille
différente, donc à des limitations différentes. Le tableau suivant en récapitule leurs caractéristiques.
Notez l’existence de constantes prédéfinies de la forme Integer.MAX_VALUE qui fournissent les
différentes limites.

17
Type Taille Taille Valeur minimale Valeur maximale
(octets) (bit)

byte 1 8 -128 127


(Byte.MIN_VALUE) (Byte.MAX_VALUE)

short 2 16 -32 768 32 767


(Short.MIN_VALUE) (Short.MAX_VALUE)

int 4 32 -2 147 483 648 2 147 483 647


(Integer.MIN_VALUE) (Integer.MAX_VALUE)

long 8 64 -9 223 372 036 854 775 808 9 223 372 036 854 775 807
(Long.MIN_VALUE) (Integer.MAX_VALUE)

Table 1: Les caractéristiques des quatre types entiers de Java

1.3. Les types flottants

1.3.1. Les différents types et leur représentation en


mémoire
Les types flottants permettent de représenter, de manière approchée, une partie des nombres réels.
Pour ce faire, ils s’inspirent de la notation dite scientifique (ou exponentielle) bien connue qu’on
trouve dans 1.5 1022 ou 0.472 10-8 ; dans une telle notation, on nomme mantisses les quantités telles
que 1.5 ou 0.472 et exposants les quantités telles que 22 ou -8.
Java prévoit deux types de flottants correspondant chacun à des emplacements mémoire de tailles
différentes : float et double. La connaissance des caractéristiques exactes du système de codage n’est
généralement pas indispensable. En revanche, il est important de noter que de telles représentations
sont caractérisées par deux éléments :
● la précision : lors du codage d’un nombre décimal quelconque dans un type flottant, il est
nécessaire de ne conserver qu’un nombre fini de bits. Or la plupart des nombres s’exprimant
avec un nombre limité de décimales ne peuvent pas s’exprimer de façon exacte dans un tel
codage. On est donc obligé de se limiter à une représentation approchée en faisant ce qu’on
nomme une erreur de troncature.
● le domaine couvert, c’est-à-dire l’ensemble des nombres représentables à l’erreur de
troncature près.

18
Le tableau suivant récapitule les caractéristiques des types float et double. Notez ici encore l’existence
de constantes prédéfinies de la forme Float.MAX_VALUE qui fournissent les différentes limites.

Type Taille Taille Précision Valeur absolue minimale Valeur absolue maximale
(octets) (bit) (chiffres
significatifs)

float 4 32 7 1.40239846E-45 3.40282347E38


(Float.MIN_VALUE) (Float.MAX_VALUE)

double 8 64 15 4.9406564584124654E- 1.797693134862316E30


324 8
(Double.MIN_VALUE (Double.MAX_VALUE
) )
Table 2: Les caractéristiques des types flottants en Java

Une estimation de l’erreur relative de troncature est fournie dans la colonne Précision sous la forme
d’un nombre de chiffres significatifs. Il s’agit d’une approximation décimale plus parlante que son
équivalent (exact) en nombre de bits significatifs.
1.4. Le type caractère

1.4.1. Généralités

Comme la plupart des langages, Java permet de manipuler des caractères. Mais il offre l’originalité
de les représenter en mémoire sur deux octets en utilisant le code universel Unicode.
Parmi les 65536 combinaisons qu’offre Unicode, on retrouve les 128 possibilités du code ASCII
restreint (7 bits) et même les 256 possibilités du code ASCII/ANSI (Latin 1) utilisé par Windows.
Celles-ci s’obtiennent simplement en complétant le code ASCII par un un premier octet nul. Cela
signifie donc qu’en Java comme dans les autres langages, la notion de caractère dépasse celle de
caractère imprimable, c’est-à-dire auquel on peut associer un graphisme.
Une variable de type caractère se déclare en utilisant le mot-clé char comme dans :
char c1, c2 ; // c1 et c2 sont deux variables de type caractère

1.1.2. Écriture des constantes de type caractère


On peut noter une constante caractère de façon classique entre apostrophes, par exemple :
’a’ ’E’ ’é’ ’+’

19
Bien entendu, cette notation n’est utilisable que si le caractère est disponible dans l’implémentation
considérée, qu’il dispose d’un graphisme et d’une combinaison de touche permettant de le saisir avec
un éditeur.
Certains caractères ne disposant pas de graphisme possèdent une notation conventionnelle utilisant
le caractère \ ; dans cette catégorie, on trouve également quelques caractères qui, bien que disposant
d’un graphisme, jouent un rôle particulier de délimiteur qui leur interdit la notation classique. En
voici la liste :

Notation Code Unicode Abréviation usuelle Signification


(hexadecimal)

\b 0008 BS (Backspace) Retour arrière

\t 0009 HT (Horizontal tabulation) Tabulation horizontale

\n 000a LF (Line feed) Saut de ligne

\f 000c FF (Form feed) Saut de page

\r 000d CR (Cariage return) Retour de chariot

\’’ 0022

\’ 0027

\\

Table 3: Les caractères disposant d'une notation spéciale

1.2. Le type booléen

Ce type sert à représenter une valeur logique du type vrai/faux. Il n’existe pas dans tous les langages
car il n’est pas aussi indispensable que les autres. En effet, on peut souvent se contenter d’expressions
booléennes du genre de celles qu’on utilise dans une instruction if :

if (n<p) ..... // n<p est une expression booléenne valant vrai ou faux

20
En Java, on peut disposer de variables de ce type, ce qui permettra des affectations telles que :

boolean ordonne; //déclaration d’une variable de type booléen .....


ordonne = n<p ; // ordonne reçoit la valeur de l’expression booléenne n<p

Les deux constantes du type booléen se notent true et false.

1.3. Initialisation et constantes

1.3.1. Initialisation d’une variable

Une variable peut recevoir une valeur initiale au moment de sa déclaration, comme dans :
int n=15;
Cette instruction joue le même rôle que :
int n; n=15;
Rien n’empêche que la valeur de n n’évolue par la suite.

Comme en Java les déclarations peuvent apparaître à n’importe quel emplacement du programme,
on ne peut plus les distinguer complètement des instructions exécutables. En particulier, on peut
initialiser une variable avec une expression autre qu’une constante. Voici un exemple :

int n=10; .....


int p=2*n //OK:p reçoit la valeur 20(si la valeur de n n’a pas
// changé depuis son initialisation)

Un autre exemple :
int n; .....
n = Clavier.lireInt() ;
int p=2*n; //OK-la valeur initiale de p ne sera toute fois
// connue qu’au moment de l’exécution

1.3.2. Cas des variables non initialisées

En Java, une variable n’ayant pas encore reçu de valeur ne peut pas être utilisée, sous peine d’aboutir
à une erreur de compilation. En voici deux exemples :

21
int n;
System.out.println("n="+n); //erreur de compilation: la valeur de n n’est pas définie ici

int n;
int p = n+3 ; // erreur de compilation : la valeur de n n’est pas encore défine
n = 12 ; // elle l’est ici (trop tard)

Contrairement à la plupart des autres langages, Java est capable de détecter toutes les situations de
variables non initialisées, comme le montre cet exemple :

int n;
if(...)n=30;
p=2*n; //erreur de compilation:n n’est pas initialisée dans tous les cas
Ici, le compilateur s’est aperçu de ce que la variable n pouvait ne pas recevoir de valeur dans certains
cas. En revanche, les instructions suivantes seront acceptées :

int n;
if(...)n=30;
else n=10;
p=2*n; //OK: n a obligatoirement reçu l’une des valeurs 30 ou 10
Compléments
Nous verrons que ce que nous nommons pour l’instant variable est en fait une variable locale à la
méthode main. Nous rencontrerons d’autres sortes de variables, en particulier les champs des objets.
Contrairement aux variables locales évoquées ici, ces champs seront soumis à une initialisation
implicite par défaut ; le risque de champ non défini n’existera donc pas. D’autre part, nous verrons
qu’il existe des variables ou des champs d’un type autre que primitif, à savoir objet ou tableau.

1.1.1. Constantes : le mot-clé final


Java permet de déclarer que la valeur d’une variable ne doit pas être modifiée pendant l’exécution du
programme. Par exemple, avec :
final int n=20;
On déclare la variable n de type int, de valeur initiale 20. De plus, toute tentative ultérieure de
modification de la valeur de n sera rejetée par le compilateur :
n=n+5; //erreur:n a été déclarée final
n=Clavier.lireInt(); //idem

22
2. Les types objets
2.1. Le type String
Le type String permet de gérer les chaînes de caractères, c'est-à-dire le stockage de texte.
Il s'agit d'une variable d'un type plus complexe que l'on appelle objet. Vous verrez que celle-ci s'utilise
un peu différemment des variables précédentes :

1 //Première méthode de déclaration


2 String phrase;
phrase = "Titi et Grosminet";
3
4
//Deuxième méthode de déclaration
5 String str = new String();
6 str = "Une autre chaîne de caractères";
7
8 //Troisième méthode de déclaration
9 String string = "Une autre chaîne";

10
//Quatrième méthode de déclaration
11
String chaine = new String("Et une de plus !");
12
13

Attention
String commence par une majuscule ! Et lors de l'initialisation, on utilise des doubles cotes (« " " »).
String n'est pas un type de variable, mais un objet. Notre variable est un objet, on parle aussi d'une
instance : ici, une instance de la classe String.

Pourquoi String commence par une majuscule et pas les autres ?


Il s'agit d'une convention de nommage. En fait, c'est une façon d'appeler nos classes, nos variables,
etc. Il faut que vous essayiez de la respecter au maximum. Cette convention, la voici :

● tous vos noms de classes doivent commencer par une majuscule ;


● tous vos noms de variables doivent commencer par une minuscule ;
● si le nom d'une variable est composé de plusieurs mots, le premier commence par une
minuscule, le ou les autres par une majuscule, et ce, sans séparation ;
● tout ceci sans accentuation !

23
Voici quelques exemples de noms de classes et de variables :

1 public class Toto{}


2 public class Nombre{}
public class TotoEtTiti{}
3
String chaine;
4
String chaineDeCaracteres;
5 int nombre;
6 int nombrePlusGrand;
7

Les variables de type String sont des objets. Les objets sont définis par une ossature (un squelette)
qui est en fait une classe. Ici, nous utilisons un objet String défini par une classe qui s'appelle « String
» ; c'est pourquoi String a une majuscule et pas int, float, etc., qui eux ne sont pas définis par une
classe.

Remarque :
Veillez à bien respecter la casse (majuscules et minuscules), car une déclaration de CHAR à la place
de char ou autre chose provoquera une erreur, tout comme une variable de type string à la place de
String !
Faites donc bien attention lors de vos déclarations de variables… Une petite astuce quand même
(enfin deux, plutôt) : on peut très bien compacter les phases de déclaration et d'initialisation en
une seule phase ! Comme ceci :

1 int entier = 32;


2 float pi = 3.1416f;
char carac = 'z';
3
String mot = new String("Coucou");
4

3. Les opérateurs
Java est l’un des langages les plus fournis en opérateurs. Il dispose en effet des opérateurs classiques
(arithmétiques, logiques) mais aussi d’un important éventail d’opérateurs originaux d’affectation et
d’incrémentation. Nous verrons en effet que ces actions sont réalisées par des opérateurs.
Ce paragraphe étudie tous les opérateurs de Java, ainsi que les règles de priorité et de conversion de
type qui interviennent dans les évaluations des expressions.

24
3.1. Les opérateurs arithmétiques
Les opérateurs arithmétiques sont ceux que l'on apprend à l'école primaire… ou presque :

● « + » : permet d'additionner deux variables numériques (mais aussi de concaténer des


chaînes de caractères ; ne vous inquiétez pas, on aura l'occasion d'y revenir).
● « - » : permet de soustraire deux variables numériques.
● « * » : permet de multiplier deux variables numériques.
● « / » : permet de diviser deux variables numériques (mais je crois que vous aviez deviné).
● « % » : permet de renvoyer le reste de la division entière de deux variables de type numérique ;
cet opérateur s'appelle le modulo.

Opérateur priorité Action Exemples

+ 1 Signe positif +a; +(a-b); +7 (unaire)

- 1 Sign négatif -a; -(a-b); -7 (unaire)

* 2 Multiplication 5*4; 12.7*(-8.31); 5*2.6

/ 2 Division 5/2; 5.0/2; 5.0/2.0

% 2 Reste ou 5%2; 5.0%2; 5.0%2.0


modulo

+ 3 Addition a+b; -8.53 + 10; 2+3

- 3 Soustraction a-b; -8.53 - 10; 2-3

Table 4: Tableau Récapitulatif des opérations arithmétiques


Ces opérateurs sont binaires (à deux opérandes) exceptés les opérateurs de signe positif ou négatif.
Ils travaillent tous avec des opérandes de types entiers ou réels. Le résultat de l'opération est converti
automatiquement en valeur du type des opérandes.
L'opérateur " % " de reste n'est intéressant que pour des calculs sur les entiers longs, courts, signés ou
non signés : il renvoie le reste de la division euclidienne de 2 entiers.
Exemples d’utilisation de l’opérateur de division selon les types des opérandes et du résultat :

Programme Java Résultat obtenu Commentaire

25
int x=5, y ; x = 5, y = ??? Déclaration

float a , b = 5 ; b = 5 , a =??? declaration

y=x/2; y=2 //type int int x et int 2


résultat : int

y=b/2; erreur de conversion conversion automatique impossible


(float b --> int y)

y = b / 2.0 ; erreur de conversion conversion automatique impossible


(float b --> int y)

a=b/2; a = 2.5 // type float float b et int 2


résultat : float

a=x/2; a = 2.0 // type float int x et int 2


résultat : int
conversion automatique int 2 --> float
2.0

a = x / 2f ; a = 2.5 // type float int x et float 2f


résultat : float

Table 5: Exemple d'utilisation de l'opérateur de division

Pour l'instruction précédente " y = b / 2 " engendrant une erreur de conversion voici deux corrections
possibles utilisant le transtypage :
y = (int)b / 2 ; // b est converti en int avant la division qui s'effectue sur deux int.
y = (int)(b / 2) ; // c'est le résultat de la division qui est converti en int.
3.2. Les opérateurs relationnels

Comme tout langage, Java permet de comparer des expressions à l’aide d’opérateurs classiques de
comparaison. En voici un exemple :
2 * a >b +5
Le résultat est une valeur booléenne ayant l’une des deux valeurs true ou false. On pourra :
● l’utiliser dans une instruction if, comme dans :
if(2*a>b+5)...
● l’affecter à une variable booléenne :

26
boolean ok ; .....
ok=2*a>b+5

● le faire intervenir dans une expression booléenne plus complexe.


Comme les opérateurs arithmétiques, les opérateurs relationnels ne sont théoriquement définis que
pour des opérandes de même type, parmi int, long, float ou double. Mais ils soumettent eux aussi
leurs opérandes aux conversions implicites (promotions numériques et ajustement de type), de sorte
qu’au bout du compte ils pourront porter sur des opérandes de types quelconques, y compris byte,
short ou char.
Voici la liste des opérateurs relationnels existant en Java. Remarquez bien la notation (==) de
l’opérateur d’égalité, le signe = étant réservé aux affectations :

Opérateur Signification

< Inférieur à

<= Inférieur ou égal à

> Supérieur à

>= Supérieur ou égal à

== Égal à

!= Different de

Table 6: les opérateurs relationnels


Il faut savoir que les quatre premiers opérateurs (<, <=, >, >=) sont de même priorité. Les deux
derniers (== et !=) possèdent également la même priorité, mais celle-ci est inférieure à celle des
précédents. D’autre part, ces opérateurs relationnels sont moins prioritaires que les opérateurs
arithmétiques. Cela permet souvent d’éviter certaines parenthèses dans des expressions.
Ainsi :
x +y <a +2
est équivalent à :
( x + y ) < ( a+ 2 )

27
3.3. Les opérateurs logiques
Java dispose d’opérateurs logiques dont voici la liste, classée par priorités décroissantes (il n’existe pas
deux opérateurs ayant la même priorité). Nous reviendrons un peu plus loin sur l’existence
d’opérateurs voisins (& et &&, | et ||).

Opérateur Signification

! Négation

&& Et

|| ou

Table 7: les opérateurs logiques

Par exemple :
(a<b) && (c<d)
prend la valeur true (vrai) si les deux expressions a<b et c<d sont toutes les deux vraies, la valeur false
(faux) dans le cas contraire.
(a<b) || (c<d)
prend la valeur true si l’une au moins des deux conditions a<b et c<d est vraie, la valeur
false dans le cas contraire.
! (a<b)
prend la valeur true si la condition a<b est fausse, la valeur false dans le cas contraire. Cette expression
possède en fait la même valeur que a>=b.
3.4. Les opérateurs d’incrémentation et de décrémentation
Dans des programmes écrits dans un langage autre que Java (ou C), on rencontre souvent des
expressions (ou des instructions) telles que :

i= i+ 1
n =n - 1
qui incrémentent ou qui décrémentent de 1 la valeur d’une variable. En Java, ces actions peuvent
être réalisées par des opérateurs unaires portant sur cette variable. Ainsi, l’expression : ++i
a pour effet d’incrémenter de 1 la valeur de i, et sa valeur est celle de i après incrémentation.
Là encore, comme pour l’affectation, nous avons affaire à une expression qui non seulement
possède une valeur, mais qui, de surcroît, réalise une action (incrémentation de i).
Il est important de voir que la valeur de cette expression est celle de i après incrémentation.

28
Ainsi, si la valeur de i est 5, l’expression :
n = ++i - 5
affectera à i la valeur 6 et à n la valeur 1.
En revanche, lorsque cet opérateur est placé après son unique opérande, la valeur de l’expression
correspondante est celle de la variable avant incrémentation. Ainsi, si i vaut 5, l’expression :
n = i++ - 5
affectera à i la valeur 6 et à n la valeur 0 (car ici la valeur de l’expression i++ est 5). On dit que ++ est:
● un opérateur de préincrémentation lorsqu’il est placé à gauche de son opérande,
● un opérateur de postincrémentation lorsqu’il est placé à droite de son opérande.
Bien entendu, lorsque seul importe l’effet d’incrémentation de l’opérande, cet opérateur peut être
indifféremment placé avant ou après. Ainsi, ces deux instructions sont équivalentes (ici, il s’agit bien
d’instructions car les expressions sont terminées par un point-virgule – leur valeur se trouve donc
inutilisée) :
i++ ;
++i ;
De la même manière, il existe un opérateur de décrémentation noté -- qui est :
● un opérateur de prédécrémentation lorsqu’il est placé à gauche de son opérande,
● un opérateur de postdécrémentation lorsqu’il est placé à droite de son opérande.
Tous ces opérateurs peuvent s’appliquer à tous les types numériques (pas nécessairement entiers)
ainsi qu’au type char.

29
Chapitre 3
Les entrées clavier
Après ce chapitre, vous pourrez saisir des informations et les stocker dans des variables afin de
pouvoir les utiliser a posteriori.
En fait, jusqu'à ce que nous voyions les interfaces graphiques, nous travaillerons en mode console.
Donc, afin de rendre nos programmes plus ludiques, il est de bon ton de pouvoir interagir avec ceux-
ci. Par contre, ceci peut engendrer des erreurs (on parlera d'exceptions, mais ce sera traité plus loin).
Afin de ne pas surcharger le chapitre, nous survolerons ce point sans voir les différents cas d'erreurs
que cela peut engendrer.

1. La classe Scanner
Les variables de type String sont en réalité des objets de type String. Pour que Java puisse lire ce que
vous tapez au clavier, vous allez devoir utiliser un objet de type Scanner. Cet objet peut prendre
différents paramètres, mais ici nous n'en utiliserons qu'un : celui qui correspond à l'entrée standard
en Java. Lorsque vous faites System.out.println();, je vous rappelle que vous appliquez la méthode
println() sur la sortie standard ; ici, nous allons utiliser l'entrée standard System.in. Donc, avant
d'indiquer à Java qu'il faut lire ce que nous allons taper au clavier, nous devrons instancier un objet
Scanner. Avant de vous expliquer ceci, créez une nouvelle classe et tapez cette ligne de code dans
votre méthode main :

1 Scanner sc = new Scanner(System.in);

30
1 import java.util.Scanner;

Vous devez avoir une jolie vague rouge sous le mot Scanner. Ajoutez au-dessus de la
déclaration de votre classe, cette ligne :
Il fallait indiquer à Java où se trouve la classe Scanner. Pour faire ceci, nous devons importer la classe
Scanner grâce à l'instruction import. La classe que nous voulons se trouve dans le package java.util.
Un package est un ensemble de classes. En fait, c'est un ensemble de dossiers et de sous-dossiers
contenant une ou plusieurs classes, mais nous verrons ceci plus en détail lorsque nous ferons nos
propres packages.
Les classes qui se trouvent dans les packages autres que java.lang (package automatiquement importé
par Java, on y trouve entre autres la classe System) sont à importer à la main dans vos classes Java pour
pouvoir vous en servir.

1 //Ceci importe la classe Scanner du package


2
3
java.util
4 import java.util.Scanner;
//Ceci importe toutes les classes du
package java.util
import java.util.*;

2. Récupérer la valeur saisie


Voici l'instruction pour permettre à Java de récupérer ce que vous avez saisi pour ensuite
l'afficher :

1 Scanner sc = new Scanner(System.in);


2
3
System.out.println("Veuillez saisir un mot :");
4 String str = sc.nextLine();
System.out.println("Vous avez saisi : " + str);

31
Une fois l'application lancée, le message que vous avez écrit auparavant s'affiche dans la console, en
bas. Pensez à cliquer dans la console afin que ce que vous saisissez y soit écrit et que Java puisse
récupérer ce que vous avez inscrit.
Si vous remplacez la ligne de code qui récupère une chaîne de caractères comme suit :

1 Scanner sc = new Scanner(System.in);


2
System.out.println("Veuillez saisir un nombre :");
3
4 int str = sc.nextInt();
System.out.println("Vous avez saisi le nombre : " + str);

Vous devriez constater que lorsque vous introduisez votre variable de type Scanner et que vous
introduisez le point permettant d'appeler des méthodes de l'objet, l’IDE vous propose une liste de
méthodes associées à cet objet (ceci s'appelle l'autocomplétion) ; de plus, lorsque vous commencez à
taper le début de la méthode nextInt(), le choix se restreint jusqu'à ne laisser que cette seule méthode.
Exécutez et testez ce programme : vous verrez qu'il fonctionne à la perfection. Sauf… si vous saisissez
autre chose qu'un nombre entier !
Vous savez maintenant que pour lire un int, vous devez utiliser nextInt(). De façon générale, dites-
vous que pour récupérer un type de variable, il vous suffit d'appeler next<Type de variable
commençant par une majuscule> (rappelez-vous de la convention de nommage Java).

1 Scanner sc = new Scanner(System.in);


2 int i = sc.nextInt();
3 double d = sc.nextDouble();
4 long l = sc.nextLong();
5 byte b = sc.nextByte();
6 //Etc.

Il y’a un type de variables primitives qui n’est pas pris en compte par la classe Scanner : il s’agit du
type char.
Voici comment on pourrait récupérer un caractère :

32
1 System.out.println("Saisissez une lettre :");
2 Scanner sc = new Scanner(System.in);
3 String str = sc.nextLine();
4 char carac = str.charAt(0);
5 System.out.println("Vous avez saisi le caractère : " + carac);

Nous avons récupéré une chaîne de caractères, puis utilisé une méthode de l'objet String (ici,
charAt(0) ) afin de récupérer le premier caractère saisi. Même si vous tapez une longue chaîne de
caractères, l'instruction charAt(0) ne renverra que le premier caractère.
Une précision s'impose, toutefois : la méthode nextLine() récupère le contenu de toute la ligne saisie
et replace la « tête de lecture » au début d'une autre ligne. Par contre, si vous avez invoqué une
méthode comme nextInt(), nextDouble() et que vous invoquez directement après la méthode
nextLine(), celle-ci ne vous invitera pas à saisir une chaîne de caractères : elle videra la ligne
commencée par les autres instructions. En effet, celles-ci ne repositionnent pas la tête de lecture,
l'instruction nextLine() le fait à leur place. Pour faire simple, ceci :

33
1 import java.util.Scanner;
2
3 public class Main {
4 public static void main(String[] args){
5 Scanner sc = new Scanner(System.in);
6 System.out.println("Saisissez un entier : ");
7 int i = sc.nextInt();
8 System.out.println("Saisissez une chaîne : ");
9 String str = sc.nextLine();
10 System.out.println("FIN ! ");
11 }
12 }

… ne vous demandera pas de saisir une chaîne et affichera directement « Fin ». Pour pallier ce
problème, il suffit de vider la ligne après les instructions ne le faisant pas automatiquement :

1 import java.util.Scanner;
2
3 public class Main {
4 public static void main(String[] args){
5 Scanner sc = new Scanner(System.in);
6 System.out.println("Saisissez un entier : ");
7 int i = sc.nextInt();
8 System.out.println("Saisissez une chaîne : ");
9 //On vide la ligne avant d'en lire une autre

10 sc.nextLine();
11 String str = sc.nextLine();
12 System.out.println("FIN ! ");
}

34
13 }
14

En résumé

● La lecture des entrées clavier se fait via l'objet Scanner.

● Ce dernier se trouve dans le package java.util que vous devrez importer.

● Pour pouvoir récupérer ce vous allez taper dans la console, vous devrez initialiser l'objet

Scanner avec l'entrée standard, System.in.

Il y a une méthode de récupération de données pour chaque type (sauf les char) : nextLine() pour les
String, nextInt()pour les int …

35
Chapitre 4 :
Les structures
conditionnelles et les boucles
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.

1. La structure « if…else »
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.

36
● « ? : » : l'opérateur ternaire. Pour celui-ci, vous comprendrez mieux avec un exemple qui

sera donné vers la fin de ce chapitre.

Comme 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 if(//condition)
{
2
//Exécution des instructions si la condition est remplie
3 }
4 else
5 {
//Exécution des instructions si la condition n'est pas
6
remplie
7 }
8

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 int i = 10;

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

Dans ce cas, notre classe affiche « le nombre est positif ». Expliquons un peu ce qui se passe.

37
● 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.

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

Une autre façon d'écrire ce code, avec le même résultat : on ajoute juste un petit « sinon si… ».

38
1 int i = 0;
2 if (i < 0)
System.out.println("Ce nombre est négatif !");
3
4 else if(i > 0)
5 System.out.println("Ce nombre est positif !");
6
7 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.
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.

Les conditions multiples


Derrière ce nom 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.

39
1 int i = 58;
2 if(i < 100 && i > 50)
3 System.out.println("Le nombre est bien dans l'intervalle.");
4 else
5 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 int i = 58;
2 if(i < 100 && i > 100)
3 System.out.println("Le nombre est bien dans l'intervalle.");
4 else
5 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.

2. La structure switch

40
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 :Doit recomposer la matière!


● 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 switch (/*Variable*/)
2 {
3 case /*Argument*/:
4 /*Action*/;
5 break;
6 default:
7 /*Action*/;
8 }

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 :

41
1 int note = 10; //On imagine que la note maximale est 20
2
3 switch (note)
4 {
5 case 0:
6 System.out.println("Ouch !");
7 break;
8 case 10:
9 System.out.println("Vous avez juste la moyenne.");
10 break;
11 case 20:
12 System.out.println("Parfait !");
13 break;
14 default:
15 System.out.println("Il faut davantage travailler.");
16 }

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 :

42
1 String chaine = "Bonjour";
2
switch(chaine) {
3
case "Bonjour":
4
System.out.println("Bonjour monsieur !");
5 break;
6 case "Bonsoir":
7 System.out.println("Bonsoir monsieur !");
8 break;
9 default:
System.out.println("Bonjoir ! :p");
10
}

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 int x = 10, y = 20;


2 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 :

43
1 int x = 10, y = 20;
2 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 int x = 10, y = 20;


2
int max = (x < y) ? (y < 10) ? y % 10 : y * 2 : x ; //Max
3
vaut 40
4
5 //Pas très facile à lire…
6 //Vous pouvez entourer votre deuxième instruction ternaire
7 par des parenthèses pour mieux voir :
8
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.

44
3. Les boucles
Le rôle des boucles est de répéter un certain nombre de fois les mêmes opérations. Tous les
programmes, ou presque, ont besoin de ce type de fonctionnalité. Nous utiliserons les boucles pour
permettre à un programme de recommencer depuis le début, pour attendre une action précise de
l'utilisateur, parcourir une série de données, etc.
Une boucle s'exécute tant qu'une condition est remplie. Nous réutiliserons donc des notions du
chapitre précédent !
3.1 La boucle “while”

Pour décortiquer précisément ce qui se passe dans une boucle, nous allons voir comment elle se
construit ! Une boucle commence par une déclaration : ici while. Cela veut dire, à peu de chose près,
« tant que ». Puis nous avons une condition : c'est elle qui permet à la boucle de s'arrêter. Une boucle
n'est utile que lorsque nous pouvons la contrôler, et donc lui faire répéter une instruction un certain
nombre de fois. C'est à ça que servent les conditions. Ensuite nous avons une ou plusieurs
instructions : c'est ce que va répéter notre boucle (il peut même y avoir des boucles dans une boucle !

1 while (/* Condition */)


2 {
//Instructions à répéter
3
}

Nous allons travailler sur un exemple concret mais d'abord, réfléchissons à « comment notre boucle
va travailler ». Pour cela, il faut déterminer notre exemple.
Nous allons afficher « Bonjour, <un prénom> », prénom qu'il faudra taper au clavier ;
puis nous demanderons si l'on veut recommencer. Pour cela, il nous faut une variable qui va recevoir
le prénom, donc dont le type sera String, ainsi qu'une variable pour récupérer la réponse. Et là,
plusieurs choix s'offrent à nous : soit un caractère, soit une chaîne de caractères, soit un entier. Ici,
nous prendrons une variable de type char. C'est parti !

45
//Une variable vide
1 String prenom;
//On initialise celle-ci à O pour oui
char reponse = 'O';
2 //Notre objet Scanner, n'oubliez pas l'import de
java.util.Scanner !
3 Scanner sc = new Scanner(System.in);
//Tant que la réponse donnée est égale à oui…
4 while (reponse == 'O')
{
//On affiche une instruction
5
System.out.println("Donnez un prénom : ");
//On récupère le prénom saisi
6 prenom = sc.nextLine();
//On affiche notre phrase avec le prénom
7 System.out.println("Bonjour " +prenom+ ", comment
vas-tu ?");
//On demande si la personne veut faire un autre
8 essai
System.out.println("Voulez-vous réessayer ?
9 (O/N)");
1 //On récupère la réponse de l'utilisateur
0 reponse = sc.nextLine().charAt(0);
}
1
1 System.out.println("Au revoir…");
1 //Fin de la boucle

Vous avez dû cligner des yeux en lisant


reponse = sc.nextLine().charAt(0);. Rappelez-vous comment on récupère un char
avec l'objet Scanner : nous devons récupérer un objet String et ensuite prendre le premier caractère
de celui-ci ! Eh bien cette syntaxe est une contraction de ce que je vous avais fait voir auparavant.
Détaillons un peu ce qu'il se passe. Dans un premier temps, nous avons déclaré et initialisé nos
variables. Ensuite, la boucle évalue la condition qui nous dit : tant que la variable reponse contient
« O », on exécute la boucle. Celle-ci contient bien le caractère « O », donc nous entrons dans la
boucle. Puis l'exécution des instructions suivant l'ordre dans lequel elles apparaissent dans la boucle

46
a lieu. À la fin, c'est-à-dire à l'accolade fermante de la boucle, le compilateur nous ramène au début
de la boucle.
Cette boucle n'est exécutée que lorsque la condition est remplie : ici, nous avons initialisé la variable
reponse à « O » pour que la boucle s'exécute. Si nous ne l'avions pas fait, nous n'y serions jamais
entrés. Normal, puisque nous testons la condition avant d'entrer dans la boucle !

Voilà. C'est pas mal, mais il faudrait forcer l'utilisateur à ne taper que « O » ou « N ». Comment
faire ? C'est très simple : avec une boucle ! Il suffit de forcer l'utilisateur à entrer soit « N » soit « O
» avec un while ! Attention, il nous faudra réinitialiser la variable reponse à « ' ' » (caractère vide). Il
faudra donc répéter la phase « Voulez-vous réessayer ? » tant que la réponse donnée n'est pas « O »
ou « N ».
Voici notre programme dans son intégralité :

47
1 String prenom;
char reponse = 'O';
2
Scanner sc = new Scanner(System.in);
3 while (reponse == 'O')
4 {
5 System.out.println("Donnez un prénom : ");
prenom = sc.nextLine();
6
System.out.println("Bonjour " +prenom+ ", comment vas-
7 tu ?");
8 //Sans ça, nous n'entrerions pas dans la deuxième boucle
9 reponse = ' ';

10 //Tant que la réponse n'est pas O ou N, on repose la


11 question
12 while(reponse != 'O' && reponse != 'N')
{
13
//On demande si la personne veut faire un autre essai
14 System.out.println("Voulez-vous réessayer ? (O/N)");
15 reponse = sc.nextLine().charAt(0);
16 }
}
17
System.out.println("Au revoir…");
18

Vous pouvez tester ce code (c'est d'ailleurs vivement conseillé) : vous verrez que si vous n'entrez pas
la bonne lettre, le programme vous posera sans cesse sa question!
Attention à écrire correctement vos conditions et à bien vérifier vos variables dans vos while, et dans
toutes vos boucles en général. Sinon c'est le drame ! Essayez d'exécuter le programme précédent sans
la réinitialisation de la variable reponse, et vous verrez le résultat ! On n'entre jamais dans la
deuxième boucle, car reponse = 'O' (puisque initialisée ainsi au début du programme). Là,
vous ne pourrez jamais changer sa valeur… Le programme ne s'arrêtera donc jamais ! On appelle ça
une « boucle infinie ». En voici un autre exemple.

48
1 int a = 1, b = 15;
2 while (a < b)
3 {
4 System.out.println("coucou " +a+ "
5 fois !!");
}

Si vous lancez ce programme, vous allez voir une quantité astronomique de « coucou 1 fois !! ».
Nous aurions dû ajouter une instruction dans le bloc d'instructions de notre while pour changer

la valeur de a à chaque tour de boucle, comme ceci :

1 int a = 1, b = 15;
2 while (a < b)
3 {
4 System.out.println("coucou " +a+ "
5 fois !!");
6 a++;
}

Lorsque vous n'avez qu'une instruction dans votre boucle, vous pouvez enlever les accolades, car
elles deviennent superflues, tout comme pour les instructions if, else if ou else.
Vous auriez aussi pu utiliser cette syntaxe :

1 int a = 1, b = 15;
2 while (a++ < b)
3 System.out.println("coucou " +a+ " fois !!");

Souvenez-vous de ce dont je vous parlais au chapitre précédent sur la priorité des opérateurs. Ici,
l'opérateur « < » a la priorité sur l'opérateur d'incrémentation « ++ ». Pour faire court, la boucle
while teste la condition et ensuite incrémente la variable a. Par contre, essayez ce code :

49
1 int a = 1, b = 15;
2 while (++a < b)
3 System.out.println("coucou " +a+ " fois !!");

Vous devez remarquer qu'il y a un tour de boucle en moins ! Eh bien avec cette syntaxe, l'opérateur
d'incrémentation est prioritaire sur l'opérateur d'inégalité (ou d'égalité), c'est-à-dire que la boucle
incrémente la variable a, et ce n'est qu'après l'avoir fait qu'elle teste la condition !

3.2 La boucle do…. while


En effet, ces deux boucles(while et do…while) ne sont pas cousines, mais plutôt sœurs. Leur
fonctionnement est identique à deux détails près.

1 do{
2 //Instructions

3 }while(a < b);

Première différence
La boucle do… while s'exécutera au moins une fois, contrairement à sa sœur. C'est-à-dire que la
phase de test de la condition se fait à la fin, car la condition se met après le while.

Deuxième différence
C'est une différence de syntaxe, qui se situe après la condition du while. Vous voyez la différence ?
Oui ? Non ? Il y a un « ;» après le while. C'est tout ! Ne l'oubliez cependant pas, sinon le programme
ne compilera pas.
Mis à part ces deux éléments, ces boucles fonctionnent exactement de la même manière. D'ailleurs,
refaisons notre programme précédent avec une boucle do… while.

50
1 String prenom = new String();
//Pas besoin d'initialiser : on entre au moins une
2 fois dans la boucle !
3 char reponse = ' ';

4 Scanner sc = new Scanner(System.in);


5
do{
6 System.out.println("Donnez un prénom : ");
7 prenom = sc.nextLine();
System.out.println("Bonjour " +prenom+ ", comment
vas-tu ?");

do{
System.out.println("Voulez-vous réessayer ?
(O/N)");
reponse = sc.nextLine().charAt(0);
}while(reponse != 'O' && reponse != 'N');

}while (reponse == 'O');

System.out.println("Au revoir…");

Vous voyez donc que ce code ressemble beaucoup à celui utilisé avec la boucle while, mais il
comporte une petite subtilité : ici, plus besoin de réinitialiser la variable reponse, puisque de toute
manière, la boucle s'exécutera au moins une fois !

3.3 La boucle for


Cette boucle est un peu particulière puisqu'elle prend tous ses attributs dans sa condition et agit en
conséquence. Je m'explique : jusqu'ici, nous avions fait des boucles avec :

● déclaration d'une variable avant la boucle ;

● initialisation de cette variable ;

● incrémentation de celle-ci dans la boucle.

Eh bien on met tout ça dans la condition de la boucle for, et c'est tout. Il existe une autre syntaxe
pour la boucle for depuis le JDK 1.5. Nous la verrons lorsque nous aborderons les tableaux.

51
1 for(int i = 1; i <= 10; i++)
2 {
System.out.println("Voici la ligne "+i);
3
}
4

Vous aurez sûrement remarqué la présence des « ; » dans la condition pour la séparation des champs.
Ne les oubliez surtout pas, sinon le programme ne compilera pas.
Nous pouvons aussi inverser le sens de la boucle, c'est-à-dire qu'au lieu de partir de 0 pour aller à 10,
nous allons commencer à 10 pour atteindre 0 :

1 for(int i = 10; i >= 0; i--)


2 System.out.println("Il reste "+i+" ligne(s) à
écrire");

● Les boucles vous permettent simplement d'effectuer des tâches répétitives.

● Il existe plusieurs sortes de boucles :

○ la boucle while(condition){…} évalue la condition puis exécute

éventuellement un tour de boucle (ou plus) ;

○ la boucle do{…}while(condition); fonctionne exactement comme la

précédente, mais effectue un tour de boucle quoi qu'il arrive ;

○ la boucle for permet d'initialiser un compteur, une condition et un incrément

dans sa déclaration afin de répéter un morceau de code un nombre limité de fois.

● Tout comme les conditions, si une boucle contient plus d'une ligne de code à exécuter, vous

devez l'entourer d'accolades afin de bien en délimiter le début et la fin.

52
Chapitre 5 :
Les concepts orientés objets
Chaque langage de programmation appartient à une “famille” de langages définissant une approche
ou une méthodologie générale de programmation. Par exemple, le langage C est un langage de
programmation procédurale car il suppose que le programmeur s’intéresse en priorité aux
traitements que son programme devra effectuer. Un programmeur C commencera par identifier ces
traitements pour écrire les fonctions qui les réalisent sur des données prises comme paramètres
d’entrée.
La programmation orientée-objet (introduite par le langage SmallTalk) propose une méthodologie
centrée sur les données. Le programmeur Java va d’abord identifier un ensemble d’objets, tel que
chaque objet représente un élément qui doit être utilisé ou manipulé par le programme, sous la forme
d’ensembles de données. Ce n’est que dans un deuxième temps, que le programmeur va écrire les
traitements, en associant chaque traitement à un objet donné. Un objet peut être vu comme une
entité regroupant un ensemble de données et de méthodes (l’équivalent d’une fonction en C) de
traitement.
La POO est dirigée par trois fondamentaux qu'il convient de toujours garder à l'esprit :
Encapsulation, héritage et polymorphisme.

1. Notion de classe
Un objet est une variable (presque) comme les autres. Il faut notamment qu’il soit déclaré avec son
type. Le type d’un objet est un type complexe (par opposition aux types primitifs entier, caractère, …)
qu’on appelle une classe.
Une classe est un modèle de la structure statique (les champs ou attributs) et du comportement
dynamique (les opérations ou méthodes) des objets associés à cette classe.
Une classe est un modèle d'objet. C'est un nouveau type créé par le programmeur et qui sert de
modèle pour tous les objets de cette classe. Une classe spécifie les informations et les actions
qu'auront en commun tous les objets qui en sont issus.
Une classe regroupe un ensemble de données (qui peuvent être des variables primitives ou des objets)
et un ensemble de méthodes de traitement de ces données et/ou de données extérieures à la classe.
On parle d’encapsulation pour désigner le regroupement de données dans une classe.
Par exemple, une classe Rectangle utilisée pour instancier des objets représentant des
rectangles, encapsule 4 entiers : la longueur et la largeur du rectangle ainsi que la position en abscisse
et en ordonnée de l’origine du rectangle (par exemple, le coin en haut à gauche). On peut alors

53
imaginer que la classe Rectangle implémente une méthode permettant de déplacer le rectangle qui
nécessite en entrée deux entiers indiquant la distance de déplacement en abscisse et en ordonnée.
L’accès aux positions de l’origine du rectangle se fait directement (i.e. sans passage de paramètre)
lorsque les données sont encapsulées dans la classe où est définie la méthode.
Représentation graphique:

Rectangle

- longueur
- largeur
- origine_x
- origine_y

+ deplace()
+ surface()

Représentation en code:
Un exemple, écrit en Java, de la classe Rectangle est donné ci-dessous :

public class Rectangle {

int longueur;
int largeur;
int origine_x;
int origine_y;

public void deplace( int x, int y) {


this.origine_x = this.origine_x + x;
this.origine_y = this.origine_y + y;

public int surface() {

return this.longueur * this.largeur;

}
}

Pour écrire un programme avec un langage orienté-objet, le programmeur écrit uniquement des
classes correspondant aux objets de son système. Les traitements à effectuer sont programmés dans
les méthodes de ces classes qui peuvent faire appel à des méthodes d’autres classes. En général, on

54
définit une classe, dite “exécutable”, dont une méthode peut être appelée pour exécuter le
programme.
1.1. Encapsulation
Lors de la conception d’un programme orienté-objet, le programmeur doit identifier les objets et les
données appartenant à chaque objet mais aussi des droits d’accès qu’ont les autres objets sur ces
données. L’encapsulation de données dans un objet permet de cacher ou non leur existence aux
autres objets du programme. Une donnée peut être déclarée en accès :
● Public ou + :
les autres objets peuvent accéder à la valeur de cette donnée ainsi que la modifier ;
● Privé ou private ou - :
les autres objets n’ont pas le droit d’accéder directement à la valeur de cette donnée (ni de la
modifier). En revanche, ils peuvent le faire indirectement par des méthodes de l’objet concerné (si
celles-ci existent en accès public).
● Protégé ou protected ou #:
L’élément protégé est accessible aux objets de la classe dans laquelle il est défini et aux objets des
classes dérivées.
public protected défaut private
Dans la même classe Oui Oui Oui Oui
Dans une classe du Oui Oui Oui Non
même package
Dans une sous-classe Oui Oui Non Non
d’un autre package
Dans une classe quelcon- Oui Non Non Non
que d’un autre package

Table 1: Autorisation des accès

1.2. Méthode Constructeur

Chaque classe doit définir une ou plusieurs méthodes particulières appelées des constructeurs. Un
constructeur est une méthode invoquée lors de la création d’un objet. Cette méthode, qui peut être
vide, effectue les opérations nécessaires à l’initialisation d’un objet. Chaque constructeur doit avoir
le même nom que la classe où il est défini et n’a aucune valeur de retour (c’est l’objet créé qui est
renvoyé).
Règles particulières des constructeurs :
● Un constructeur doit toujours être une méthode publique
● Vous devez impérativement donner le même nom que votre classe au constructeur
● Un constructeur ne retourne rien, c'est-à-dire que vous n'ajouterez pas de return dans cette
méthode.

55
● Vous ne devez pas mettre de void, même si le constructeur ne retourne rien.
Dans l’exemple précédent de la classe rectangle, le constructeur initialise la valeur des données
encapsulées :

public class Rectangle {


...
public Rectangle( int lon, int lar) {
this.longueur = lon;
this.largeur = lar;
this.origine_x = 0;
this.origine_y = 0;
}
...
}

❖ Constructeur par défaut : Sans Paramètre


Si on crée un constructeur par défaut on définit des valeurs par défaut.
public class Rectangle {
...
public Rectangle ()
{
longueur = 5;
largeur = 3;
origine_x = 0;
origine_y = 0;
}
}

❖ Constructeur par recopie:


public class Rectangle {
...
public Rectangle (Rectangle r)
{
longueur = r.longueur;
largeur = r.largeur;
origine_x = r.origine_x ;
origine_y = r.origine_y ;
}
}

56
Un constructeur de copie, appelé aussi « constructeur par recopie », est un constructeur qui admet
comme paramètre un objet (de la même classe) déjà existant.
1.3. Destructeur
Un destructeur est une opération de classe qui détruit des objets. Cette méthode libère donc de
l'espace mémoire. Le garbage collector est un "ramasse-miettes" chargé de faciliter la tâche des
programmeurs en libérant les ressources prises en mémoire automatiquement. Cette méthode n'est
pas forcément appelée lorsque vous supprimez l'objet.
Pour utiliser le destructeur vous devez redéfinir une méthode appelée finalize() publique et qui ne
renvoie rien. On peut donc avoir le code suivant :
public class Rectangle {
...
public Rectangle (Rectangle r)
{
longueur = r.longueur;
largeur = r.largeur;
origine_x = r.origine_x ;
origine_y = r.origine_y ;
}
public finalize ();
}
1.4. Les accesseurs et les mutateurs(get/set)

Un accesseur(get) est une méthode permettant de récupérer le contenu d'une donnée membre
protégée. Un accesseur, pour accomplir sa fonction :
● doit avoir comme type de retour le type de la variable à renvoyer
● ne doit pas nécessairement posséder d'arguments
Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom de
l'accesseur par le préfixe get, afin de faire ressortir sa fonction première.
➔ get: permet de lire la valeur d’un attribut.

La syntaxe d'un accesseur réduit à sa plus simple expression ressemble donc à ceci :
public class Rectangle {
int longueur;
int largeur;
int origine_x;
int origine_y;
public int getLongueur ()
{

57
return longueur;
}
}
Un mutateur(set) est une méthode permettant de modifier le contenu d'une donnée membre
protégée. Un mutateur, pour accomplir sa fonction :
● doit avoir comme paramètre la valeur à assigner à la donnée membre. Le paramètre doit donc
être du type de la donnée membre
● ne doit pas nécessairement renvoyer de valeur (il possède dans sa plus simple expression le
type void)
Une convention de nommage veut que l'on fasse commencer de façon préférentielle le nom du
mutateur par le préfixe set.
La syntaxe d'un mutateur réduit à sa plus simple expression ressemble donc à ceci :
➔ Set : permet de modifier la valeur d’un attribut.

public class Rectangle {


int longueur;
int largeur;
int origine_x;
int origine_y;

public int getLongueur ()


{
return longueur;
}
public void setLongueur(int l)
{
longueur = l ;
}
}

NB : Pour chaque attribut on a toujours une méthode get et set

2. Notion d’objet
Un objet représente une entité individuelle et identifiable, réelle ou abstraite, avec un rôle bien défini
dans le domaine du problème, chaque objet peut être caractérisé par une identité, des états
significatifs et par un comportement.

2.1. Instanciation

58
Un objet est une instance (anglicisme signifiant « cas » ou « exemple ») d’une classe et est référencé
par une variable ayant un état (ou valeur). Pour créer un objet, il est nécessaire de déclarer une
variable dont le type est la classe à instancier, puis de faire appel à un constructeur de cette classe.
L’exemple ci-dessous illustre la création d’un objet de classe Cercle en Java :

Cercle mon_rond;
mon_rond = new Cercle();

L’usage de parenthèses à l’initialisation du vecteur, montre qu’une méthode est appelée pour
l’instanciation. Cette méthode est un constructeur de la classe Cercle. Si le constructeur appelé
nécessite des paramètres d’entrée, ceux-ci doivent être précisés entre ces parenthèses (comme lors
d’un appel classique de méthode). L’instanciation d’un objet de la classe Rectangle faisant appel au
constructeur donné en exemple ci-dessous pourra s’écrire :

Rectangle mon_rectangle = new Rectangle(1,3) ;

☛ Remarque importante : en Java, la notion de pointeur est transparente pour le


programmeur.
Il faut néanmoins savoir que toute variable désignant un objet est un pointeur. Il s’ensuit alors
que le passage d’objets comme paramètres d’une méthode est toujours un passage par
référence. A l’inverse, le passage de variables primitives comme paramètres est toujours un
passage par valeur.
2.2. Accès aux variables et aux méthodes
Pour accéder à une variable associée à un objet, il faut préciser l’objet qui la contient. Le symbole ’.’
sert à séparer l’identificateur de l’objet de l’identificateur de la variable. Une copie de la longueur
d’un rectangle dans un entier temp s’écrit :
int temp = mon_rectangle.longueur;

La même syntaxe est utilisée pour appeler une méthode d’un objet. Par exemple :
mon_rectangle.deplace(0,0) ;

Pour qu’un tel appel soit possible, il faut que trois conditions soient remplies :
a. La variable ou la méthode appelée existe !
b. Une variable désignant l’objet visé existe et soit instanciée.
c. L’objet, au sein duquel est fait cet appel, ait le droit d’accéder à la méthode ou à la variable.

59
Pour référencer l’objet “courant” (celui dans lequel se situe la ligne de code), le langage Java fournit
le mot-clé this. Celui-ci n’a pas besoin d’être instancié et s’utilise comme une variable désignant
l’objet courant. Le mot-clé this est également utilisé pour faire appel à un constructeur de l’objet
courant. Ces deux utilisations possibles de this sont illustrées dans l’exemple suivant :

class Carre {
int cote;
int origine_x;
int origine_y;
Carre( int cote, int
x, int y) {
this.cote = cote;
this.origine_x =
x;
this.origine_y =
y;
}
Carre( int cote){
this cote, 0, 0 ;
}
}

60
Chapitre 6
Héritage
1. Héritage
Le principe
Quand on dispose d’une classe c, on a la possibilité de l’agrandir (ou de l’étendre) en créant une
deuxième classe c0. On dit dans ce cas que c0 hérite de c, ou encore que c est la classe mère et c0 la classe
fille. Par exemple, considérons les deux classes suivantes :
package heritage;
public class ClasseMere{
private final int x;

public ClasseMere( int x){


this.x=x;
}
public int getX(){
return x;
}
}
package heritage;
public class ClasseFille extends ClasseMere{
private final int y;

public ClasseFille( int x,y){


super(x);
this.y=y;
}
public int getY(){
return y;
}
}
Le mot-clé extends signifie hérite de. Le mot-clé super est le constructeur de la classe mère. Tout ce
qui peut être fait avec la classe mère peut aussi être fait avec la classe fille. Notez donc que la classe
fille est une extension de la classe mère. On peut par exemple utiliser la classe fille de la façon
suivante :
package heritage ;

public class TestClasseFille{


public static void main(String[] args){
ClasseFille o = new ClasseFille(1,2);
System.out.println(“(”+o.getX()+”,”+o.getY()+”)”);
}
}

61
Notes bien que comme la classe mère possède une méthode getX, la classe fille la possède aussi. Et
l’attribut x de tout instance de la classe mère est aussi un attribut de toute instance de la classe fille.

Héritage simple Vs. héritage multiple

En java, une classe ne peut avoir qu’une seule classe mère. Dans d’autres langages (comme le C++)
cela est permis, mais pour des raisons de fiabilité, Java l’interdit.

Object

En java, toutes les classes héritent implicitement d’une classe Object. L’ensemble des classes
Java, y compris celles écrites en dehors de l’API, forme une hiérarchie avec une racine unique.
Cette racine est la classe Object dont hérite toute autre classe. En effet, si vous ne précisez pas
explicitement une relation d’héritage lors de l’écriture d’une classe, celle-ci hérite par défaut de la
classe Object. Grâce à cette propriété, des classes génériques de création et de gestion d’un
ensemble, plus élaborées que les tableaux, regroupent des objets appartenant à la classe Object
(donc de n’importe quelle classe).
Une des propriétés induites par le polymorphisme est que l’interpréteur Java est capable de
trouver le traitement à effectuer lors de l’appel d’une méthode sur un objet. Ainsi, pour plusieurs
objets déclarés sous la même classe (mais n’ayant pas la même classe réelle), le traitement associé à
une méthode donnée peut être différent. Si cette méthode est redéfinie par la classe réelle d’un
objet (ou par une classe située entre la classe réelle et la classe de déclaration), le traitement effectué
est celui défini dans la classe la plus spécifique de l’objet et qui redéfinit la méthode.

2. Polymorphisme
Considérons l’exemple suivant :
package heritage ;
public class TestClasseFillePolymorphisme{
public static void main(String [] args){
ClasseMere o = new ClasseFille(1,2);
System.out.println(“(”+o.getX()+”,”
+((ClasseFille)o).getY()+”)”);
}
}
On remarque d’une part que o référence un objet de la classe fille de son type. Cela s’appelle le
polymorphisme. D’autre part, si l’on souhaite effectuer des opérations spécifiques aux objets de la
classe fille, il est nécessaire d’effectuer un cast.

3. Redéfinition de méthodes

62
La méthode toString() appartient initialement à la classe Object. Elle est donc héritée par toutes les
classes. Vous avez la possibilité de la redéfinir, c'est-à-dire de remplacer la méthode par défaut par
une méthode davantage adaptée à la classe en question.

4. Interfaces
L’héritage multiple est interdit en Java. Les interfaces sont un moyen de résoudre en partie le
problème.
Une interface est un ensemble de constantes et de méthodes vides. Il est impossible d’instancier une
interface. On utilise une interface en créant une classe qui en hérite et qui contient le corps des
méthodes qui y sont déclarées.. Dans le cas où la classe mère est une interface, le mot-clé implements
prend la place de extends.
L’utilité du concept d’interface réside dans le regroupement de plusieurs classes, tel que chacune
implémente un ensemble commun de méthodes, sous un même type. Une interface possède les
caractéristiques suivantes :
● elle contient des signatures de méthodes ;
● elle ne peut pas contenir de variables ;
● une interface peut hériter d’une autre interface (avec le mot-clé extends) ;
● une classe (abstraite ou non) peut implémenter plusieurs interfaces. La liste des interfaces
implémentées doit alors figurer après le mot-clé implements placé dans la déclaration de
classe, en séparant chaque interface par une virgule.
En voici un exemple d’utilisation :
package heritage ;
import java . util . ArrayList ;
interface Saluer{
public void direBonjour () ;
}

class Bonjour implements Saluer{


@Override
public void direBonjour (){
System.out.println(“Bonjour”);
}
}
class Hello implements Saluer{
@Override
public void direBonjour (){
System.out.println(“Hello”);
}
}
class GutenTag implements Saluer{
@Override
public void direBonjour (){
System.out.println(“Guten Tag”);
}

63
}

public class ExempleInterface{


public static void main(String [ ] args){
Saluer s= new Bonjour();
s.direBonjour();
s = new Hello();
s.direBonjour();

ArrayList<Saluer> arrayList = new ArrayList<Saluer >() ;


arrayList.add(new Bonjour());
arrayList.add(new Hello());
arrayList.add(new GutenTag());

for (Saluer saluer : arrayList){


saluer.direBonjour();
}

}
}

Vous remarquez que la méthode Saluer est implémentée par les trois classes Bonjour, Hello et
GutenTag, qui contiennent trois façons différentes de programmer la méthode public void saluer().
Le polymorphisme permet de mettre dans une référence de type Saluer tout objet dont le type hérite
de Saluer.
On peut voir une interface comme un contrat :
§ Toute sous-classe d’une interface se doit d’implémenter toutes les méthodes qui y sont
déclarées.
§ En échange, il devient possible d’utiliser le polymorphisme, et donc d’utiliser le même
code avec des objets de types différents.
La restriction interdisant l’héritage multiple en Java ne s’applique pas aux interfaces. Une classe peut
implémenter plusieurs interfaces.

5. Classes Abstraites
Nous voulons représenter des sommes dans des devises différentes et implémenter
automatiquement les conversions. Nous allons créer une classe devise qui contiendra l’attribut
somme et nous utiliserons l’héritage pour implémenter les spécificités des diverses devises (Euros,
Dollars, Livres, ...).
package heritage;
public abstract class Devise{
private double somme = 0;
/∗
∗ Nombre de devises pour 1$ .
∗/

64
public abstract double getCours () ;
public abstract String getUnite () ;
protected void setSomme(double somme){
this.somme=somme;
}

protected void setSomme(Devise d){


setSomme(d.getSomme()∗this.getCours()/d.getCours());
}

public double getSomme (){


return somme ;
}

@override

public String toString(){

return "somme = " + somme + " " + getUnite () ;

}
public class Livres extends Devise{

public Livres(Devise d) {
setSomme(d);
}

public Livres(double somme){


setSomme(somme);
}
@Override
public double getCours (){
return 0.76636574;

@Override public String getUnite (){

return “Livres”;}

public class Euros extends Devise{

public Euros(Devise d){


setSomme(d) ;
}

public Euros(double somme){


setSomme(somme) ;
}

@Override public double getCours(){


return 0.895744319;
}

65
@Override public String getUnite (){
return "Euros" ;
}

public class Dollars extends Devise{

public Dollars(Devise d){


setSommet(d);
}
public Dollars(double somme){
setSomme(somme);
}

@Override
public double getCours(){
return 1.0;
}

@Override

public String getUnite (){

return "Dollars" ;

public static void main(String [ ] args) {

Devise devise = new Dollars (12) ;


System.out.println(devise) ;
devise = new Euros(devise) ;
System.out.println(devise) ;
devise = new Livres(devise) ;
System.out.println(devise) ;
devise = new Dollars(devise) ;
System.out.println(devise) ;
}
Ces classes permettent de prendre en charge automatiquement les conversions entre devises. La
classe Devise contient une méthode setSomme qui est surchargée et qui peut prendre en paramètre
soit une somme exprimée dans la bonne unité, soit une autre devise.
On remarque qu’il est impossible d’implémenter getCours() car le cours varie selon la devise. La
classe Euros hérite de la classe Devise et implémente getCours(). La classe Dollars fonctionne de
façon similaire.

66
Chapitre 7
Les Tableaux en JAVA
1. Déclaration
Un tableau en Java est un objet. Il est nécessaire de le créer par allocation dynamique avec un new
en précisant ses dimensions. On note:

T[]
Le type tableau d’éléments de type T. La taille du tableau n’est précisée qu’à l’instanciation. On
déclare un tableau t d’éléments de type T de la façon suivante :

T [ ] t;

Par exemple, si l’on souhaite créer un tableau i d’éléments de type int, on utilise l’instruction :

int [ ] i ;

2. Instanciation
Comme un tableau est un objet, il est nécessaire d’instancier pendant l’exécution. On instancie un
tableau avec l’instruction

new T[taille];

Par exemple, si l’on souhaite déclarer et allouer dynamiquement un tableau de 100 entiers, en utilise

int [ ] i= new int [100];

3. Accès aux éléments


On accède aux éléments d’un tableau avec la notation à crochets, par exemple,

67
int [ ] t =new int [100];
for ( int i = 0 ; i < 100; i++)
{
t [ i ] = 100 − (i + 1) ;
System.out.println(t [ i ]) ;
}

On remarque que la variable i est déclarée à l’intérieur de la boucle for, cette façon de déclarer les
variables est très utile en Java. Dans l’exemple,
package tableaux ;

public class ExempleTableau


{
public static void main(String [ ] args){
final int T = 20;
int [ ] t = new int [ T ] ;
for ( int i = 0; i < T ; i++) t[i]=i ;
for ( int i = 0; i < T ; i++)
System.out.println(t[ i ]) ;
}
}

4. Longueur d’un tableau


Pour connaître la taille d’un tableau on utilise l’attribut length. Par exemple,

int [ ] t = new int [ T ] ;


for(int i = 0;i<t.length;i++) t[i]=i;
for ( int i=0;i<t.length;i++)
System.out.println(t[i]) ;

5. Tableaux à plusieurs dimensions


On crée un tableau à plusieurs dimensions (3 par exemple) en juxtaposant plusieurs crochets. Par
exemple,

68
int [ ] [ ] [ ] t = new int [ 2 ] [ 2 ] [ 2 ] ;
for(int i=0; i<2; i++)
for(int j=0; i<2; j++)
for(int k=0; i<2; k++)
{
t[i][j][k] = 100∗i+10∗j+k;
System.out.println(t[i][j][k]) ;
}

Ou encore,
package tableaux ;

public class ExempleCubique{


public static void main(String
[ ] args){
final int T = 3;
int[][][] u = new int [T][T][T];
for ( int i=0; i<T; i++)
for(int j=0;j<T; j++)
for(int k=0; k<T;k++){
u[i][j][k]=100∗i+10∗j+k;
System.out.println(u[i][j][k];
}

}
}

69

Vous aimerez peut-être aussi