Professional Documents
Culture Documents
439 Poly Java Version Web
439 Poly Java Version Web
le langage Java
Objectifs 11
Pourquoi Java ? 13
I - Introduction 15
A. Les langages de programmation............................................................15
B. Origine et historique de Java................................................................18
C. Java aujourd'hui..................................................................................18
D. Caractéristiques techniques de Java......................................................19
E. Qualités et défauts de Java...................................................................20
F. JRE, Java SE, JDK, Eclipse, ..................................................................21
G. Les différentes « éditions » du langage Java...........................................22
H. Langages et technologies connexes.......................................................22
II - Syntaxe de base 25
A. Premiers exemples..............................................................................25
B. Variables, types, portée, commentaires, ….............................................26
1. Variables et types.............................................................................................26
2. Types « primitifs »............................................................................................26
3. Le type booléen................................................................................................27
4. Le type caractère..............................................................................................27
5. Les types entiers..............................................................................................28
6. Les types flottants............................................................................................28
7. Constantes......................................................................................................29
8. Déclaration et portée des variables.....................................................................30
9. Conventions de nommage.................................................................................30
10. Commentaires................................................................................................31
C. Opérateurs.........................................................................................31
1. Principaux opérateurs.......................................................................................31
2. Opérateurs arithmétiques..................................................................................32
3. Opérateurs de comparaison...............................................................................33
4. Opérateurs booléens.........................................................................................33
5. Opérateurs bit-à-bit..........................................................................................34
6. Opérateurs d'affectation....................................................................................34
7. Opérateurs d'incrémentation et de décrémentation...............................................35
8. Autres opérateurs.............................................................................................35
9. Priorité des opérateurs......................................................................................35
3
7. Boucles d'itération « simplifiées ».......................................................................40
8. Interruptions des boucles, labels........................................................................41
E. Entrées-sorties....................................................................................42
F. Exemple de programme, compilation, exécution......................................45
IV - Fonctions 57
A. Introduction.......................................................................................57
B. Type de retour et instruction return.......................................................58
C. Appel (ou « invocation » ) de fonction....................................................59
D. Fonction et portée...............................................................................59
E. Programme principal............................................................................60
F. Passage des paramètres.......................................................................60
G. Récursivité.........................................................................................62
H. Surcharge (ou « overloading »)............................................................62
I. Fonctions à nombre variable d'arguments...............................................62
J. Fonctions « natives »...........................................................................63
4
3. Méthodes........................................................................................................81
4. Constructeur....................................................................................................81
5. Instanciation (mot-clé : new).............................................................................82
6. Tableau d'objets...............................................................................................83
7. L'instruction instanceof......................................................................................83
8. Destructeur.....................................................................................................84
C. This...................................................................................................84
1. this(...) dans un constructeur.............................................................................84
2. this comme référence........................................................................................84
D. Static................................................................................................85
1. Mot-clé static...................................................................................................85
2. Attribut statique...............................................................................................85
3. Initialiseur statique...........................................................................................86
4. Méthode statique..............................................................................................87
5. Appel de méthode statique................................................................................87
6. Static or not static ?..........................................................................................88
E. Visibilité.............................................................................................88
F. Types énumérés..................................................................................89
VII - Exceptions 91
A. Principe des exceptions........................................................................91
B. Gestion des erreurs.............................................................................91
C. Traitement des exceptions....................................................................93
D. Nature des exceptions.........................................................................93
E. Catégories d'exceptions........................................................................94
F. Exceptions contrôlées ou non................................................................94
G. Types d'exception usuels.....................................................................95
H. Lancement d'exception........................................................................95
I. Création de nouveaux types d'exception.................................................96
J. Clause throws......................................................................................96
K. Assertions..........................................................................................97
5
IX - Listes, piles, files, arbres 109
A. Problématique commune....................................................................109
B. Listes...............................................................................................110
1. Introduction...................................................................................................110
2. Fonctions de manipulation...............................................................................111
3. Implantation..................................................................................................112
4. Applications...................................................................................................113
C. Piles................................................................................................113
1. Introduction...................................................................................................113
2. Fonctions de manipulation...............................................................................114
3. Piles : implantation.........................................................................................114
4. Application.....................................................................................................115
D. Files................................................................................................116
1. Introduction...................................................................................................116
2. Fonctions de manipulation...............................................................................116
3. Implantation..................................................................................................117
4. Applications...................................................................................................117
E. Arbres..............................................................................................117
1. Introduction...................................................................................................117
2. Récursivité....................................................................................................117
3. Vocabulaire....................................................................................................118
4. Arbres binaires...............................................................................................118
5. Numérotation des nœuds.................................................................................118
6. Parcours........................................................................................................119
7. Exemple de parcours RGD en java....................................................................119
8. Fonctions de manipulation d'arbres binaires.......................................................119
9. Implantation..................................................................................................120
10. Applications.................................................................................................120
6
11. Classe non dérivable.....................................................................................133
12. Méthode non redéfinissable............................................................................133
13. Héritage et tableau.......................................................................................134
14. la classe « Object ».......................................................................................134
15. Méthode clone()...........................................................................................136
16. Programmation « générique » via la classe Object.............................................136
E. Introspection....................................................................................137
7
XIV - Le paquetage java.lang 159
A. Le paquetage java.lang......................................................................159
B. La classe Math..................................................................................160
C. La classe StrictMath...........................................................................161
D. La classe System..............................................................................161
E. La classe Runtime..............................................................................162
F. La classe Process...............................................................................162
G. Les classes « enveloppes ».................................................................162
H. La classe Character...........................................................................163
I. La classe Number et ses classes filles...................................................163
J. La classe Enum..................................................................................164
K. La classe Class..................................................................................164
L. La classe Field...................................................................................165
M. La classe Method..............................................................................166
N. Interfaces pré-définies à connaître......................................................166
8
J. Dimensions de l'écran et des composants.............................................195
K. Applet vs application..........................................................................196
L. Ecrire une applet...............................................................................196
M. Ecrire une application graphique.........................................................201
N. Swing..............................................................................................203
O. Pour aller plus loin............................................................................205
Index 225
9
Objectifs
Ce document est conçu pour servir de support de cours principal au tronc commun
d'Informatique.
Il couvre au plus près les aspects algorithmique et programmation de cet enseignement
(mais pas les aspects architecture des ordinateurs et systèmes d'exploitation pour lesquels
d'autres documents ont été distribués) en suivant autant que possible l'ordre des séances.
Il comporte un certain nombre de compléments et d'exemples qui ne seront pas
nécessairement détaillés lors des petites classes.
Il ne saurait toutefois remplacer un ouvrage de référence sur le langage Java, ou
sur l'algorithmique, et encore moins l'ensemble des documentations, cours et
bases d'exemples disponibles via le site web de l'Ecole.
NOTE : ce support de cours a pour origine un diaporama sur la programmation en Java,
écrit par Fabien Moutarde et Norbert Kajler. Il s'agit ici d'une version complétement
réécrite, avec le concours actif de Norbert Kajler et Jean-Michel Viovy, et la participation de
toute l'équipe du CCSI. Cette version utilise la chaîne éditoriale « Scénari ».
Nous vous remercions par avance de signaler toute erreur ou imprécision aux
auteurs.
11
Pourquoi Java ?
Java a été choisi par l'équipe enseignante en tant que compromis entre :
langage puissant, incluant un maximum de paradigmes de programmation
pertinents à enseigner car généralement non maîtrisés par la plupart des élèves
admis en 1° année (typage fort, références, programmation objet, exceptions,
événements et programmation réactive, threads, ...) ;
langage pouvant constituer un 2° langage idéal pour des élèves qui connaissent déjà
soit un langage moins riche et/ou moins général que Java (Maple, Mathematica,
Pascal, Basic, JavaScript, PHP, ...) soit un langage essentiellement fonctionnel
(CAML, Lisp, ...) de nature très différente ;
langage relativement facile à maîtriser sans avoir suivi au préalable un
enseignement d'Informatique avancé ;
langage non-spécialisé, permettant l'écriture de programmes de toutes sortes,
de toutes tailles, et dans tous les domaines ;
langage largement utilisé dans l'industrie du logiciel 1 ;
langage mature et très bien documenté (existence de nombreux cours, FAQs,
bases d'exemples couvrant tous les aspects du langage) en anglais français, et bien
d'autres langues si besoin ;
langage disponible gratuitement sur l'ensemble des matériels, et doté d'une
vaste bibliothèque de classes et de nombreux outils de développement
également gratuits.
Java n'est certes pas optimal sur l'ensemble de ces critères ; il constitue néanmoins – du
point de vue de l'équipe enseignante – le meilleur compromis disponible étant donné
l'objectif de cours et les connaissances préalables des élèves.
Par ailleurs, l'équipe enseignante considère que la maîtrise d'un langage de programmation
donné importe moins que la maîtrise des notions sous-jacentes même si, dans le cas
particulier de Java, l'expérience acquise peut être directement valorisée (stages, junior
entreprise, ...) étant donné le nombre de projets informatiques réalisés à l'aide de ce
langage (y compris le développement d'applications Android).
Ainsi, apprendre à programmer en Java est avant tout un moyen d'étudier, et pratiquer, un
certain nombre de principes et styles de programmation essentiels (et que l'on retrouve
dans beaucoup d'autres langages).
Ce faisant, l'apprentissage de java constitue une étape dans l'étude de l'Informatique en
général, et en particulier dans la capacité à écrire des programmes non-triviaux dans un
langage fortement typé.
A l'issue de cet enseignement, il devrait être assez facile aux élèves qui en auraient besoin
d'apprendre à programmer dans n'importe lequel des autres langages très répandus
aujourd'hui (C, C++, C#, Python ...) ou qui émergent depuis quelques années (Scala,
Ruby, ...).
1 - Java est en 1° ou 2° place dans les différents classements sur l'utilisation des langages de programmation
(TIOBE, Transparent Language Popularity Index, PYPL, RedMonk Programming Language Rankings, ...)
13
14
I- Introduction
Définition
Langage binaire : langage natif de l'ordinateur, spécifique à un type
d'ordinateur ; programmes constitués d'une suite de zéros et de uns,
directement exécutables par l'ordinateur mais incompréhensibles ou presque
par un être humain.
Assembleur : langage de « bas niveau » spécifique à un processeur et très
proche du langage de l'ordinateur, donc difficile à comprendre pour un être
humain mais trivial à transcrire en langage binaire (en assembleur chaque
instruction du langage correspond à une instruction élémentaire du processeur,
par exemple : affecter une valeur à une case mémoire, comparer deux valeurs,
poursuivre l'exécution à une adresse mémoire donnée, ...)
Langage de « haut niveau » : par opposition au langage binaire et à
l'assembleur, langage relativement lisible pour un être humain et nécessitant
15
un gros travail de transcription en langage binaire ; les langages de « haut
niveau » se déclinent en plusieurs catégories ─ pas forcément exclusives les
unes des autres ─ selon le style de programmation qu'ils préconisent :
- style impératif : le programme correspond à une suite d'instructions
totalement explicitées et regroupées en modules/procédures/instructions.
- style logique : un programme correspond à une suite de « faits » et de
« règles » à partir desquels sera créée automatiquement la séquence
d'instructions exécutée par l'ordinateur ; dans un langage de
« programmation logique » tel que Prolog le code décrit ce qui doit être fait
en termes abstraits, sans se préoccuper du comment cela sera fait (ce qui
limite en pratique les domaines d'applications et engendre des problèmes
de performances) ; en cela les langages de « programmation logique » sont
à l'opposé des langages impératifs.
- style fonctionnel : les programmes sont des fonctions au sens
mathématique – fonctions « d'ordre supérieur »2 y compris, ce qui fait qu'il
n'existe pas de distinction fondamentale entre programmes et données en
programmation fonctionnelle (un programme dans un langage fonctionnel
tel que Lisp, ML/CAML, Haskell, etc. peut typiquement en cours de
traitement produire un autre programme qui crée un troisième programme
qui s'applique à des données dont la nature est elle-même un programme).
- style orienté objets : repose sur un certain nombre d'abstractions
positionnées au cœur du langage – encapsulation, classes, instances,
attributs, méthodes, héritage, ... (voir plus loin) ; la plupart des langages
orientés objets sont des langages essentiellement impératifs (C++, Java)
avec des aspects fonctionnels plus ou moins prononcés.
2 - On appelle fonction d'ordre supérieur une fonction prenant d'autres fonctions en paramètres. Par exemple,
le calcul formel de la dérivée étant données une fonction et une variable est une fonction d'ordre supérieur.
Autre exemple : une fonction qui prend en paramètres deux fonctions f et g et une liste l et qui applique la
fonction f à tous les éléments de la liste dont l'image par g est vraie.
16
Introduction
particularités des processeurs ARM (très utilisés dans les smartphones, tablettes, ...)
est leur formidable flexibilité, à tel point que certaines versions disposent de mode(s)
permettant d'exécuter du bytecode Java plus efficacement3.
Complément
Le diagramme ci-dessus présente quelques uns des langages de programmation
« généralistes » (permettant d'écrire une grande variété de programmes dans de
nombreux domaines) qui ont été développés depuis l'apparition des premiers
ordinateurs. Y sont ainsi visibles, les langages généralistes ayant été les plus utilisés
au fil des ans et/ou ayant le plus influencé les langages utilisés aujourd'hui.
Outre les langages généralistes, il existe des milliers de langages de programmation
plus ou moins spécialisés, autrement dit, des langages qui ont été développés pour
écrire des programmes dans des domaines spécifiques (e.g. VHDL 4 pour la conception
de circuits électroniques), ou pour fonctionner exclusivement à l'intérieur d'un logiciel
donné (e.g. ceux utilisés dans Maple ou Mathematica).
La frontière entre langages généralistes et spécialisés est toutefois floue et poreuse :
historiquement, de nombreux langages ont été initialement développés pour satisfaire
un besoin spécifique avant d'être utilisés plus largement. C'est le cas de C (conçu
pour créer Unix), de Python, et de Java comme on le verra plus loin. Inversement des
langages comme C++, C# ou Scala ont, d'emblée, été conçus pour être des langages
généralistes.
De même, la frontière entre langages impératifs / fonctionnels / orientés objets n'est
3 - Le mode Jazelle DBX permet, au moins théoriquement, l'exécution directe du bytecode sur les processeurs
ARM sans l'intermédiaire d'une machine virtuelle. En pratique, tout dépend de l'implantation du mode Jazelle
DBX sachant qu'il existe des dizaines de fournisseurs de processeurs ARM. Au pire le code reste entièrement
exécuté dans une machine virtuelle ; au mieux, seule une partie du bytecode est véritablement exécutée
directement sur le processeur, les instructions les plus complexes et/ou les moins courantes étant toujours
interprétées dans une machine virtuelle. Une variante à Jazelle DBX est par ailleurs incluse dans les
processeurs ARM depuis 2005 : ThumbEE, conçu comme le mode d'exécution privilégié pour l'exécution des
programmes écrits en Java, C#, Phython, Perl, etc. Dans ce mode, le processeur exécute un jeu d'instructions
réduit optimisé pour être très proche de tous ces langages à la fois. L'usage de ThumbEE n'est cependant plus
recommandé par ARM sur les dernières générations de ses processeurs, même si il reste disponible pour des
raisons de compatibilité avec les anciens processeurs.
4 - VHSIC (Very High Speed Integrated Circuit) Hardware Description Language.
17
pas figée : la plupart des langages évoluent au fil des années, et dans certains cas
changent de catégorie, en ajoutant une couche objet par exemple (e.g. Pyhthon, PHP
et bien d'autres) ou des aspects fonctionnels (Java 8). D'autres langages sont conçus
pour être précisément à la frontière de différents styles comme Scala ou F# qui
tentent de concilier au mieux les styles impératifs, objets et fonctionnels.
Par ailleurs il existe de nombreux « langages informatiques » qui ne sont pas des
langages de programmation : par exemple XML (Extensible Markup Language) est un
langage conçu pour représenter/archiver/manipuler des données structurées, il ne
permet pas l'écriture de « programmes ».
C. Java aujourd'hui
Langage de programmation parmi les plus utilisés aujourd'hui :
plus de 10 millions de développeurs Java
nombreux outils de développement
plusieurs milliards d'objets avec une « machine virtuelle Java », dont :
18
Introduction
5 - Du moins pas au sens de C++ qui permet l'héritage multiple des attributs et des méthodes : en Java seuls
les méthodes peuvent dans une certaines mesure faire l'objet d'un héritage multiple via le mécanisme des
méthodes « par défaut ».
19
de la technologie AJAX (asynchronous JavaScript and XML) utilisée pour la création de
pages web dynamiques dans lesquelles il y a des échanges fréquents et automatiques
entre le navigateur et le serveur (par exemple pour la mise à jour d'une carte).
JavaScript et Java sont en fait complémentaires : certains codes très spécifiques
s'écrivent plus aisément avec JavaScript (pour la gestion de formulaires dans des
pages web par exemple) alors que Java est utilisé beaucoup plus largement pour
exécuter des programmes complexes à l'intérieur de pages web ou de serveurs, et
pour développer des programmes autonomes de grande taille comme Eclipse.
Cette complémentarité est telle qu'il existe plusieurs briques technologiques pour
faciliter l'utilisation conjointe des deux langages dont le moteur JavaScript
« Nahshorn » (fournit avec Java depuis la version 8) et qui permet l'exécution de code
Javascript au sein de la machine virtuelle Java (la JVM) et également l'invocation de
code Java depuis Javascript (et réciproquement).
Principaux défauts
Vitesse d'exécution des codes inférieure à C/C++ (dépend des codes)
Réputation de sécurité ternie à plusieurs reprises par des bugs dans les
implantations de référence
Syntaxe relativement verbeuse
Système de type non entièrement unifié (types élémentaires / tableaux /
classes)
Poids du passé encombrement cognitif (beaucoup de classes a « superflues »
maintenues pour garantir la compatibilité ascendante des codes Java)
Langage difficile pour des programmeurs occasionnels
Inversement, langage possiblement trop banal/mature pour des programmeurs
expérimentés
Complément
Une étude de 2012 sur un ensemble de codes de référence met en évidence
une vitesse d'exécution des codes Java (J2SE 1.7) inférieure de 44% comparé
au langage C++. Il s'agit d'une différence importante dans l'absolu mais, en
pratique, rares sont les applications pour lesquelles un tel gain de vitesse
justifie à lui seul le choix d'un langage de programmation : les critères
essentiels sont bien plutôt la rapidité et le coût de développement des
programmes, la fiabilité, la portabilité, ...
Concernant la verbosité, c'est un point à relativiser : la verbosité de java
découle en grande partie d'un choix de conception délibéré lié d'une part au
20
Introduction
6 - En Java, « compatibilité ascendante » veut dire qu'un programme compilé avec une version antérieure du
langage continuera à fonctionner de la même manière sur une machine virtuelle plus récente, sans nécessiter
de re-compilation ou de modification du code source (à de rares exceptions près). Autrement dit, un code
développé pour Java 1.6 pourra fonctionner sur un ordinateur doté d'un environnement d'exécution (JRE)
plus récent tel que Java 1.8. L'inverse est faux : un code Java récent ne fonctionnera pas forcément sur un
environnement d'exécution plus ancien.
Attention : la « compatibilité ascendante » concerne les programmes écrits en langage Java ; si on considère
les outils (compilateur et machine virtuelle Java) on doit alors parler de « compatibilité descendante » ou
« rétro-compatibilité » (une JVM 1.6 pourra exécuter tout code écrit en Java 1.6 ou avec des versions plus
anciennes, mais pas forcément des codes plus récents).
21
Complément : OpenJDK, licences, ...
OpenJDK est une version de Java dont la totalité des composants est
strictement dans le domaine public (sources de toutes les classes, de la
machine virtuelle, du compilateur,...)
OpenJDK est distribué sous licence GNU
OpenJDK est une initiative soutenue par une grande partie de l'industrie
informatique (Oracle, IBM, Apple, SAP, ...)
La version standard distribuée gratuitement par Oracle (JRE, Java SE, ...)
utilise les mêmes codes sources qu'OpenJDK mais y ajoute des composants qui
ne sont pas dans le domaine public ; le résultat est distribué sous une licence
spécifique (Binary Code License)
22
Introduction
Attention
Ce cours correspond à l'édition standard de Java (Java SE) et ne couvre pas
les spécificités des autres éditions, ni les langages connexes à Java.
23
II - Syntaxe de base
II
Premiers exemples 25
Variables, types, portée, commentaires, … 26
Opérateurs 31
Blocs, instructions de contrôle (tests, boucles, …) 36
Entrées-sorties 42
Exemple de programme, compilation, exécution 45
A. Premiers exemples
Remarque : mots-clés
Dans l'exemple ci-dessus, int, for, class, public, static et void sont des mot-
clés. Par mot-clé il faut comprendre un mot réservé par les concepteurs du langage,
et qu'il est donc impossible d'utiliser dans un programme pour nommer une variable,
une fonction, ...
Java comporte une cinquantaine de tels mots-clés qui seront présentés au fil du
cours.
25
B. Variables, types, portée, commentaires, …
1. Variables et types
Remarque
Contrairement à certains langages moins fortement typés (Python, Maple, ...), Java
ne cherche quasiment jamais à « inférer » (deviner) le type des variables : en Java, il
faut déclarer le type de chaque nouvelle variable. Cela alourdit l'écriture du code mais
permet de gagner en fiabilité (le compilateur interdit les manipulations risquées, le
programmeur est obligé d'expliciter ses choix).
Par ailleurs, le type d'une variable en Java est fixé une fois pour toute (i.e. il ne peut
changer au fur et à mesure des affectations...)
2. Types « primitifs »
boolean
Remarque
Le typage est particulièrement strict en Java (comparé à C ou C++ par exemple),
ainsi :
les conversions automatiques sont peu nombreuses (et seulement vers des
types « plus larges », par exemple du type int vers le type long)
les conversions manuelles sont restreintes (il est, par exemple, interdit de
convertir un booléen en entier)
26
Syntaxe de base
3. Le type booléen
Valeurs possibles : true ou false
Véritable type
Type retourné par les opérateurs de comparaison
Type attendu dans tous les tests
Ne peut pas être converti en entier
Remarque
Contrairement à d'autres langages, le type booléen est un type à part entière en
Java. En particulier, il n'y a pas de correspondance entre faux et 0 comme c'était le
cas historiquement en C/C++ (non-ISO).
4. Le type caractère
16-bit 65536 valeurs : quasiment tous les caractères de toutes les écritures (mais
affichables uniquement si le système possède les polices de caractères adéquates !)
Littéraux entre simples quotes : 'a' 'Z' ...
Caractères spéciaux : '\n' '\t' '\b' '\\' '"' ...
Possibilité d'utiliser la valeur Unicode : '\u03c0'7
Convertibles automatiquement en int ou long (et manuellement en byte ou short)
Inversement, (char)val est le caractère dont le code Unicode est l'entier val
Possibilité de tester la nature du caractère :
Character.isLetter(c), Character.isDigit(c), ...
où c est une variable de type char
NOTA-BENE : nombreuses fonctions utilitaires dans la classe Character, voir plus loin
(cf. La classe Character p 163) et dans la documentation en-ligne de Java
Attention
Ne pas confondre 'a' et "a" ('a' est un char, i.e. UN SEUL caractère, "a"est
une chaîne de caractères de longueur 1)
\ suivi directement d'un nombre indique un char donné par son code en octal
(base 8)
ex. : `\43' est le char de code 4x8+3=35 (et pas le caractère de code 43)
27
5. Les types entiers
Littéraux de type entier :
en base dix : 139
en octal : 0213
en hexadécimal : 0x8b
en binaire : 0b100101
Valeurs min/max ::
byte = [-128; +127]
short = [-32768 ; +32767]
int = [-2.147.483.648 ; +2.147.483.647]
long = [-9.223.372.036.854.775.808 ; +9.223.372.036.854.775.807]
Conversion automatique seulement vers les types entiers plus grands (int long,
etc...) et vers les types flottants
Remarque
Contrairement à d'autres langages (C, C++, ...), il n'existe pas de variantes « non-
signées » de ces types en Java (et donc pas de mot-clé unsigned).
28
Syntaxe de base
7. Constantes
Variable dont la valeur ne peut plus être changée une fois fixée
Se déclare avec le mot-clé final :
final double PI = 3.14159;
PI = 3.14; // ERREUR...
29
8. Déclaration et portée des variables
Déclaration préalable obligatoire
Identificateurs :
- caractères Unicode
- commencent par une lettre, _ ou $
- ensuite : lettre, chiffre, _ ou $
Exemples :
int i;
double x, y, z;
char c = 'A', d;
boolean flag = true;
9. Conventions de nommage
1. Identificateurs toujours en minuscules, sauf :
- majuscule au début des « sous-mots » intérieurs :
unNomDeVariableOuDeFonctionOrdinaire
- début des noms en majuscule pour classes et interfaces (et elles seules) :
UnNomDeClasse
2. Pour les constantes : tout en majuscules et séparation des mots par _
UNE_CONSTANTE
3. Pour les classes et interfaces : éviter tous les noms déjà utilisés dans le JDK
(ex. String, System, ...)
4. Pas d'emploi du caractère $ (ni de caractères non ASCII8)
Remarque
Ces conventions de nommage édictées par les auteurs du langage ne sont pas
strictement obligatoires pour faire fonctionner un programme ; elles sont néanmoins
fortement recommandées dans la mesure où elles facilitent grandement la
lisibilité du code et sa maintenance). Elle sont de fait très largement respectées.
8 - ASCII = American Standard Code for Information Interchange. La norme ASCII date de 1963, c'est
l'ancêtre de tous les systèmes d'encodage de caractères en informatique ; les caractères y sont codés sur un
octet ce qui limite leur nombre à 256. ASCII a été conçu pour la langue anglaise dont il couvre tous les
caractères et symboles usuels. Pour des raisons de compatibilité ascendante, les normes plus récentes qui
couvrent davantage de langues sont généralement calquées sur l'ASCII pour ce qui concerne les caractères
couverts par cette norme (lettres latines sans accents, chiffres, ponctuation courante...) . En particulier, sous
Unicode, le standard ASCII est intégré sous le label « Basic Latin » (ou C0 Controls and Basic Latin).
30
Syntaxe de base
10. Commentaires
Plusieurs sortes de commentaires en Java :
Remarque : javadoc
C. Opérateurs
1. Principaux opérateurs
affectation : =
arithmétique : + - * / %
comparaison : < <= > >= == !=
booléen : && || ! ^ & |
opération bit-à-bit (sur les entiers) : & | ^ ~ << >> >>>
opération et affectation simultanées : += -= *= /= %= &= |= ^=
<<= >>= >>>=
pré/post-incrémentation : ++
pré/post-décrémentation : --
opérateur ternaire : ?:
création tableau ou objet (allocation mémoire) : new
31
2. Opérateurs arithmétiques
Attention
L'arithmétique entière est « circulaire » : elle produit des résultats
mathématiquement faux en cas de dépassement, mais pas d'erreur au sens
informatique, sauf lors d'une division par zéro.
L'arithmétique décimale (en virgule flottante) produit des erreurs d'arrondis
mais n'est pas circulaire : elle produit des valeurs de type infini en cas de
dépassement.
En cas de division par zéro, l'arithmétique entière produit une erreur
informatique (ArithmeticException) tandis que l'arithmétique décimale
retourne la valeur spéciale NaN (NotANumber).
Les divisions entre entiers produisent le quotient 9 (pas de passage automatique
à l'arithmétique décimale).
Les constantes et fonctions mathématiques usuelles sont dans la classe Math (cf. La
classe Math p 160) :
Math.E
Math.PI
Math.pow(x,y)
Math.sin(x)
Math.log(x)
…
9 - En java, étant donnés deux entiers et , vaut avec qui vaut , ou selon que est <, = ou > à .
Exemples : 18/10 vaut 1 ; -18/10 vaut -1 ; -18/-10 vaut 1.
32
Syntaxe de base
3. Opérateurs de comparaison
Opérateur Fonction
== égalité
!= inégalité
< inférieur strict
<= inférieur ou égal
> supérieur strict
>= supérieur ou égal
Attention
Ne surtout pas confondre == (test d'égalité) et = (affectation)
4. Opérateurs booléens
! négation ! expr1
Remarque
Différence entre les versions optimisées et non-optimisées :
avec le et optimisé : &&, le deuxième opérande n'est pas évalué si le premier
est faux
avec le ou optimisé : ||, le deuxième opérande n'est pas évalué si le premier
est vrai
33
5. Opérateurs bit-à-bit
| ou op1 | op2
~ négation ~ op1
6. Opérateurs d'affectation
int i, j, k ;
final int TMAX = 100 ;
34
Syntaxe de base
pré-incrémentation ++i
-- post-décrémentation i--
pré-décrémentation --i
n = i++; équivaut à n = i;
i = i + 1;
n = ++i; équivaut à i = i + 1;
n = i;
8. Autres opérateurs
Ternaire conditionnel : bool ? expr1 : expr2
int v = (x < y) ? x : y
// v vaut le minimum entre x et y
double x = 1.7;
int i = (int) x; // i vaut 1
double y = -1.7;
int j = (int) y; // i vaut -1
35
Opérateurs Java (par ordre de priorité décroissante)
&
^
|
&&
||
? :
1. Instructions et blocs
Chaque instruction se termine par un ';'
int x, y, z;
x = 10;
y = f(x);
z = (x+y)/2;
{ // début de bloc
int x = a;
a = b;
b = x;
} // fin de bloc
Remarque
La portée d'une variable va de sa déclaration jusqu'à la fin du bloc où elle est
déclarée
36
Syntaxe de base
2. Instructions de contrôle
Les instructions de contrôle permettent de modifier l'ordre normal (séquentiel)
d'exécution des instructions :
3. Exécution conditionnelle
Forme minimale (pas de clause else, une seule instruction) :
if (boolExpr) instruction;
Forme standard :
if (boolExpr) {
instruction(s); // exécutée(s) si VRAI
} else {
instruction(s); // exécutée(s) si FAUX
}
Possibilité d'imbrication :
if (boolExpr) {
instruction(s); // exécutée(s) si VRAI
} else if (boolExpr2) {
instruction(s);
} else { // . . .
}
}
Exemple
if ( a!=10 ) x = 4;
else { //bloc car plusieurs instructions
x = 5;
y = t+2;
}
Remarque
Dans tous les cas : le test est placé entre parenthèses.
La partie « sinon » (else) est facultative.
Les accolades sont facultatives si il n'y a qu'une seule instruction.
Contrairement à d'autres langages, il n'y a pas de mot-clé then en Java.
37
4. Cas multiples
switch (e) {
case cst1:
// instruction(s) si e==cst1
break;
case cst2:
// instruction(s) si e==cst2
case cst3:
// instruction(s) si e==cst3 ou e==cst2
break;
default:
// instruction(s) si aucun des cas prévus
break;
}
Avec :
e : de type entier ou char ou String ou bien type énuméré (enum)
cst1, cst2, ... : littéral ou constante (final)
Exemple
final int ERREUR=-1;
int x, y;
//...
switch(x) {
case 0 :
y=x;
break;
case 1 :
x=y;
break;
case ERREUR :
System.exit(1);
break;
default :
y=0;
}
Exemple
enum Temperature { FROID, TIEDE, CHAUD } ;
Temperature t;
// ..
switch(t) {
case FROID : // ...
case TIEDE : // ...
case CHAUD : // ...
}
38
Syntaxe de base
Attention
Le paramètre de l'instruction switch ne peut pas être de n'importe quel type
(les nombres flottants en particulier sont interdits, de même que les instances
de classes autres que String).
Sauf cas particuliers, une clause break est nécessaire à la fin de chaque
branche du switch. A défaut, chacun des codes correspondant aux branches
suivantes sera exécuté sans même vérifier la validité des tests associés, ce qui
ne correspond que très rarement au fonctionnement souhaité.
5. Boucles de répétitions
Deux sortes de boucles « while » en Java :
while (boolExpr) { do {
// corps exécuté tant que // corps exécuté
// boolExpr est vrai : // au moins 1 fois :
instruction(s); instruction(s);
} } while (boolExpr);
Exemples :
int y = 10 ;
while (y<8) {
y *= 2 ;
}
// que vaut y ?
int z = 10 ;
do {
z *= 2 ;
} while (z<8);
// que vaut z ?
39
6. Boucles d'itération
Avec :
init : déclarations et/ou affectations, séparées par des virgules
(typiquement : initialisation des variables utilisées dans la boucle)
incr : expressions séparées par des virgules
(typiquement : incrémentation des variables utilisées dans la boucle)
Equivaut à :
init;
while (boolExpr) {
instructions;
incr;
}
Exemples :
int somme=0;
for (int i=1 ; i<=n ; i++) {
somme += i;
}
for ( ; ; ) ;
Remarque
Possibilité d'avoir plusieurs instructions à la suite dans la zone « initialisation »
et/ou « incrémentation » comme dans le 2° exemple ci-dessus (remarquer
l'usage de la virgule pour séparer les instructions en question).
Inversement, chacun des composants du for peut être vide (voir le 3e
exemple : boucle infinie qui ne fait rien !)
40
Syntaxe de base
Exemple
int[] prems = { 2, 3, 5, 7, 11};
// prems : tableau d'entiers
int somme = 0;
for (int i : prems) {
somme += i*i;
}
Attention
Contrairement à la version « classique » du for, le 1° paramètre entre
parenthèse n'est pas forcément de type entier (son type doit être celui des
éléments du tableau).
Par ailleurs, les valeurs successives affectées à ce paramètre lors du
déroulement de la boucle correspondent aux différentes valeurs présentes dans
le tableau (et pas aux indices comme dans la version « classique » du for).
DONC ATTENTION : risque d'erreur lorsque le type des éléments est entier si on
confond les deux versions de l'instruction « for ».
41
Exemple
nomDuLabel:
while ( f(x) > 0 ) {
for ( x : tab) {
// ....
if ( tab[x] > 100 ) {
break;
// sort de la boucle la plus interne (for)
}
if ( tab[x] < 0 ) {
break nomDuLabel;
// sort de la boucle englobante (while)
}
if ( tab[x] == 0 ) {
continue nomDuLabel;
// saute au prochain test de la boucle
// englobante (while)
}
// ....
}
}
E. Entrées-sorties
Exemple d'écriture sur le flux de sortie standard (écrit sur
la console par défaut) :
double z = 0.43;
System.out.print("z=");
System.out.print(z);
System.out.println(" et 2z=" + (2*z));
// Lecture de 10 caractères
byte buf[] = new byte[10];
int nbLus = System.in.read(buf);
Conseil
Utiliser la classe Scanner pour lire autre chose que des caractères ou tableaux de
caractères (voir ci-après).
42
Syntaxe de base
//…
ATTENTION : Java utilise, par défaut, le format « local » des nombres (par exemple
en français : 2,5 et pas 2.5) ; possibilité de choisir une « localisation » avec la
méthode useLocale() (cf. Localisation et internationalisation p 172)
int i=3;
int j=30;
int k=303;
System.out.printf("|%3d|%3d|%3d|", i, j, k);
// imprime : | 3| 30|303|
double x=2.5;
double y=-3.755;
System.out.printf("x:%+.2f\ny:%+.2f", x, y);
// imprime quoi ?
43
Complément : printf(), format() et la classe Formatter
printf() est une méthode d'affichage puissante mais plus complexe d'emploi que
print() et println(). Son principal intérêt est de permettre un contrôle fin du
formatage des données, en particulier numériques (mais pas seulement)10.
Le principe général est de passer en 1° paramètre une chaîne de caractères avec du
texte à afficher, et comportant un nombre quelconque de « séquences » introduites
par le caractère %.
A chaque séquence doit correspondre une variable passée en paramètre à la suite de
la chaîne de caractères comme dans les exemples ci-dessus.
Les séquences doivent suivre une syntaxe spécifique détaillée dans la documentation
en-ligne de la classe Formatter.
Pour comprendre les exemples ci-dessus il suffit de savoir que :
chaque séquence commence par un caractère % et se termine par une lettre qui
spécifie la nature de la variable qui sera substituée à cette séquence, à savoir :
- s pour une chaîne de caractères ;
- c pour un caractère ;
- d pour un entier ;
- f pour un nombre flottant ;
- e pour un nombre flottant à afficher en notation « scientifique » ;
- ...
le contrôle de l'affichage s'effectue en ajoutant, si besoin, des directives entre
le caractère % et la lettre qui termine la séquence, ainsi :
- %f indique qu'on souhaite afficher à cet endroit un nombre flottant ;
- %.2f indique qu'on souhaite exactement 2 chiffres après la virgule ;
- %6.2f indique en outre que l'affichage devra comporter au minimum 6
caractères, y compris la virgule et le signe éventuel (quitte à ajouter des
blancs si besoin) ;
- %+6.2f indique en outre que le signe (+ ou -) devra impérativement
s'afficher (par défaut seuls les signes - s'affichent);
- %6d indique qu'on souhaite afficher à cet endroit un nombre entier occupant
6 caractères au minimum ;
- %+6d indique en outre que le signe devra impérativement s'afficher.
[ NOTA-BENE : beaucoup d'autres directives sont disponibles pour les nombres
flottants, et pour chacun des autres types. ]
%% permet d'inclure un caractère % sans qu'il soit interprété comme le début
d'une séquence
Au delà, se souvenir que printf() est une méthode à la fois puissante et flexible ; à
privilégier dès qu'un simple print() ou println() ne suffit pas, et ce d'autant plus
qu'elle permet de formater des données créées par l'utilisateur dès lors que ces
données se conforment à l'interface « Formattable ».
Outre printf(), il peut être utile de connaître la méthode statique String.format()
qui s'appuie sur la même syntaxe que printf() mais se contente de retourner la
chaîne de caractères produite au lieu de l'afficher.
NOTA-BENE : comme pour tout aspect non-trivial de Java, il ne faut pas chercher à
tout découvrir – et encore moins tout mémoriser – par avance. Concernant, par
exemple, printf(), il faut bien comprendre et mémoriser le mode général de
fonctionnement, puis, lorsque nécessaire, approfondir ses connaissances en
parcourant la documentation de référence en-ligne (l'ensemble des possibilités de
10 - Accessoirement, elle présente l'avantage de fonctionner de manière similaire à la fonction de même nom
du langage C, et donc d'être facile d'utilisation pour tous les programmeurs en C.
44
Syntaxe de base
formatage permises par la classe Formatter occupe 5 pages) et/ou en cherchant des
exemples dans une base telle que http://www.java2s.com.
Compilation et exécution
En général, un fichier MaClasse.java doit contenir la classe MaClasse, et elle
seule ; pour plus de détails voir organisation en fichiers (cf. Organisation en
fichiers, compilation et exécution p 124)
La compilation de MaClasse.java MaClasse.class
Le fichier MaClasse.class peut être exécuté si et seulement si la classe
MaClasse comporte une fonction « main ».
45
Références,
III -
tableaux, chaînes de
caractères, types III
énumérés simples
Références 47
Tableaux 48
Chaînes de caractères 53
Types énumérés simples 55
Références constantes 56
A. Références
Les références servent à manipuler toutes les variables dont le type n'est pas
primitif (i.e. tableaux, objets, types énumérés)
NOTA-BENE :
plusieurs références différentes peuvent référencer un même objet ou tableau
les références sont typées
le mot-clé null désigne une référence « vers rien » (compatible avec tous
types de référence)
une affectation entre références modifie la référence en partie gauche de
l'affectation, et non la chose référencée
Exemple :
47
B. Tableaux
Principes
Manipulés par des références
Allocation dynamique par new ( taille définissable à l'exécution)
Taille fixée une fois pour toute après allocation
Taille accessible à tout moment par le « champ » length
Indices variant entre 0 et length-1 (et vérification systématique des bornes à
l'utilisation)
Création :
- par new après la déclaration (ou lors de la déclaration) :
Initialisation :
// A la déclaration :
int tab[] = {1, 2, 3};
// Lors de la création :
tab = new int[] {1, 2, 3};
NOTA-BENE : par défaut, les cases du tableau sont initialisées à 0, '\u0000', false ou
null (selon le type de base)
48
Références, tableaux, chaînes de caractères, types énumérés simples
Attention
Il ne faut jamais spécifier de dimension (entier entre les crochets) lors :
d'une simple déclaration : on doit écrire int tab[]; et surtout pas int
tab[5];
d'une création comportant la liste des valeurs initiales : on doit écrire tab =
new tab[]{1,2,3,4,5}; et surtout pas tab = new tab[5]{1,2,3,4,5};
Manipulations usuelles
Accès à la taille :
tab[0] = 1;
tab[4] = -1;
// RAPPEL : les indices varient entre 0 et length-1
Affichage :
for(val : tab) {
System.out.println(val) ;
}
// affiche quoi ?
// ATTENTION :
System.out.println(tab) ;
// affiche tab en tant que référence
// (adresse mémoire où est stockée le contenu)
Attention
Lancement de l'exception (cf. Principe des exceptions p 91)
ArrayIndexOutOfBoundsException en cas de tentative d'accès hors des bornes d'un
tableau (indice négatif ou >= t.length)
Définition
On appelle « ramasse-miettes » (en anglais : garbage collector ou encore GC) le
mécanisme intégré à l'interpréteur du langage (la machine virtuelle dans le cas de
49
Java) qui récupère de manière automatique les zones mémoires allouées puis rendues
inaccessibles au fil de l'exécution du programme.
Tous les langages n'incluent pas de « ramasse-miette », l'alternative étant de
confier au programmeur la tâche de libérer explicitement les zones mémoire dont il
n'a plus l'usage (cas des langages C et C++ par exemple).
En pratique, la présence d'un « ramasse-miette » simplifie la programmation et
rend les programmes plus fiables, mais cela se paye par :
une dégradation (et une moindre prévisibilité) des performances à
l'exécution ;
l'impossibilité de procéder à certaines optimisations très spécifiques liées à
l'organisation des données en mémoire.
Dans tous les cas, il est essentiel de recycler les zones mémoire sans quoi la taille des
programmes grossit inutilement au cours de l'exécution (on parle alors de « fuite de
mémoire » ou memory leak en anglais).
Exemple
public class ExempleTableau {
public static void main(String[] args) {
// DECLARATION :
double[] tab;
// CREATION ET DIMENSIONNEMENT :
int lg = 1 + (int)( 9*Math.random() );
tab = new double[lg];
// AFFICHAGE :
for (int i=0 ; i<tab.length ; i++) {
System.out.print(tab[i] + " ");
}
System.out.println();
}
}
Copie de tableaux
Méthode « manuelle » : création d'un nouveau tableau, puis copie case par
case
Copie (sans allocation) par appel de System.arraycopy() :
50
Références, tableaux, chaînes de caractères, types énumérés simples
Tableaux d'objets
Des tableaux contenant des (références à des) objets d'une classe donnée peuvent
être déclarés et créés pour toute classe (prédéfinie ou bien écrite par le
programmeur).
Par exemple, un tableau de chaînes de caractères modifiables (classe StringBuffer :
voir ci-après) se déclare et se dimensionne ainsi :
StringBuffer[] tabChaines;
tabChaines = new StringBuffer[2];
51
Attention
Le dimensionnement d'un tableau d'objets crée uniquement des « cases » pour
stocker des références aux objets, mais pas les objets eux-mêmes.
Ces références valent initialement null, il faut donc les faire ensuite pointer vers les
objets voulus par des affectations, comme dans l'exemple suivant :
StringBuffer[] tabChaines;
tabChaines = new StringBuffer[2];
Tableaux multi-dimensionnels
Il n'existe pas de tableaux à plusieurs dimensions en Java, mais, de manière analogue
aux tableaux d'objets, on peut créer des « tableaux de tableaux » :
// Déclaration et création :
float matrix[][] = new float[2][3];
// matrix référence un tableau de taille 2
// dont chaque case référence un tableau
// d'entiers de taille 3
// Utilisation :
for (int i=0 ; i<matrix.length ; i++) {
for (int j=0 ; j<matrix[i].length ; j++) {
matrix[i][j] = i*j;
}
}
float triangle[][];
int dim;
// ...
triangle = new float[dim][];
for (int i=1 ; i<dim ; i++) {
triangle[i] = new float[i];
}
52
Références, tableaux, chaînes de caractères, types énumérés simples
C. Chaînes de caractères
Attention
Deux classes complémentaires en Java :
1. chaînes immuables (non modifiables) : String
2. chaînes modifiables : StringBuffer
La classe String
Chaînes immuables
Chaînes littérales : "une chaîne"
Concaténation par l'opérateur +
Exemple :
Attention
En java, pour accéder à la longueur, il faut écrire :
s.length() si s est de type String
et t.length si t est un tableau !
53
Complément
Le classe String comporte de nombreuses fonctions utilitaires :
test d'égalité partielle :
boolean regionMatches(int deb, String s2, int deb2, int fin2)
test de début/fin :
boolean startsWith(String) ; boolean endsWith(String),...
extraction de sous-chaîne :
String substring(int deb, int fin)
void getChars(int deb, int fin, char[] dest, int destDeb)
découpage :
String[] split(String delim)
suppression des blancs de début et fin :
String trim()
changement de casse :
String toLowerCase() ; String toUpperCase() ; ...
substitution de caractères :
String replace(char ancien, char nouveau)
conversion en chaîne des types de base (méthodes statiques) :
String.valueOf(int) ; String.valueOf(double) ; ...
...
La classe StringBuffer
Chaînes modifiables
Exemple :
// Utilisation :
int l = buf.length();
char c = buf.charAt(0);
buf.setCharAt(0, 'L');
buf.insert(3, "gues ");
buf.append("née");
buf.deleteCharAt(6);
String s = buf.toString();
String s2 = buf.substring(7, 11);
Attention
Entre variables de type StringBuffer :
pas de compareTo() ni de compareToIgnoreCase()
equals() ne teste pas l'égalité des caractères de la chaîne
pas d'opérateur + pour concaténer
par contre (buf + s) et (s + buf) sont OK si s est une String, mais le
résultat est alors de type String
54
Références, tableaux, chaînes de caractères, types énumérés simples
Conseil
Les classes String et StringBuffer comportent bien plus de méthodes que
présentées ci-dessus ; penser à consulter la documentation en-ligne pour approfondir
le sujet.
enum CouleurFeu {
VERT, ORANGE, ROUGE
}
// . . .
CouleurFeu col = CouleurFeu.ROUGE;
// . . .
switch(col) {
case CouleurFeu.VERT : passer() ; break ;
case CouleurFeu.ORANGE : freiner() ; break ;
case CouleurFeu.ROUGE : stopper() ; break ;
}
Remarque
Pour plus de détails, voir la section consacrée aux types énumérés (cf. Types
énumérés p 89).
55
E. Références constantes
Une référence constante est une référence associée de façon définitive à un tableau
ou à un objet donné
Mot-clé : final
Exemple :
56
IV - Fonctions
IV
Introduction 57
Type de retour et instruction return 58
Appel (ou « invocation » ) de fonction 59
Fonction et portée 59
Programme principal 60
Passage des paramètres 60
Récursivité 62
Surcharge (ou « overloading ») 62
Fonctions à nombre variable d'arguments 62
Fonctions « natives » 63
A. Introduction
Eléments essentiels de structuration en programmation « impérative »
57
Premier exemple de fonction
Attention
En Java, chaque fonction est obligatoirement définie dans une classe (ex. : la
classe prédéfinie Math regroupe des fonctions mathématiques).
Contrairement à d'autres langages, les fonctions en Java ne s'imbriquent pas
(i.e. toutes les fonctions d'une classe sont définies les unes après les autres).
class MaClasse {
/* indexDe() retourne l’index de la valeur v
dans t (ou -1 si pas trouvée) */
public static int indexDe(float v, float[] t) {
int len = t.length;
58
Fonctions
Rappel
Attention à bien respecter les conventions de nommage vues précédemment :
maFonction() // 1° lettre en minuscule pour les fonctions
MaClasse // 1° lettre en majuscule pour les classes
y = Math.sin(x);
k = MaClasse.carre(i);
class MaClasse {
public static int carre(int i) {
return i*i;
}
public static void main(String[] args) {
int x = MaClasse.carre(5);
System.out.println(x); // affiche 25
int y = carre(6);
System.out.println(y); // affiche 36
}
}
D. Fonction et portée
Les variables déclarées dans une fonction sont locales à cette fonction
Idem pour les paramètres
Exemple :
class Portee {
public static int calcul(int val) {
int tmp = 3*val;
return tmp;
}
public static void main(String[] args) {
int tmp = 1;
System.out.println( calcul(9) );
// Que vaut la variable tmp ici ?
// et val ?
}
}
59
E. Programme principal
En Java, l'exécution de programme consiste en la recherche et l'appel d'une fonction
(publique) particulière
1. nommée main
2. prenant impérativement un (et un seul) paramètre de type String[]
3. ne retournant rien
Exemple, avec utilisation du paramètre :
class Echo {
public static void main(String [] args) {
for (String s : args) {
System.out.print(s + " ");
}
}
}
// Exemple d'exécution (en mode texte)
// L'utilisateur demande l'exécution du programme echo
// avec 3 arguments :
// java Echo un deux trois
// un deux trois
60
Fonctions
NOTA-BENE : la référence est passée par valeur (la référence passée en paramètre
est une copie de l'originale), mais l'objet référencé peut néanmoins être modifié par la
fonction (la référence copiée tout comme la référence originale pointent vers le même
objet).
Remarque
En Java (contrairement à ce qui se passe dans d'autres langages) l'ordre d'écriture
des fonctions n'a pas d'importance : une fonction peut être invoquée depuis une ligne
qui précède sa définition dans le fichier.
Toutefois, il est vivement recommandé d'écrire les fonctions dans un ordre qui facilite
la compréhension du programme.
Exercice
class Passage {
public static int fonc(int x) {
x++;
return x;
}
public static void main(String[] args) {
int v = 1;
int y = fonc(v);
// Que valent y et v ici ?
int[] tab={1, 2, 3};
f2(tab);
// Etat de tab maintenant ?
}
public static void f2(int[] t) {
t = new int[] {2, 2};
}
}
61
G. Récursivité
Une fonction peut s'appeler elle-même à condition de bien gérer l'arrêt de la récursion
(à défaut : récursion infinie bug à l'exécution)
Exercice : cette fonction est incorrecte. Pourquoi ?
class ExempleRecursif {
public static double puiss(double x, int n){
if ( n==1 ) {
return x;
}
else {
return x*puiss(x, n-1);
}
}
//...
}
class NomClasse {
public static int longueur(String s){
return s.length();
}
public static int longueur(int i){
String si = String.valueOf(i);
return si.length();
}
public static void main(String [] args) {
int k = 12345;
int lk = longueur(k); // lk vaut 5
String s = "oui";
int ls = longueur(s); // ls vaut 3
}
}
Remarque
Lors d'un appel de fonction, les arguments doivent être du type prévu ou d'un type
convertible automatiquement vers le type prévu.
62
Fonctions
}
//...
double[] t1=f(2, 2.57); // nb.length vaut 1 dans f
double[] t2=f(2, 7.5, 8, 8.5); // nb.length vaut 3
double[] t3=f(2); // nb.length vaut 0
NOTA-BENE :
Le paramètre avec « ellipse » est traité dans la fonction comme un tableau
Possibilité d'arguments de types hétérogènes via le type Object (cf. la classe «
Object » p 134)
J. Fonctions « natives »
Le mot-clé native dans une déclaration de méthode indique que cette méthode n'est
pas codée en Java, mais dans un autre langage, i.e. C ou C++.
Le code de la fonction sera recherché dans un fichier à part (une méthode native n'a
donc pas de corps).
63
Algorithmique,
V-
complexité, tris
V
Algorithme 65
Calculabilité 66
Heuristique 67
Complexité, efficacité 67
Algorithmique, classification des algorithmes, … 69
Problématique du tri 69
Tri par sélection 70
Tri par insertion 71
Tri bulle 72
Tri rapide 74
Complexité des algorithmes de tri 77
A. Algorithme
Définition : Algorithme
Spécification d'un schéma de calcul sous forme d'une suite finie d'opérations
élémentaires obéissant à un enchaînement déterminé.11
Dans cette définition, le mot « spécification » doit être compris dans un sens assez
large : un algorithme peut être spécifié en langage naturel, dans un pseudo-langage,
dans un langage informatique, sous forme de diagramme, ... l'important étant que la
spécification en soit vraiment une en termes d'exhaustivité et de non-ambiguïté.
Dans son ouvrage de référence « The Art of Computer Programming (TAOCP) »,
Donald Knuth privilégie pour sa part un pseudo-langage de bas niveau : l'assembleur
MMIX, langage conçu spécifiquement par l'auteur pour garantir que chaque
algorithme est à la fois :
1. explicité dans ces moindres détails ;
2. facile à transcrire en code informatique sans perte d'efficacité.
11 - Cette définition ne fait pas référence à la notion de programme, ni d'ordinateur. C'est bien sûr
volontaire. D'autres définitions sont possibles :
- « processus systématique de résolution, par le calcul, d'un problème permettant de présenter les étapes
vers le résultat à une autre personne physique (un autre humain) ou virtuelle (un calculateur) » (Wikipedia) ;
- « Ensemble de règles opératoires dont l'application permet de résoudre un problème énoncé au moyen d'un
nombre fini d'opérations. Un algorithme peut être traduit, grâce à un langage de programmation, en un
programme exécutable par un ordinateur » (Encyclopédie Larousse).
65
Remarque
Si la définition ci-dessus est relativement récente (20° siècle), le mot « algorithme »
est relativement ancien : il provient de la transcription en latin d'Al-Khawarizmi,
mathématicien perse (9° siècle ap. J.-C.).
Le concept d'algorithme remonte à plus loin encore : l'algorithme d'Euclide pour le
calcul du PGCD fut explicité par son auteur en ~ 300 av. J.-C. ; d'autres algorithmes
sont semble-t-il plus anciens encore.
B. Calculabilité
Définition : Calculable (synonyme : décidable)
Caractérisation des problèmes (ou fonctions) qui peuvent être résolus par un
algorithme14.
Cette notion est beaucoup plus récente que celle d'algorithme (années 1930s :
théorie de la calculabilité par Hilbert, Gödel, Church, Turing, ...)
Remarque
Dans la suite de ce cours, on s'intéressera uniquement aux problèmes « calculables ».
12 - En pratique, délimiter une frontière entre algorithme, logiciel et procédé en vue d'accorder ou refuser un
brevet peut être particulièrement délicat, d'où les litiges nombreux en ce domaine. Le problème est aggravé
par le nombre relativement faible de personnes maîtrisant à la fois les aspects techniques (informatique
théorique) et légaux (droit de la propriété intellectuelle).
13 - La protection liée au droit d'auteur est en théorie automatique, elle est liée à l'écriture d'une œuvre
originale. Il est toutefois prudent de se placer en situation de pouvoir prouver formellement sa qualité
d'auteur, et aussi de pouvoir dater sa création. Cela peut être réalisé en déposant une copie du programme
(source et/ou code binaire) chez un huissier, ou un organisme spécialisé tel que l'Agence pour la Protection
des Programmes (APP) en France.
14 - Plus formellement (au sens de la théorie de la calculabilité), un problème est décidable si, et seulement
si, il peut être décidé (calculé) par l'un ou l'autre des dispositifs suivants : fonctions récursives, machine de
Turing, lambda-calcul, machine à compteurs, automate cellulaire, machine de Blum-Shub-Smale, etc. Ces
différents dispositifs étant fondamentalement tous équivalents en ceci qu'ils permettent de résoudre
exactement la même classe de problèmes : les problèmes décidables.
66
Algorithmique, complexité, tris
C. Heuristique
Définition : Heuristique
Méthode de calcul qui, sans être un algorithme, fournit rapidement (en temps
polynomial) une solution – possiblement non-optimale voire approximative – à un
problème.
Exemples :
les méthodes permettant de faire (bien) jouer un ordinateur au jeu d'échecs ;
les méthodes permettant de reconnaître en temps réel des panneaux routiers à
partir d'un flux d'images provenant d'une caméra embarquée ;
…
D. Complexité, efficacité
Définition : Complexité
Etude des ressources nécessaires à l'exécution d'un algorithme en « temps »
et en « espace ».
NOTA-BENE : dans cette définition,
le temps correspond au nombre d'opérations élémentaires exécutées ;
et l'espace à la quantité de mémoire nécessaire pour stocker les
instructions du programme et les données (y compris les données
intermédiaires produites au cours du calcul).
67
complexité croissante : 1 (temps constant), log n, n (linéaire), n log n, n^2
(quadratique), n^3, 2^n (exponentiel) et n! (factorielle).
On utilisera la notation t(n) = O(...) 15 pour exprimer le fait que la complexité en
temps correspond à l'ordre de grandeur du nombre d'opérations élémentaires
exécutées lorsque n tend vers l'infini.
On pourra ainsi écrire que la complexité en temps de tel algorithme est en O(n^2).
Idem pour la complexité « en espace ».
15 - La notation « O majuscule » fait partie des notations Bachmann–Landau permettant de caractériser une
fonction par une autre, plus simple, dont le comportement asymptotique est identique. Les autres notations
pertinentes à cet égard sont : o, Ω, ω et Θ qui différent par la manière dont la seconde fonction s'approche de
la première lorsque n tend vers l'infini.
68
Algorithmique, complexité, tris
F. Problématique du tri
Avec la recherche dans une liste ou un tableau, trier le contenu d'une liste ou d'un
tableau est l'une des opérations les plus courantes dans les applications
informatiques.
Il peut s'agir de trier des valeurs numériques par ordre croissant ou décroissant, des
valeurs littérales par ordre lexicocraphique, ou des valeurs de type quelconque, à
condition d'avoir défini une relation d'ordre permettant de répondre à la question :
entre deux valeurs x et y quelconque, est ce que x est inférieur à y ou pas (la relation
d'ordre n'a pas forcément besoin d'être totale) ?
16 - Il s'agit d'une définition à la fois formelle et arbitraire. Elle se révèle en pratique tout à fait pertinente
dans la mesure où la quasi-totalité des algorithmes de complexité polynomiale sont dans les faits en O(n^2)
ou O(n^3), et pas en O(n^1000) !
69
On distingue :
les cas où il est possible de recopier et/ou dupliquer l'ensemble des données à
trier (si accessibles et pas trop volumineuses) ;
ceux où il est nécessaire d'opérer sur place (i.e. par permutations successives
de quelques valeurs) tris « en place ».
Pratiquement, sur des données composites (instances de classe par exemple), le tri
se fera suivant un critère défini par le programmeur à partir de tout ou partie des
attributs non-statiques de la classe (cf. Attribut statique p 85).
Aussi, lorsqu'il s'agit d'objets de grande taille, il est essentiel de procéder par
indirection pour éviter de déplacer l'ensemble des données (c'est ce qui se passe
automatiquement en Java via le mécanisme des références qui s'impose au
programmeur dès qu'il manipule autre chose que des types primitifs).
70
Algorithmique, complexité, tris
Conclusion
Retenir : tri en
71
Tri par insertion : principe
« placer chaque élément à sa place un par un »
Placer l'élément t [1] dans le sous-tableau contenant t [0] et t [1].
Placer t [2] dans { t [0], t [1], t [2] }
Recommencer à placer t [i] dans le sous-tableau de taille i+1
Conclusion
Retenir : tri en
I. Tri bulle
Trier le tableau d'entier
12 7 20 25 9 2
Pour obtenir
2 7 9 12 20 25
72
Algorithmique, complexité, tris
Conclusion
Retenir : tri en
73
J. Tri rapide
Trier le tableau d'entier
12 7 20 25 9 2
Pour obtenir
2 7 9 12 20 25
74
Algorithmique, complexité, tris
75
Tri rapide : complexité
Conclusion
Retenir : tri en
76
Algorithmique, complexité, tris
Sélection
Insertion
Bulle
Rapide
Sélection
Insertion
Bulle
Rapide
77
Programmation par
VI -
objets
VI
79
Un autre exemple : la classe PolygoneRegulier
Exemple
// Définition de la classe Cercle :
class Cercle {
// I : définition des attributs :
double rayon=0;
// II : définition des constructeurs :
// NOTA-BENE : constructeur par défaut si non défini
// III : définition des méthodes :
double calculerSurface() {
return Math.PI*rayon*rayon;
}
}
80
Programmation par objets
NOTA-BENE : la syntaxe pour désigner un attribut ou une méthode d'une classe varie
selon qu'on se trouve dans le bloc correspondant à la définition de la classe, ou pas :
accès direct aux attributs et méthodes (non-statiques) de l'instance courante
depuis l'intérieur de la classe
accès via l'opérateur . (« point ») à l'extérieur de la classe
2. Attributs
Attributs = données propres à l'objet (sauf cas particulier des attributs statiques,
voir plus loin)
Exemple :
System.out.print( x1.nom );
if ( x2.age > 62 ) { … }
3. Méthodes
Méthodes = opérations pouvant s'appliquer aux instances de la classe (sauf cas
particulier des méthodes statiques, voir plus loin)
4. Constructeur
Constructeur : permet de spécifier comment créer des instances de la classe
NOTA-BENE : la destruction des instances se fait automatiquement par le « ramasse
miettes » (garbage collector ou GC) qui élimine régulièrement tous les objets non-
référencés
81
Exemple de constructeur pour la classe Salarie :
IMPORTANT :
jamais de type de retour lors de sa déclaration (sinon Java le considère comme
une méthode et pas comme un constructeur)
nom = nom de la classe
Complément
Une classe peut avoir plusieurs constructeurs à condition que leurs signatures
soient différentes (il ne peut pas y avoir deux constructeurs pour une même
classe avec exactement la même liste de paramètres).
Un constructeur fréquemment utile prend pour seul paramètre une instance de
la classe afin de s'en servir comme modèle : on appelle un tel constructeur «
constructeur par recopie ». Dans son corps, on pourra recopier tous les
attributs de l'instance passée en paramètre, ou seulement certains en fonctions
des spécificités de la classe en question.
Attention
Comme pour les tableaux, on peut séparer
1. déclaration = typage
2. création = allocation mémoire
(voir exemple ci-après)
NOTA-BENE : les références non encore initialisées par new ont pour valeur null
lorsqu'elles sont dans un tableau ou dans une classe (attribut) ; dans les autres cas
(variables locales dans une fonction) elles n'ont pas de valeur du tout (erreur de
compilation)
82
Programmation par objets
Exemple
Salarie leDG ;
la variable leDG a été déclarée et typée (elle pourra stocker des références à des
instances de la classe Salarie)
// ....
leDG = new Salarie("Edgar Legrand", 53, 9500);
Un espace mémoire référencé par la variable leDG a été alloué et initialisé : il
contient l'objet créé, c'est à dire
1. une référence à une String contenant "Edgar Legrand "
2. un entier égal à 53
3. un double égal à 9500.0
6. Tableau d'objets
ATTENTION : un tableau d'objets est en fait un tableau de références vers objet :
Il faut donc créer les objets eux-mêmes (après avoir créer le tableau) :
RAPPEL : l'opérateur d'affectation (=) entre références ne copie que la référence, pas
l'espace mémoire référencé :
7. L'instruction instanceof
L'opérateur instanceof permet de tester si un objet est, ou n'est pas, instance d'une
classe donnée.
Ainsi, r instanceof C vaut :
- true si r est une référence à un objet pouvant être considéré comme une
instance de la classe C
- false sinon (y compris si r == null)
Remarque
instanceof permet aussi tester si un objet est, ou n'est pas, instance d'une classe
qui implante une « interface » donnée (cf. Interfaces p 139).
83
8. Destructeur
Destructeur : permet de définir un comportement lié à la destruction d'une instance
Si besoin, ajouter un destructeur à la classe en suivant la syntaxe :
protected void finalize() {...}
Le code sera appelé automatiquement par le « ramasse-miettes »
(garbage collector ou GC) juste avant de supprimer chaque objet de la classe
Sauf cas très particuliers, le destructeur n'est jamais invoqué explicitement
dans un programme
Utile en particulier pour « fermer » proprement des fichiers associés à une
instance
Remarque
Le destructeur est appelé une seule fois par instance quoi qu'il arrive (donc pas ré-
appelée par le GC si appelé « à la main » avant)
C. This
1. this(...) dans un constructeur
Le mot-clé « this » suivi de parenthèses permet d'invoquer un autre constructeur de
la classe :
this permet d'accéder à l'attribut « age » qui est masqué dans la méthode
changerAge() par le paramètre de même nom
Remarque
this étant par définition une référence sur l'instance courante, on ne peut utiliser
this que là où une instance courante existe, c'est à dire : uniquement lors de
l'écriture du corps d'une méthode non-statique (cf. Mot-clé static p 85).
84
Programmation par objets
class Fenetre {
// ....
public void montrerImage (Salarie untel) {
untel.dessinerDans(this);
}
}
cette utilisation de this en tant que référence sur l'instance courante est
essentielle : c'est le seul moyen de se passer « soi-même» en paramètre quand on
écrit le code d'une méthode.
D. Static
1. Mot-clé static
Mot-clef static : indique que ce qui suit est lié à la classe en tant que telle plutôt qu'à
l'une de ses instances.
On peut donner le caractère « statique » à :
- un attribut (y compris un attribut constant) ;
- un bloc d'instruction (initialisateur) ;
- une méthode.
2. Attribut statique
Attribut statique : attribut lié à la classe, sa valeur est partagée par toutes les
instances de la classe (il n'existe qu'une seule zone en mémoire pour stocker l'unique
valeur commune à la classe).
Synonyme : attribut de classe
Exemple :
class Cercle {
double rayon;
Color couleur;
// rayon et couleur : attributs ordinaires
// (une valeur par instance)
85
NOTA-BENE : un attribut statique peut-être déclaré constant avec le mot-clé final
(on parle alors de « constante de classe »), exemple :
class Direction {
public static final int NORD=1 ;
public static final int EST=2 ;
public static final int SUD=3 ;
public static final int OUEST=4 ;
}
// Utilisation :
// monRobot.tournerVers(Direction.EST) ;
3. Initialiseur statique
Initialiseur statique = bloc d'instructions exécuté une seule fois, lors du chargement
de la classe dans la machine virtuelle Java (au lancement du programme, donc bien
avant toute création d'instance).
class Cercle {
double rayon;
static int nbCercles=0;
// .…
}
86
Programmation par objets
4. Méthode statique
Méthode statique : méthode s'appliquant à la classe en tant que telle, et pas à une
instance en particulier
Exemples :
class Cercle {
static private int epaisseur=1;
static public void modifierEpaisseurDuTrait(int e) {
epaisseur = e;
}
}
class Cercle {
// ...
public void bidule () {
modifierEpaisseurDuTrait(2) ;
}
}
Cercle.modifierEpaisseurDuTrait(2);
// il faut préfixer avec le nom de la classe
Remarque
Le même principe s'applique pour l'accès aux attributs statiques.
87
6. Static or not static ?
E. Visibilité
Recommandations pour l'usage des mots clés : public,
private, ...
Obligatoire :
- la classe contenant la fonction main doit être publique
- un fichier .java ne peut contenir qu'une classe publique (au maximum)
Conseillé :
- les attributs sont généralement privés si besoin, créer des « accesseurs »
(méthodes publiques qui renvoient ou modifient la valeur d'un attribut privé)
- sauf cas très particuliers : les constructeurs sont publics
- les méthodes auxiliaires purement internes à une classe sont évidemment privées
- les méthodes dialoguant avec d'autres classes seront publiques
Voir plus loin pour détails sur public / private / protected / ... (cf. Niveaux de visibilité
p 127)
Exemple
class Contact {
// Attributs -> private (ou protected) :
private String nom;
private String mail;
private long tel ;
88
Programmation par objets
F. Types énumérés
Mot-clef enum au lieu de class
Equivaut à une classe ayant un nombre FINI d'instances, toutes prédéfinies
Syntaxe spécifique, peut servir dans un switch voir types énumérés « simples » (cf.
Types énumérés simples p 55)
Intérêt double : lisibilité du code + fiabilité (impossible d'affecter une valeur non
prévue)
enum Jeune {
BEBE ("Bebe", 0, 3),
ENFANT ("Enfant", 3, 12),
ADO ("Adolescent", 12, 18) ;
89
VII - Exceptions
VII
91
Exemple
Gestion des erreurs sans utiliser d'exceptions :
Exemple
Gestion des erreurs en utilisant des exceptions :
NOTA-BENE :
toute exception générée provoque l'arrêt brutal du programme ;
pour éviter cela, prévoir la capture et le traitement des exceptions ;
mots-clefs : try, catch et finally
Conseil
1. Eviter de créer un bloc try{...} catch ... séparé autour de chaque
instruction pouvant poser problème (car cela conduirait à un code pas
92
Exceptions
tellement plus clair qu'avec des if/else imbriqués) faire plutôt un bloc
try{...} catch ... le plus gros possible.
2. Ordonner les clauses catch du plus spécifique (en premier) au plus général
(vers la fin), avec si besoin une clause finally à la fin.
Rappel
Lorsqu'une variable c1 de type C (une classe quelconque) contient une référence
nulle, les écritures suivantes sont interdites (elles génèrent le lancement d'une
NullPointerException) :
int x = c1.a ; // tentative d'accès à l'attribut a de la classe C ;
c1.m() ; // tentative d'accès à la méthode m de la classe C ;
De même lorsqu'une variable t de type tableau contient une référence nulle, il est
interdit d'écrire :
93
int l = t.length ; // tentative d'accès à la taille du tableau ;
Arrays.sort(t) ; // cette méthode interdit les références nulles en
paramètre (cf. doc. de la classe prédéfinie Arrays)
Pour mémoire, une variable dont le type n'est pas un type primitif contient une
référence nulle tant que l'instance (ou le tableau) n'a pas été « créée » par new. Elle
peut aussi contenir une référence nulle si on lui affecte explicitement la valeur null
(par exemple pour provoquer la destruction de l'instance précédemment référencée
par cette variable).
E. Catégories d'exceptions
Classe mère : Throwable
Erreurs « système » : classe Error (dérivée de Throwable)
Autres anomalies : classe Exception (dérivée de Throwable) et ses sous-classes
Cas particuliers : classe RuntimeException (dérivée de Exception) et ses sous-
classes exceptions « non contrôlées » (voir plus loin)
Fonctionnement identique pour les erreurs et les exceptions :
NomException(String) : constructeur avec message explicatif sur la cause
de l'exception
String getMessage() : renvoie le message explicatif en question
String toString() : renvoie le type de l'exception (nom de sa classe) et le
message explicatif
void printStackTrace() : affiche la pile d'appel jusqu'au point de lancement
de l'exception
94
Exceptions
Remarque
Le diagramme ci-dessus présente quelques une des erreurs et exceptions les plus
courantes prédéfinies en Java.
Dans le diagramme chaque rectangle correspond à une classe et les flèches pointent
vers la classe « mère » au sens de l'héritage (cf. Héritage p 129).
H. Lancement d'exception
Possibilité de lancer « manuellement des exceptions » (en plus de celles générées
automatiquement)
Mot-clef : throw
Exemple :
if (test_anomalie) {
throw new Exception("blabla");
}
if (autre_test) {
throw new IllegalArgumentException("bla");
}
95
Conseil
Lancer de préférence une exception d'un type spécifique à l'anomalie (et contenant un
texte précisant la nature de l'anomalie).
J. Clause throws
Chaque méthode doit utiliser une clause « throws » pour déclarer toutes les
exceptions « contrôlées » :
1. qu'elle envoie elle-même (par throw)
2. qu'elle « laisse passer » (i.e. émises par des méthodes appelées, et non
traitées localement par un try/catch)
Exemple :
// ...
void lire() throws MonException, IOException {
// lancement explicite d'une exception si pb. :
if (testAnomalie() == true) {
throw new MonException("bla");
}
// appel d'une méthode susceptible de générer
// une exception contrôlée de type IOException :
int car = System.in.read();
}
Rappel
Toutes les exceptions sont « contrôlées » sauf celle dérivant de RuntimeException.
96
Exceptions
K. Assertions
Le mot-clé assert donne accès à un mécanisme de nature assez proche des
exceptions : les assertions.
Il s'agit de positionner dans un code java des lignes telles que :
assert r != null ;
assert t >= 0 : "t doit être positif ou nul !"
qui vont interrompre l'exécution du programme lorsque la condition est fausse – sous
réserve que le programme soit bien lancé dans un mode où les assertions sont
vérifiées. En effet, la vérification des assertions n'est pas le mode par défaut : pour
que les assertions soient vérifiées il faut lancer la machine virtuelle (le programme
java) avec l'option -enableassertions (ou -ea), sinon elles sont toutes ignorées afin
de ne pas ralentir l'exécution du code.
Comparé aux exceptions, il faut savoir que les assertions :
sont destinées à effecteur des vérifications « de routine » de nature à détecter
des bugs de programmation : il ne faut surtout pas les utiliser pour gérer autre
chose, comme par exemple des erreurs de saisie de l'utilisateur, un fichier
inaccessible, ... toutes les anomalies qui ne sont pas liées à une mauvaise
écriture du code doivent être gérées par des exceptions et pas des assertions ;
sont conçues pour faciliter la mise au point des programmes (c'est pourquoi le
dispositif est débrayable : une fois le programme débuggé on peut choisir de
supprimer la vérification des assertions pour privilégier la vitesse sur la
fiabilité) ;
sont nettement plus simples à utiliser ;
sont inactivées par défaut.
Remarque
Il est parfaitement possible de se passer complétement des assertions et utiliser
uniquement les exceptions (y compris pour gérer la détection des bugs). L'inverse est
faux : les exceptions sont un dispositif essentiel de Java qu'il est impératif de
connaître et maîtriser – ne serait-ce que pour pouvoir utiliser l'ensemble des classes
prédéfinies – on ne saurait donc s'en passer et n'utiliser que des assertions.
97
VIII - Entrées - Sorties
VIII
Remarque
En tant que « classes abstraites (cf. Classe abstraite p 133) », ces classes servent de
modèles aux classes qui suivent ; toutes ces méthodes seront donc disponibles par la
suite dès lors qu'on voudra lire/écrire des données très élémentaires (de nature
caractères ou octets). Pour lire des données de nature différentes (chaînes de
caractères, nombres, instance de classes, ...) il conviendra d'utiliser d'autres classes
de plus haut niveau (voir ci-après).
99
Attention
Les méthodes read() ci-dessus sont « bloquantes » : si il n'y a rien à lire sans
que l'on soit en fin de fichier alors le programme se bloque dans l'attente d'un
prochain octet ou caractère (cela ne peut pas arriver lors d'une lecture de
fichier sur disque dur mais peut survenir dans le cas d'une lecture sur le clavier
ou sur une connexion réseau), auquel cas le prochain octet ou caractère sera
automatiquement détecté et débloquera le read(), et le programme.
Les méthodes int read(byte[] buf) et int read(chat[] buf) lisent au
maximum buf.length octets ou caractères, et retournent le nombre
d'éléments lus, ou -1 si fin de flux.
Quatorze classes de « bas niveau » déclinent les quatre classes précédentes selon
l'origine ou la destination des données :
lecture/écriture (séquentielle) dans fichiers :
- en mode binaire : FileInputStream et FileOutputStream
- en mode caractères : FileReader et FileWriter
NOTA-BENE : nom du fichier en paramètre du constructeur
lecture/écriture dans tableau en mémoire :
- en mode binaire : ByteArrayInput(/Output)Stream
- en mode caractères : CharArrayReader et CharArrayWriter
NOTA-BENE : tableau en paramètre du constructeur
lecture/écriture dans une chaîne :
- en mode caractères : StringReader et StringWriter
NOTA-BENE : chaîne en paramètre du constructeur
enchaînements de flux (« pipes ») :
- en mode binaire : PipedInputStream et PipedOutputstream
- en mode caractères : PipedReader et PipedWriter
100
Entrées - Sorties
101
Exemple : Ecriture de deux lignes de texte dans un
fichier
import java.io.*;
// …
double x = 5.72 , y = -1.5;
// …
try {
PrintWriter out = new PrintWriter("f.txt");
out.println("x vaut : " + x);
out.println("y vaut : " + y);
out.close();
}
catch (FileNotFoundException e) {
System.err.println("f.txt ne peut pas être ouvert");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
102
Entrées - Sorties
Remarques :
Chaque étape (sauf l'import) peut lancer une IOException bloc try/catch (ou
throws) .
Pour lire des nombres ou toutes données structurées écrites sous forme texte,
utiliser la classe Scanner (voir exemple suivant)
// …
int n = 0;
// …
try {
FileReader in = new FileReader("f.txt");
while ( ( ch = in.read() ) != -1 ) {
if (ch == 'A') n++;
}
in.close();
}
catch (FileNotFoundException e) {
System.err.println("f.txt ne peut pas être ouvert");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
103
Remarque : chaque étape (sauf l'import) peut lancer une IOException bloc
try/catch (ou throws)
// …
int somme = 0;
try {
FileReader in = new FileReader("f.txt");
Scanner sc = new Scanner(in);
while (sc.hasNextInt()) {
somme += sc.nextInt();
}
in.close();
}
catch (FileNotFoundException e) {
System.err.println("f.txt n'existe pas");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
Complément
Dans l'exemple ci-dessus il faut que le fichier comporte uniquement des entiers et des
séparateurs (blancs, passages à la ligne, ...) sinon la lecture du fichier – et le calcul
de la somme – s'arrête avec le premier élément invalide (lettre, ponctuation, ...) dans
la mesure où sc.hasNextInt() retourne faux si le prochain élément à lire sur le flux
ne peut pas être considéré comme un entier écrit en base 10.
Dans la variante ci-dessous, le code a été « amélioré » pour faire la somme de tous
les entiers d'un fichier, quelque soit ce qu'il contient par ailleurs. On y utilise toujours
un scanner mais, à chaque tour de boucle, on commence par vérifier qu'il reste
quelque chose à lire par sc.hasNext() avant de lire l'élément suivant en distinguant
selon sa nature (entier ou pas).
import java.io.*;
import java.util.Scanner;
// …
int somme = 0;
try {
FileReader in = new FileReader("f.txt");
Scanner sc = new Scanner(in);
while (sc.hasNext()) {
if (sc.hasNextInt()) {
somme += sc.nextInt();
}
else {
sc.next();
}
}
in.close();
}
104
Entrées - Sorties
catch (FileNotFoundException e) {
System.err.println("f.txt n'existe pas");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
// …
Auteur a, b;
// …
try {
FileOutputStream out = new FileOutputStream("f.bin");
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(a);
objOut.writeObject(b);
b.modifier(.........); // attributs de b modifiés
objOut.reset(); // indispensable ici voir remarque !
objOut.writeObject(b);
objOut.close();
}
catch (FileNotFoundException e) {
System.err.println("f.bin ne peut pas être ouvert");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
105
Complément : Sérialisation / désérialisation
On appelle sérialisation ou linéarisation (en anglais serialization ou
marshalling) l'opération consistant à transformer des données en mémoire vive
(d'essence possiblement complexe telles qu'un arbre ou un graphe) en une série
d'octets en vu, typiquement, d'une sauvegarde sur fichier ou d'une transmission par
connexion réseau. L'opération inverse s'appelle désérialisation.
Dans le cadre d'un langage objet, il est ainsi fréquemment nécessaire de la sérialiser /
désérialiser des objets (instances des classes). Or, ce n'est pas une tâche triviale
dans le cas général dans la mesure où :
1. les données « propres » à un objet (celles qu'il convient de sauvegarder si on
veut pouvoir re-créer ensuite l'objet) se compose de l'ensemble de ses
attributs non-statiques, ainsi que ceux de sa classe mère (et récursivement
jusqu'à la classe racine)
2. chaque attribut dont la nature est « référence non-nulle » pointe soit sur un
tableau, soit sur objet, qu'il convient donc de sérialiser également. Le tout
forme un graphe avec possibilités de cycles.
3. en cas de sauvegarde sur fichier, il faut anticiper le problème que posera la
modification du programme entre l'instant où des données sont sérialisées et
celui où l'on cherchera à les relire pour recréer un objet : rien n'interdit que la
définition des classes correspondants aux objets sauvegardées ait été modifiée,
par exemple via l'ajout ou la suppression d'un attribut.
Pour simplifier le travail des programmeurs (et dans le même temps améliorer la
fiabilité des programmes), Java inclut en standard un mécanisme de sérialisation /
désérialisation capable de fonctionner automatiquement sur n'importe quel objet de
n'importe quelle classe, et pas seulement les classes prédéfinies. C'est bien sur ce
mécanisme qui est mis en œuvre de manière transparente par les méthode
writeObject() et readObject() sous réserve que la classe « implante l'interface
Serializable » (cf. Interfaces Serializable, Externalizable et mot-clé transient p
143).
Remarques :
chaque étape (sauf l'import) peut lancer une IOException bloc try/catch
(ou throws)
la méthode readObject() peut en outre lancer d'autres exceptions
penser à convertir ce que retourne readObject() dans le bon type (celui de
l'objet écrit à cet endroit du fichier)
106
Entrées - Sorties
// …
Auteur a;
// …
try {
FileInputStream in = new FileInputStream("f.bin");
ObjectInputStream objIn = new ObjectInputStream(in);
a = (Auteur) objIn.readObject();
objIn.close();
}
catch (FileNotFoundException e) {
System.err.println("f.bin ne peut pas être ouvert");
}
catch (IOException e) {
System.err.println("erreur d'entrée-sortie");
}
Remarque
Il peut être utile de connaître davantage de détails sur le fonctionnement des
méthodes readObject() et writeObject(), surtout lorsqu'on ne se satisfait pas du
comportement par défaut consistant à lire/écrire tous les attributs de la classe : voir
plus loin pour un complément à ce propos nécessitant d'avoir déjà vu les notions
d'héritage et d'interfaces (cf. Interfaces Serializable, Externalizable et mot-clé
transient p 143).
107
2. Manipulation de fichiers et répertoires
File : classe pour manipuler fichiers/répertoires (accès à la taille, listage du contenu,
suppression, renommage, ...)
constructeurs :
- File(String name)
- File(String path, String name)
- ...
méthodes :
- boolean exists()
- long length()
- File getParent()
- boolean isDirectory()
- String[] list()
- void delete()
- void mkdir(),
- boolean renameTo(File f)
- ...
108
Listes, piles, files,
IX -
arbres
IX
A. Problématique commune
Trouver une structure de données qui permette de représenter en mémoire, et
manipuler, efficacement une suite d'éléments de même type.
Atteindre tous ces objectifs à la fois est impossible en général. Le mieux que l'on
puisse faire consiste à choisir la « meilleure » structure de données dans un
contexte donné, c'est-à-dire celle qui présente le compromis optimal lorsque l'on
tient compte :
1. de la nature des éléments à manipuler ;
2. de l'application à réaliser, chaque application se caractérisant par une
distribution différente dans la fréquence relative des opérations ci-dessus.
Aussi, il est important de bien connaître les structures de données classiques que
sont les listes, piles, files et arbres (et pour chacune de comprendre les différentes
implantations possibles) afin de savoir bien choisir la combinaison type abstrait -
implantation la mieux adaptée à la résolution d'un problème donné.
109
Exemple
Un tableau d'entier conviendrait-il pour ranger efficacement des entiers dans l'ordre
croissant ?
B. Listes
1. Introduction
Une liste est une suite finie de N+1 couples (ai, pi) E P {null} telle que :
(ai , pi ) s'appelle un maillon
E est l'ensemble des éléments ai
P est l'ensemble des positions pi
valeur ((ai, pi)) = ai E
position (a0, p0) = premier P
position ((ai, pi)) = pi -1 P i > 0
pn = null P
Attention
Une liste est ordonnée par la fonction de succession (rang = n ième maillon de la liste),
mais la position peut n'avoir aucun rapport avec cet ordre.
110
Listes, piles, files, arbres
2. Fonctions de manipulation
Les accesseurs
renvoient des positions de maillons
Les transformateurs
modifient une liste (peuvent éventuellement renvoyer une liste modifiée)
Les observateurs
renvoient des renseignements divers
111
3. Implantation
Avantages
- Accès direct à l'élément par l'indice
Inconvénients
- Insertion, suppression, ajouts délicats
- Taille maximum fixée à l'avance
Avantages
- Accès semi-direct à l'élément par l'indice
- Réarrangement facile
Inconvénients
- Taille maximum fixée à l'avance
- Comment ajouter rf ?
112
Listes, piles, files, arbres
Avantages
- Taille maximum non fixée à l'avance, occupation mémoire optimale (si on
néglige l'espace occupé par les références vers les maillons suivants)
- Réarrangement facile
Inconvénients
- Parcours séquentiel obligatoire pour accéder à un élément
4. Applications
Liste ordonnée pour ranger des éléments suivant un ordre prédéfini
(insertion, suppression)
- augmente le temps d'insertion d'un nouvel élément
- diminue le temps de restitution (évite un tri)
- Ex : répertoire alphabétique, actions datées, catalogue de références, …
Pile et File pour simplifier à l'extrême le jeu d'instructions
- Pile : on met et retire un élément uniquement en fin de liste
- File : on ajoute les éléments en fin de liste, on les retire en début de liste
C. Piles
1. Introduction
Une pile est une liste à accès restreint, c'est une suite d'éléments accessible
uniquement par le sommet
Une pile est une liste de type « LIFO » (Last In First Out)
Fonctions essentielles d'une pile:
- Créer une pile
- Empiler un maillon
- Dépiler un maillon
- Obtenir l'élément « sommet » (peut-être combiné à « dépiler »)
- Vérifier si la pile est vide
113
2. Fonctions de manipulation
Si E est l'ensemble des éléments et P l'ensemble des piles, les fonctions
d'accès à une pile sont :
méthode arguments retour action
sommet() P E renvoie
l'élément situé
au sommet
estVide() P B renvoie un
booléen : vrai
si la pile est
vide, faux
sinon
Selon la manière d'implanter une pile, on peut modifier le type, ou les
arguments de ces fonctions. (par ex : dépiler() peut renvoyer le sommet et pas
la pile)
3. Piles : implantation
Selon l'utilisation souhaitée, on peut implanter une pile par tableau statique ou
chaîné ou par allocation dynamique de mémoire.
Tableau : dans le cas d'un tableau simple, il faut un tableau de N éléments et
un entier désignant le sommet courant.
Attention, la taille est fixée, d'où la gestion nécessaire d'un dépassement (pile
pleine)
Chaînage : il faut soit utiliser un tableau chaîné (statique), soit considérer une
structure maillon qui contient la partie « élément », et une référence au maillon
suivant (dynamique)
114
Listes, piles, files, arbres
4. Application
La pile (stack) est beaucoup utilisée en programmation (pile d'appels, pile
d'erreurs).
La gestion de la récursivité fait généralement appel à une pile.
Certaines calculettes utilisent la notion de pile pour éviter la gestion des
parenthèses.
Exemple d'utilisation d'une pile : gestion de la pile d'appels d'une fonction récursive
115
D. Files
1. Introduction
Une file est une liste à accès restreint ; c'est une suite d'éléments accessible
par le sommet en entrée, par la base en sortie
Une file est une liste de type « FIFO » (First In First Out)
Fonctions essentielles d'une file:
- Créer une file
- Ajouter un maillon (au sommet)
- Retirer un maillon (à la base)
- Vérifier si la file est vide
2. Fonctions de manipulation
Si E est l'ensemble des éléments et F l'ensemble des files, les fonctions d'accès
à une file sont :
estVide() F B renvoie un
booléen : vrai
si la pile est
vide, faux
sinon
116
Listes, piles, files, arbres
3. Implantation
Seule une implantation de type « chaînée » convient pour une file.
L'implantation en tableau simple nécessiterait de réorganiser le tableau à
chaque suppression
4. Applications
Les files sont souvent utilisées pour gérer « l'attente ».
Les files d'attente d'impressions, les buffers sont autant de files
E. Arbres
1. Introduction
Structure d'arbre
Un arbre est une extension de la notion de liste dans laquelle un maillon peut
avoir plusieurs suivants.
C'est donc une suite d'éléments qui ont chacun 0, 1, ou plusieurs suivants.
En conséquence, il y a plusieurs façon de définir un ordre, c'est à dire le
« rang » d'un élément.
2. Récursivité
Un arbre peut toujours être considéré d'une manière récursive par sa racine et un
ensemble d'arbres liés à cette racine (les sous-arbres).
117
3. Vocabulaire
« racine », « feuilles »
« nœud », « branche »
« fils », « père », « frères »
« ascendants »
« descendants »
« arc », « chemin »
« sous-arbre »
« niveau »
« profondeur »
« forêt »
« complet »
« dégénéré »
« général »
« binaire »
4. Arbres binaires
Un arbre binaire, est une arbre général dont les nœuds ne peuvent avoir plus
de 2 fils.
En pratique, il existe une équivalence entre arbre général et arbre binaire.
118
Listes, piles, files, arbres
6. Parcours
Dans une numérotation dynastique, on distingue essentiellement 3 modes de
parcours d'un arbre binaire - selon la position de la racine dans le parcours -
(récursivité):
Le parcours R G D dit parcours préfixé.
Le parcours G R D dit parcours infixé.
Le parcours G D R dit parcours postfixé.
void afficherRGD() {
if ( !(estVide())) {
imprimeRacine();
gauche.afficherRGD();
droit.afficherRGD();
}
else {
imprimerVide();
}
}
119
9. Implantation
Par Chaînage :
Il faut considérer une structure récursive qui contient, à chaque niveau :
- la partie « élément » (racine)
- Des références aux sous arbres comme - par exemple - une liste de sous-
arbres
Dans le cas d'un arbre binaire :
- une référence à un arbre : le sous arbre gauche
- une référence à un arbre : le sous arbre droit
Par Tableau :
Il faudrait un tableau de N éléments et (pour un arbre binaire) deux tableaux
de N entiers pour représenter les indices (dans le tableau) des fils à gauche et
à et droite.
Très peu utilisé par sa structure figée et les « trous » laissés lorsque l'arbre
n'est pas complet.
10. Applications
Gestion syntaxique d'une expression logique parenthésée
Principe :
Si opérateur alors on crée un sous-arbre dont l'opérateur est la racine
Sinon (opérande) on crée une feuille
120
Listes, piles, files, arbres
121
Paquetages,
X-
importation
X
Paquetage 123
Paquetage et visibilité 123
Importation 124
Nommage des paquetages 124
Organisation en fichiers, compilation et exécution 124
Paquetages standards de Java 125
A. Paquetage
Entité de structuration regroupant plusieurs classes et/ou interfaces et/ou sous-
paquetages
Les packages définissent des espaces de nommage (ou namespace) distincts
(réduit les risques de conflits dans les noms de classes)
Le paquetage d'appartenance est indiqué au début du fichier source par :
package nomPackage;
Les fichiers .class de chaque paquetage doivent impérativement être placés dans un
répertoire ayant le nom exact du paquetage
Les paquetages (et classes) sont recherchés dans une liste de répertoires (et/ou de
fichiers zip) fixée par la variable d'environnement : CLASSPATH
Attention
Par défaut (lorsque le mot-clé package est omis en début de fichier) les classes et
interfaces sont définis dans le « paquetage anonyme » à éviter, sauf pour de petits
programmes.
B. Paquetage et visibilité
Par défaut, les classes et interfaces ne sont visibles que dans le paquetage où elles
sont définies
seules celles qui sont déclarées « publiques » pourront être importées dans d'autres
paquetages.
Exemple :
123
class Auxiliaire {
// classe visible dans son package uniquement
// (pas de possibilité de l'importer)
}
Par défaut, les attributs et méthodes sont visibles dans tout le paquetage de la classe
où ils sont définis (et nulle part ailleurs).
Les mots-clés public, protected et private appliqués aux attributs et méthodes
permettent de modifier la visibilité « paquetage » par défaut.
C. Importation
Pour utiliser une classe (publique) C à l'extérieur de son package P :
la désigner par son nom complet : P.C
ou alors l'importer en début de fichier par : import P.C;
puis la désigner par son nom court : C
Possibilité d'importer toutes les classes publiques d'un package P par : import P.*;
NOTA-BENE : importer des attributs et/ou méthodes non-statiques n'est pas possible
(cela n'aurait guère de sens).
Conseil
L'importation statique doit être utilisée avec parcimonie (le système de nommage par
défaut de Java est conçu pour faciliter l'écriture de grands programmes en évitant les
conflits de noms, y compris lorsque le code évolue dans le temps).
On évitera en particulier d'utiliser le caractère * pour importer tous les attributs et
méthodes statiques d'une classe, sauf à la rigueur pour les classes les plus connues
de Java telles que java.lang.Math.
124
Paquetages, importation
Conseil
Penser à la documentation en-ligne de Java pour approfondir tel ou tel paquetage,
voir aussi les nombreux tutoriaux disponibles (cf. Annexe : ressources
complémentaires sur Java p 219).
125
Compléments sur les
XI -
classes
XI
A. Niveaux de visibilité
Objectif : sécuriser l'écriture des programmes composés d'un grand nombre de
classes.
Trois mots-clés : private, protected et public (package est la visibilité par défaut en
l'absence de qualificatif)
Voir les règles de bon usage dans le chapitre sur les classes (cf. Visibilité p 88).
127
Exemple
class Employe {
private String nom;
protected int age;
protected int salaire;
public toString() {...}
double calculerPrime() {....}
// ...
}
Complément
La visibilité « protected » n'a de sens spécifique que lorsqu'une (au moins) des
classes filles est située dans un package différent.
128
Compléments sur les classes
2. Héritage
Intérêt de l'héritage : réutiliser une classe existante en l'adaptant ; créer des
variantes d'une classe ; ...
Mot-clef : extends
class Figure {
private String nom;
private Position pos;
public Figure(Position p){ pos = p; }
public void deplacer(int dx, int dy) {
pos.ajouter(dx, dy);
}
}
129
3. Héritage, attributs et méthodes
Une sous-classe (ou classe fille ou classe dérivée) hérite de tous les attributs
et méthodes (y compris statiques) de sa super-classe (ou classe mère) :
4. Héritage et visibilité
Une classe fille ne peut accéder qu'aux attributs et méthodes « public » ou
« protected » de sa classe mère (ainsi qu'aux attributs et méthodes « package » ssi
elle appartient au même paquetage que sa classe mère) :
5. Héritage et références
Toute référence vers une instance de la classe fille peut être vue aussi comme une
référence vers la classe mère (conversion automatique fille mère) :
if ( f.contient(c) ) {
// OK : passage d’un Cercle en paramètre
// à une méthode attendant une Figure
130
Compléments sur les classes
6. Héritage et constructeurs
Les constructeurs ne sont pas hérités, mais on peut appeler ceux de la classe mère
avec super(...) :
NOTA-BENE :
l'appel super(...) doit impérativement être la 1ère instruction du constructeur
si la 1ère instruction n'appelle ni le constructeur de la classe mère, ni un autre
constructeur de la classe fille, alors il y a appel automatique de super() sans
argument
ordre des opérations :
1/ appel du constructeur de la classe mère
2/ initialiseurs et blocs d'initialisation
3/ corps du constructeur fille
131
private float rayon;
//...
public void afficher() {
// si besoin, appel de la méthode de même
// nom dans la classe mère :
super.afficher();
// traitement spécifique à la classe fille :
System.out.println("rayon=" + rayon);
}
}
Remarque
La visibilité d'une méthode redéfinie peut être différente (mais seulement
augmentée).
En cas de masquage, c'est le type de la référence qui détermine quel attribut
est pris en compte par défaut entre celui de la classe fille et celui héritée mais
masqué.
Il est possible d'accéder à un attribut (mais pas à une méthode) masqué d'une
classe ancêtre quelconque en utilisant la syntaxe : ((ClasseAncêtre)
this).attributMasqué
L'annotation (cf. Annotations p 177) @Override permet d'expliciter l'intention
du programmeur de redéfinir une méthode héritée, syntaxe : @Override public
void afficher() { .... }
La redéfinition d'un attribut non-statique crée en pratique un 2° attribut pour
chaque instance de la classe fille (Java alloue une zone mémoire
supplémentaire et stocke les 2 valeurs).
8. Polymorphisme dynamique
Quand on manipule un objet via une référence à une classe mère, ce sont toujours les
méthodes (non statiques) de la classe effective de l'objet qui sont appelées :
Figure f = new Cercle();
// ...
f.afficher();
// appel afficher() de Cercle bien que
// f est une référence de type Figure !
9. Méthode abstraite
Une méthode « abstraite » est une méthode dont on a spécifié la signature mais
pas écrit le corps
Mot-clef : abstract
class Figure {
//...
public abstract void colorier();
}
132
Compléments sur les classes
Toute classe qui contient au moins une méthode abstraite (ou qui en hérite une sans
la redéfinir) doit obligatoirement être déclarée abstraite
Exemple :
133
13. Héritage et tableau
Si une classe Fille dérive de Mere, alors Fille[] est considéré comme un « sous-
type »17 de Mere[].
Cela se traduit par le fait qu'un tableau d'instances de Fille sera autorisé partout où
un tableau d'instances de Mere est attendu. Exemple :
La classe Object définit plusieurs méthodes héritées par toutes les classes (et
applicables aussi aux tableaux) :
boolean equals(Object obj)
par défaut, retourne this==obj (compare les références), mais conçue pour
être redéfinie afin de comparer véritablement les contenus (ex : classe String)
int hashCode()
par défaut, retourne un entier raisonnablement utilisable dans une table de
hashage (entier déduit de l'adresse mémoire de l'objet), conçue pour être
redéfinie si besoin pour optimiser les performances du hashage
String toString()
par défaut, retourne "NomClasse@"+hashCode(), mais conçue pour être
redéfinie pour produire une représentation textuelle pertinente de l'objet
finalize()
par défaut, ne fait rien, mais conçue pour être redéfinie si besoin pour
spécifier quoi faire lors de la destruction de l'objet avant de libérer la mémoire
Object clone() : voir ci-après
Class getClass() : voir ci-après
notify(), notifyAll(), wait() : voir le chapitre sur les Threads (cf.
Synchronisation des exécutions p 210)
17 - Le concept de Sous-type est proche mais différent de celui de sous-classe et d'héritage. Il dépasse le
cadre des langages objets ; il veut dire que les instances du sous-type sont systématiquement substituables
aux instances du type. A la différence de l'héritage, il ne signifie pas que le sous-type est défini à partir du
type en termes de sémantique et/ou d'implantation. Dans le cas de tableaux d'objets on préférera employer
le vocabulaire type/sous-type dans la mesure où les tableaux en Java ne sont pas eux-mêmes des classes.
134
Compléments sur les classes
Conseil
Sous Eclipse, le plus efficace pour redéfinir les méthodes equals() et/ou hashCode()
consiste à les générer à partir du menu « Source -> Generate hashCode() and
equals() ». D'une manière générale beaucoup de tâches plus ou moins complexes
et/ou fastidieuses peuvent être effectuées efficacement à l'aide des menus « Source »
et « Refactor » d'Eclipse (génération d'un constructeur, création d'un bloc try/catch,
etc.).
L'équivalent existe sur NetBeans (alternative à Eclipse).
135
15. Méthode clone()
La méthode clone() de la classe Object permet de dupliquer un tableau ou une
instance (recopie des attributs)
Sur les tableaux, clone() est directement utilisable :
int[] tab = { 1, 2, 3, 4 } ;
int[] tab2 = tab.clone() ;
ATTENTION : pour les tableaux multi-dimensionnels et pour les tableaux d'objets car
la méthode clone() telle que définie dans la classe Object copie les références (et
pas les objets référencés)
Sur les objets, clone() n'est pas toujours utilisable par défaut les objets ne sont
pas « clonables », pour pouvoir leur appliquer la méthode clone() il faut :
1. déclarer que la classe implante l'interface Cloneable
2. redéfinir la méthode clone() en tenant compte des spécificités de la classe
(e.g. attributs de type référence)
136
Compléments sur les classes
E. Introspection
Chaque classe (et interface) est représentée par une instance de la classe Class (cf.
La classe Class p 164)
La classe Class permet d'instancier une classe à partir de son nom :
Class cl;
cl = Class.forName("NomPackage.NomDeClasse");
Object o = cl.newInstance();
Les classes Class, Method, Field et Constructor permettent d'explorer (et invoquer)
dynamiquement du code Java (on parle alors d'introspection) :
Method[] getDeclaredMethods()
Field[] getDeclaredFields()
Constructors[] getDeclaredConstructors()
Class[] getInterfaces()
Class getSuperClass()
boolean isInterface()
// ...
Complément
On appelle « introspection » (en anglais : reflection), la possibilité dans un langage
de programmation de pouvoir étudier dynamiquement le code en cours d'exécution,
avec dans le cas d'un langage objet, la possibilité de naviguer dans le réseaux de
classes/attributs/méthodes.
Certains programmes sont de fait bien plus simples à écrire si on peut utiliser ce
mécanisme.
Exemple : supposons que pour tester une classe on souhaite disposer d'une interface
homme-machine qui donne accès à la liste complète des méthodes définies dans cette
classe ; en utilisant l'introspection pour construire la liste des fonctions de la classe on
est certain que la liste sera toujours à jour sans pour autant avoir à la mettre à jour,
d'où un gain de temps (et de fiabilité).
En Java, l'introspection est possible à travers les méthodes de la classe Class, Field
et Method.
Elle inclut la possibilité d'instancier une classe et/ou d'invoquer une méthode dont le
nom est déterminé à l'exécution du code.
Toutefois, il n'est pas possible en Java d'utiliser la classe Class pour modifier une
classe à l'exécution (i.e. ajouter ou supprimer un attribut ou une méthode par
exemple).
ATTENTION : l'introspection peut permettre de contourner le typage fort au niveau
du compilateur Java mais ce faisant on prend le risque de générer des erreurs
(IllegalArgumentException) lors de l'exécution du programme. Autrement dit, le
typage fort en Java n'est pas juste lié aux vérifications effectuées par le compilateur
(et qui se matérialisent par des interdits sous Eclipse), il est plus fondamentalement
lié aux mécanismes de contrôle qu'applique systématiquement la machine virtuelle au
bytecode lors de son exécution. On ne peut donc pas utiliser l'introspection pour
contourner le typage de Java et programmer ainsi comme on le ferait dans un
langage faiblement typé !
137
Conseil
Penser au tutoriel d'Oracle18 sur le sujet pour approfondir cet aspect du langage (le
tutoriel d'Oracle est organisé sous forme de sentiers dont un sentier intitulé « The
Reflection API ».)
18 - http://docs.oracle.com/javase/tutorial/
138
XII - Interfaces
XII
Interfaces 139
Exemple d'interfaces 140
Autres exemples d'interfaces 140
Interfaces prédéfinies en Java 141
Héritage entre interfaces 141
Implantation d'une interface par une classe 141
Interface dans une déclaration d'attribut, variables, ... 141
Interfaces en paramètres de méthodes 142
Interfaces « marqueurs » 142
Interfaces Serializable, Externalizable et mot-clé transient 143
Interfaces fonctionnelles 144
Passage d'une fonction/méthode en paramètre de méthode
144
Méthodes par défaut 146
Corps de méthodes statiques dans une interface 146
Comparaison interfaces / classes abstraites 147
A. Interfaces
Interface = ensemble de signatures = ensemble de méthodes toutes abstraites
Remarque
En Java, une interface peut aussi contenir :
des constantes de classe ;
des méthodes « par défaut » (cf. Méthodes par défaut p 146) ;
des méthodes statiques avec leur corps (cf. Corps de méthodes statiques dans
une interface p 146).
139
Complément
Les constantes définies dans une interface sont toujours public, static et final :
ces mots-clés peuvent donc être omis, ils sont implicites dans le contexte d'une
interface.
De même, les méthodes définies dans une interface sont toujours abstraites et
publiques (sauf cas particulier des méthodes « par défaut ») : inutiles donc de les
qualifier de public et abstract.
B. Exemple d'interfaces
Définition d'une interface, puis d'une classe qui « implante » cette interface :
interface Coloriable {
// NOTA-BENE :
// possibilité de définir des constantes :
Couleur ROUGE = new Couleur("rouge");
Couleur NOIR = new Couleur("noir");
//...
void colorier(Couleur c);
}
interface Pile {
void empiler(Object o);
void depiler();
boolean estVide();
//...
}
140
Interfaces
NOTA-BENE : une référence à une interface peut désigner toute instance de toute
classe qui implante l'interface en question.
Attention
Les méthodes applicables dépendent de la nature de la référence :
Cercle cercle = new Cercle();
Redimensionnable redim = cercle;
Coloriable col = cercle;
141
// ATTENTION : dans un tel cas, les méthodes applicables
// dépendent de la vue utilisée :
col.colorier(Coloriable.ROUGE); // OK
col.grossir(2); // ERREUR
redim.grossir(2); // OK
cercle.colorier(Coloriable.ROUGE); // OK
RAPPEL : une référence à une interface peut désigner toute instance de toute classe
qui implante l'interface en question.
Autre exemple :
interface Comparable {
int compareTo(Object o);
}
class Tri {
public static void trier(Comparable[] tab) {
//...
if (tab[i].compareTo(tab[j]) > 0) {
//...
}
}
}
I. Interfaces « marqueurs »
Définition
On appelle interface « marqueur » ou « interface de marquage » (en anglais :
marker interface) une interface qui ne contient aucune méthode ni constante, et
sert juste à préciser une propriété des classes qui l'implantent.
142
Interfaces
Etant donné leur grande utilité, il est toutefois souhaitable d'aller plus loin dans leur
étude et réaliser que leur fonctionnement dans le cas général dépend de deux
interfaces prédéfinies en Java : Serializable et Externalizable.
143
interface est quelque chose qui s'hérite, autrement dit : une classe est «
serializable » si elle est déclarée comme telle ou si l'une des classes dont
elle hérite implante l'interface Serializable (idem pour Externalizable).
K. Interfaces fonctionnelles
Définition
Interface contenant une et une seule méthode abstraite non-statique.
Complément
L'annotation (cf. Annotations p 177) @FunctionalInterface avant une définition
d'interface permet de s'assurer que l'interface comporte bien une et une seule
méthode abstraite non-statique (surtout elle empêche qu'un programmeur y ajoute
involontairement une seconde méthode abstraite dans le futur et transforme ainsi une
interface fonctionnelle en interface ordinaire).
Exemple :
interface FonctionAUneVariable {
double appliquer(double d);
}
class Sin implements FonctionAUneVariable {
public double appliquer(double d) { return Math.sin(d); }
}
class DoubleExp implements FonctionAUneVariable {
public double appliquer(double d) {
return Math.exp(Math.exp(d));
}
}
class CN {
public static double integrer(FonctionAUneVariable f,
double deb, double fin, double pas) {
double s=0.0 , x=deb;
long n = (long) ((fin-deb)/pas)+1;
for (long k=0 ; k<n ; k++, x+=pas) {
s += f.appliquer(x);
}
144
Interfaces
return s*pas;
}
}
// ............
double d1 = CN.integrer(new Sin(), 0, Math.PI, 0.001);
double d2 = CN.integrer(new DoubleExp(), 0, 4, 0.01);
// d1 vaut 2.0 et d2 vaut 12416347058128187000000,0
Remarque
La même technique peut être utilisée pour le type de retour : le type de retour d'une
méthode peut être une interface permettant indirectement de désigner une méthode
ou fonction.
class CN {
public static double integrer(FonctionAUneVariable f,
double deb, double fin, double pas) {
double s=0.0 , x=deb;
long n = (long) ((fin-deb)/pas)+1;
for (long k=0 ; k<n ; k++, x+=pas) { s += f.appliquer(x); }
return s*pas;
}
}
// ............
double d1 = CN.integrer(Math::sin, 0, Math.PI, 0.001);
double d2 = CN.integrer((d) -> Math.exp(Math.exp(d)), 0, 4, 0.01);
NOTA-BENE :
la notation C::m permet de désigner directement la méthode m définie dans la
classe C ;
l'opérateur -> sert à définir une lambda expression (indispensable dans
l'exemple ci-dessus vu que la fonction double-exponentielle n'est pas définie en
tant que telle comme l'est la fonction sinus dans la paquetage Math).
class CN {
public static double integrer(Function<Double, Double> f,
double deb, double fin, double pas) {
double s=0.0 , x=deb;
long n = (long) ((fin-deb)/pas)+1;
for (long k=0 ; k<n ; k++, x+=pas) { s += f.apply(x); }
return s*pas;
145
}
}
// ............
double d1 = CN.integrer(Math::sin, 0, Math.PI, 0.001);
double d2 = CN.integrer((d) -> Math.exp(Math.exp(d)), 0, 4, 0.01);
NOTA-BENE :
l'interface fonctionnelle prédéfinie Function<T, V> comporte une méthode
abstraite unique apply() prenant en paramètre une instance de la classe T et
retournant une instance de la classe V ;
en typant le premier paramètre de la méthode integrer() par
Function<Double, Double> f, on indique que la méthode integrer() accepte
comme premier paramètre toute fonction prenant en paramètre (et retournant)
une instance de la classe Double (le type Double étant compatible avec le type
primitif double, on peut comme dans l'exemple invoquer integrer() avec une
fonction travaillant sur des double comme Math.sin()).
Remarque
Les lambda-expressions, les références sur méthodes/fonctions ainsi que le package
java.util.function ne sont pas détaillés dans ce document.
Attention
Les méthodes par défaut ne peuvent pas utiliser les variables d'instance de la
classe.
Si dans deux interfaces il existe une méthode par défaut commune (avec la
même signature) alors tout classe qui implante ces deux interfaces devra
impérativement surcharger cette méthode (erreur de compilation sinon).
Soit une classe C qui implante une interface I où est définie une méthode par
défaut m(), alors si m() est surchargée dans C, son implantation par défaut
dans I reste accessible depuis la classe C avec la syntaxe : I.super.m();
146
Interfaces
147
Collections (listes,
XIII -
ensembles, files,
tables) XIII
Introduction 149
Deux versions : « paramétrée » ou pas 150
Les classes Collections et Arrays 151
Fiches pratiques et exemple d'utilisation 151
Principales interfaces et classes 154
A. Introduction
Collection = structure de donnée permettant de rassembler plusieurs éléments (ex. :
tableau, liste, …)
149
Complément
Le paquetage java.util s'enrichit régulièrement, au fil des nouvelles versions du
langage Java 1.8 propose ainsi 9 sortes de collections (interfaces correspondant à
un type abstrait) et plus de 20 implantations (classes).
Remarque
A chaque sorte de collection correspond :
une interface (spécification du type abstrait en question)
une ou plusieurs classes qui implantent cette interface (avec des stratégies
différentes en termes de stockage en mémoire et/ou d'algorithmes).
Attention
Plusieurs restrictions à connaître lorsqu'on utilise les collections de Java :
Les collections ne peuvent contenir que des objets (pas de types
primitifs)
Les types ArrayList, ArrayList<String> et ArrayList<Integer> (par
exemple) sont distincts et incompatibles (bien qu'il n'y ait en fait qu'une
unique classe ArrayList)
Il est impossible de créer des tableaux dont les éléments sont d'un type
paramétré (new ArrayList<String>[3] est par exemple illégal !)
utiliser à la place des collections de collections, e.g. :
ArrayList<ArrayList<String>> lili ;
lili = new ArrayList<ArrayList<String>>() ;
150
Collections (listes, ensembles, files, tables)
NOTA-BENE : la classe Arrays contient le même genre de fonctions pour les tableaux.
151
3. Exemple d'utilisation de la classe LinkedList
On crée une liste de String (de type LinkedList) sur laquelle on exécute quelques
méthodes de l'interface List :
import java.util.*;
pn.add("Paul"); // INSERTION
pn.add(0, "Léa"); // INSERTION (EN *DEBUT* DE LISTE)
pn.add("Julie"); // INSERTION (EN FIN DE LISTE)
System.out.println(pn); // AFFICHAGE
152
Collections (listes, ensembles, files, tables)
Elle permet d'utiliser les fonctions pré-programmées telles que sort(), exemple :
Class C implements Comparable <C> {
//...
public int compareTo(C autre) { ... }
}
Elle permet d'utiliser les fonctions pré-programmées telles que sort() pour réaliser
des tris multi-critères, exemple :
class ComparePrix implements Comparator <Produit> {
public int compare (Produit o1, Produit o2) {
return (int) (o1.getPrix () - o2.getPrix () )
}
}
class CompareNom implements Comparator <Produit> {
public int compare (Produit o1, Produit o2) {
return o1.getNom.compareTo( o2.getNom () );
}
}
153
E. Principales interfaces et classes
1. L'interface Collection
L' interface Collection (ou plutôt l'interface Collection<E>, où E est le type des
éléments) regroupe les méthodes communes à toutes les collections :
taille : int size()
test si vide : boolean isEmpty()
ajout : boolean add(E elt)
suppression : boolean remove(E elt)
suppression de tous les éléments : void clear()
recherche : boolean contains(E elt)
création d'un itérateur : Iterator<E> iterator()
conversion en tableau : Object[] toArray()
...
Remarque
add(elt) renvoie false uniquement dans le cas où elt figure déjà dans la
collection et que celle-ci interdit les duplicata.
La présence de méthodes add() , clear() et remove() véritablement
utilisables n'est pas garantie pour toutes les implantations qui implantent cette
interface : certaines implantations peuvent en effet lancer l'exception
UnsupportedOperationException quand on les appelle (cf. documentation des
différentes implantations).
2. L'interface Iterator
L'interface Iterator permet de parcourir n'importe quelle sorte de collection.
Un itérateur :
s'obtient par appel de iterator() sur la collection à parcourir
contient les méthodes :
- boolean hasNext()
- E next()
- void remove()
Attention
Il faut impérativement re-créer nouveau itérateur (par appel de iterator()) dès que
la collection originale a été modifiée [ par appel à add(), remove(),... en dehors de
l'itérateur ]
154
Collections (listes, ensembles, files, tables)
E remove(int index)
int indexOf(E elt)
ListIterator<E> listIterator(int debut)
ListIterator<E> listIterator()
...
Trois implantations :
classe LinkedList<E> (liste doublement chaînée)
classe ArrayList<E> (tableau)
classe Vector<E> (implantation similaire à ArrayList mais « synchronized » +
méthodes additionnelles)
En pratique, et dans le cas d'un usage dans un seul thread, la classe ArrayList est
plus efficace (parcours, recherche, ...) et la classe Vector plus puissante ; il est donc
recommandé d'utiliser la classe ArrayList dès lors qu'on n'a pas besoin de ce
qu'ajoute la classe Vector.
4. L'interface ListIterator
L'interface ListIterator<E> est spécifiquement conçu pour parcourir les listes :
s'obtient par appel de listIterator() sur la liste à parcourir
étend l'interface Iterator<E> en ajoutant des méthodes :
- pour parcourir en sens inverse : previous(), hasPrevious(), ...
- pour insérer : add(E elt)
- pour modifier : set(E elt)
- …
155
Remarque
En héritant de la classe Vector, la classe Stack de Java fournit une implantation du
type abstrait pile qui inclut des méthodes permettant d'accéder directement à
n'importe quel élément, et pas juste au sommet comme on pourrait s'y attendre pour
une pile.
L'interface Set<E> contient les mêmes méthodes que Collection<E>, plus les
méthodes suivantes :
Test d'inclusion : e1.containsAll(e2)
Union : e1.addAll(e2) [modifie e1 !]
Intersection : e1.retainAll(e2) [modifie e1 !]
Deux implantations :
classe HashSet<E> pour Set<E> (utilisant une table de hachage HashMap<E,
Object>)
classe TreeSet<E> pour SortedSet<E> (utilisant un « arbre bicolore »
TreeMap<E, Object>)
156
Collections (listes, ensembles, files, tables)
157
11. Principales implantations de l'interface Map
Deux implantations principales :
HashMap<K,V> = implantation de Map<K,V> par hachage
TreeMap<K,V> = implantation de SortedMap<K,V> par « arbre bicolore »
Set<MonEnum> s;
s = EnumSet.allOf(MonEnum.class);
Complément
EnumMap<K extends Enum<K>, V> est une classe offrant une implantation de Map
spécialisée et optimisée pour des tables d'association dont les clefs sont des valeurs
d'un même type énuméré.
158
Le paquetage
XIV -
java.lang
XIV
Le paquetage java.lang 159
La classe Math 160
La classe StrictMath 161
La classe System 161
La classe Runtime 162
La classe Process 162
Les classes « enveloppes » 162
La classe Character 163
La classe Number et ses classes filles 163
La classe Enum 164
La classe Class 164
La classe Field 165
La classe Method 166
Interfaces pré-définies à connaître 166
A. Le paquetage java.lang
Contient une trentaine de classes parmi les plus importantes de Java :
la classe « racine » : Object (cf. la classe « Object » p 134)
les classes : String, StringBuffer, StringBuilder (cf. Chaînes de caractères
p 53)
des classes essentielles : Math, System, Runtime, ClassLoader, Thread, ...
huit classes « enveloppes » permettant d'encapsuler les huit types
élémentaires dans des objets : Boolean, Character, Integer, Long, Short,
Byte, Double, Float
la classe abstraite Number (classe mère d'Integer, Double, Float, ...)
la classe abstraite Enum (classe mère des types énumérés)
des classes permettant « l'introspection » : Class, Method, Field, …
159
B. La classe Math
Constantes : Math.PI, Math.E
Calcul entre entiers (type int ou long) avec lancement d'une exception en cas de
dépassement :
addExact(), subtractExact(), multiplyExact(), ... toIntExact()
Autres fonctions :
int round(float) , long round(double) : arrondis à l'entier le plus proche
float signum(float), double signum(double) : selon le signe, retourne -1.0
, 0.0 ou 1.0
abs(a), min(a,b), max(a,b)
pour a et b : int, long, float ou double
double random() : nombre compris dans l'intervalle [ 0.0 ... 1.0 [ et tiré, par
défaut, d'une série pseudo-aléatoire nouvelle à chaque exécution du
programme19
NOTA-BENE : toutes les méthodes de la classe Math sont statiques (elles s'invoquent
en les préfixant par le nom de la classe : Math.sin(x), Math.sqrt(y), ...)
Complément : Arrondis
Plusieurs fonctions permettent d'arrondir une valeur flottante :
ceil(x) : arrondi à l'entier supérieur ou égal (sous forme de double)
floor(x) : arrondi à l'entier inférieur ou égal (sous forme de double)
rint(x) : arrondi à l'entier le plus proche (sous forme de double)
round(x) : arrondi à l'entier le plus proche (sous forme d'entier)
(int) x : conversion explicite en entier (consiste à supprimer tout ce qui suit
la virgule)
EXEMPLE :
double x = -5.75;
double a = Math.ceil(x); // a vaut -5.0
double b = Math.floor(x); // b vaut -6.0
double c = Math.rint(x); // c vaut -6.0
int m = Math.round(x); // m vaut -6
int n = (int) x; // n vaut -5
Remarque
Ne pas confondre la classe Math (du paquetage java.lang) et le paquetage
java.math (cf. La classe Number et ses classes filles p 163).
Les fonctions dans la classe Math utilisent autant que possible les routines
19 - Pour la génération de nombres pseudo-aléatoires, voir aussi la classe java.util.Random.
160
Le paquetage java.lang
C. La classe StrictMath
StrictMath est identique à la classe Math en termes de fonctionnalités, mais avec
des caractéristiques différentes en termes de performances et de portabilité :
utilise des algorithmes standards définis dans la bibliothèque mathématique
fdlibm « Freely Distributable Math Library »
résultats des calculs strictement identiques quelque soit le matériel utilisé
performances possiblement inférieures comparées à celles de la classe Math
(lorsque le hardware utilisé fournit des routines optimisées).
Conseil
Si la vitesse est primordiale utiliser la classe Math
Si la portabilité des résultats des calculs est essentielle utiliser la classe
StrictMath.
Remarque
Selon les machines il est tout à fait possible qu'une partie (voire la totalité) des
méthodes des classes Math et StrictMath retournent exactement les mêmes
résultats.
D. La classe System
La classe System contient beaucoup de choses très utiles :
lancement forcé du Garbage Collector : System.gc()
ordre de fin d'exécution : System.exit(int status)
accès aux variables d'environnement : String System.getProperty(Sring
name)...
copie rapide de tableau : System.arraycopy(src, deb, dest, debD, len)
entrée-sorties standards : InputStream System.in, PrintStream System.out
et System.err
redirection des I/O : System.setIn(InputStream), ...
réglage sécurité : System.setSecurityManager(SecurityManager)
heure (en ms depuis 1/1/1970) : long System.currentTimeMillis()
161
E. La classe Runtime
La classe Runtime est instanciée une fois (et une seule) dans chaque programme Java
s'exécutant.
Principales méthodes :
récupération d'une instance correspondant au programme courant :
Runtime.getRuntime()
lancement de programme externe (dans un process séparé) : Process
exec(String commande)
exemple : Runtime.getRuntime().exec("ls -l *.c");
bilan sur l'utilisation de la mémoire : long freeMemory() et totalMemory()
F. La classe Process
La classe abstraite Process permet de gérer les programmes externes lancés en tant
que processus séparés vua la méthode exec() (cd. classe Runtime) :
attente de fin et récupération du status : int waitFor()
suppression du process : destroy()
connexion avec les I/O standard :
- InputStream getInputStream() : récupère la sortie standard (pour lire
dessus)
- OutputStream getOutputStream() : permet de se connecter à l'entrée
standard du process (pour écrire des choses dessus)
Remarque
Les conversions dans les deux sens entre chaque type primitif et sa classe
« enveloppe » se font automatiquement :
Integer objEntier = 4;
// OK : équivalent de = new Integer(4);
162
Le paquetage java.lang
H. La classe Character
Character est la classe « enveloppe » du type primitif char :
ne contient quasiment que des fonctions (méthodes statiques)
test de la nature d'un caractère :
- boolean Character.isLetter(char),
- Character.isDigit(char),
- Character.isWhiteSpace(char),
- ...
Accès au type précis d'un caractère :
- int Character.getType(char ch) renvoie un identifiant parmi :
Character.LOWERCASE_LETTER, Character.DECIMAL_DIGIT_NUMBER, ...
changement de casse :
- char Character.toLowerCase(char), ...
...
163
Complément : le paquetage java.math
Deux classes du paquetage java.math héritent également de la classe Number :
BigInteger : entiers en précision arbitraire, nombreuses fonctions disponibles
dont certaines particulièrement pertinentes en cryptographie :
isProbablePrime(), modInverse(), ...
BigDecimal : chiffres décimaux de très grande précision, gestion fine des
arrondis, possibilité de contrôler la précision des calculs20.
NOTA-BENE : comme pour la classe String, les instances de ces deux classes sont
immuables (une fois crée un objet de type BigInteger ne peut pas être modifié).
Outre ces deux classes, java.math inclut MathContext pour spécifier la précision des
calculs et les modalités d'arrondis dans le contexte de la classe BigDecimal.
J. La classe Enum
Enum est la classe abstraite ancêtre de tous les types énumérés (i.e. définis avec le
mot-clef enum).
Enum implante l'interface de comparaison Comparable de sorte que toute valeur d'un
type énuméré est automatiquement comparable à toute autre valeur d'un même type
énuméré ; l'ordre « naturel » utilisé par la méthode compareTo(Enum autre) est
l'ordre de déclaration des constantes dans le type énuméré.
K. La classe Class
La classe « Class » contient la représentation abstraite des classes, interfaces et
tableaux :
obtention d'une instance de la classe Class :
- via une instance : o.getClass()
- ou par le nom : Class.forName("NomCompletClasse")
littéraux : NomClasse.class
(ex: String.class désigne la classe String)
instanciation : Object newInstance()
exploration des membres de la classe :
- Method[] getDeclaredMethods()
- Field[] getDeclaredFields()
20 - Contrôler finement la précision des calculs et des arrondis et particulièrement utile en finance lorsqu'il
s'agit de manipuler des valeurs monétaires ; on pourra donc utiliser des instance de BigDecimal plutôt que
des long pour représenter des montants exprimées dans une devise donnée (les types float et double
sont à proscrire car le manque de précision des calculs rend très difficile l'obtention de résultats
systématiquement juste ─ au centime près ─ ce qui est bien sur essentiel dans un contexte bancaire ou
autre).
164
Le paquetage java.lang
- Constructor[] getDeclaredConstructors()
- Class[] getInterfaces()
- Class getSuperClass()
- ...
recherche d'un membre donné par son nom :
Method getMethod(String), Field getField(String), ...
informations sur la classe :
- nom complet : String getName()
- toString() : idem, précédé de « class » ou « interface » selon les cas
- boolean isInterface()
- boolean isArray()
- boolean isPrimitive()
- int getModifiers() : retourne un « masque » de la forme
Modifier.PUBLIC|Modifier.STATIC...
- type des éléments (pour tableaux seulement) : Class getComponentType()
test d'appartenance d'un objet à la classe (instanceof dynamique) : boolean
isInstance(Object)
accès aux annotations éventuelles (cf. Annotations p 177) :
- Annotation[] getAnnotations()
Définition : métaclasse
En termes de langages objets, on appelle couramment « métaclasse » une classe
permettant de représenter le concept de classe au sein du langage.
Tous les langages objets ne comporte pas cette notion, et quand elle existe, elle peut
s'incarner de différentes manières offrant plus ou moins de possibilités au
programmeur.
L'un des intérêts des métaclasses est de permettre l'introspection (cf. Introspection p
137).
L. La classe Field
La classe Field contient la représentation abstraite des attributs :
implante l'interface Member :
- String getName()
- int getModifiers()
- Class getDeclaringClass()
autres méthodes :
- set(Object instance, Object valeur)
- void Object get(Object instance)
- Class getType()
(renvoie instances spéciales int.class, double.class, boolean.class,... si
type primitif)
- Annotation[] getAnnotations()
165
M. La classe Method
La classe Method contient la représentation abstraite des attributs :
implante l'interface Member Field (cf. La classe Field p 165)
autres méthodes :
- Class[] getParameterType()
- Class getReturnType()
- Object invoke(Object instance, Object[] args)
- Annotation[] getAnnotations()
21 - C'est-à-dire les instruction de type for (item : séquence) { ... } (cf. Boucles d'itération
« simplifiées » p 40).
166
Autres classes et
XV -
interfaces à
connaître XV
A. Le paquetage java.util
Le paquetage java.util contient beaucoup de classes relativement importantes :
classes et interfaces liées aux « collections » (cf. Introduction p 149)
interface Formattable, classes Formatter, .. (cf. Entrées-sorties p 42)
classes Scanner
classe Random
classe Objects
classes Locale, ResourceBundle, ...
classe Currency
classes Calendar, Date, Timer, TimeZone, ...
interface Observable et classe Observer
...
Remarque
Depuis la version 1.8 de Java 1.8, le paquetage java.time fournit un ensemble de
classes à la fois pratique et très complet pour gérer tous les aspects liés au temps
(instants, durées, temps universel, temps local, calendriers alternatifs, etc.)
Ces classes ne sont pas détaillées dans ce document ; si besoin penser à consulter le
tutoriel d'Oracle22 qui comporte un sentier intitulé « Date-Time APIs ».
22 - http://docs.oracle.com/javase/tutorial/
167
B. Les classes Scanner et Pattern
La classe Scanner permet de « parser » (en français : décortiquer ou « analyser
syntaxiquement ») tout ce qui est « Readable23 » (flux, Strings, etc.) :
import java.util.Scanner;
// . . .
String tst = "bleu 12 rouge 1,618";
Scanner sc = new Scanner(tst);
String s = sc.next(); // s vaut "bleu"
int k = sc.nextInt(); // k vaut 12
double x = sc.nextDouble(); // InputMismatchException !
// . . .
Scanner sc2 = new Scanner(System.in);
if (sc2.hasNextDouble()) {
double y = sc2.nextDouble();
// . . .
}
Exemples :
7.[xy] représente l'ensemble des chaînes composées de trois caractères,
commençant par le chiffre 7 et finissant par une lettre x ou y ;
[a-zA-Z]* représente l'ensemble des chaînes composées exclusivement de
lettres (minuscules ou majuscules de l'alphabet latin).
168
Autres classes et interfaces à connaître
169
Exemple : Lecture depuis le clavier avec utilisation d'un
pattern et gestion d'erreurs
Scanner sc = new Scanner(System.in);
try {
String s1 = sc.next(p);
// accepte uniquement Y ou y
}
catch(InputMismatchException e) {
System.out.println("Y ou y attendu");
}
Conseil
L'ensemble formé des classes Scanner et Pattern constitue l'outil à utiliser en priorité
chaque fois qu'il faut analyser des données en mode texte dont la structure n'est pas
complétement triviale, et ce, quelque soit la source de ces données (fichier, chaîne de
caractères, socket, ...)
Toutefois, comme pour tout aspect un peu complexe de Java, il ne faut pas chercher
à tout découvrir – et encore moins tout mémoriser – par avance.
Mieux vaut adopter une démarche pragmatique consistant à bien mémoriser les
principes puis, lorsqu'on en a besoin, rechercher les détails dans la documentation de
référence (qu'il convient d'avoir toujours accessible, soit via Internet, soit en ayant
une copie physique sur son disque dur). Tout aussi utile : penser à rechercher des
exemples dans une base telle que http://www.java2s.com (généralement plus
efficace que de chercher un exemple avec Google).
C. La classe Random
Comparée à la méthode Math.random()26, la classe Random permet :
de contrôler le caractère reproductible ou pas de la séquence générée ;
d'obtenir des valeurs flottantes avec une distribution de type gaussienne plutôt
qu'uniforme ;
de générer autre chose que des double (e.g. des boolean, int, long, byte...).
Exemple
import java.util.Random;
// . . .
26 - RAPPEL : Math.random() retourne un double dans l'intervalle [ 0.0 ... 1.0 [ ; des appels successifs
produisent une série nouvelle à chaque exécution du programme ; la distribution des valeurs est
« approximativement uniforme »
cette fonction suffit tant qu'il s'agit de générer des double sans autre contrainte spécifique (caractère
reproductible de la séquence générée, caractère « sécurisé » ou pas, contextes multi-threadé, ...)
170
Autres classes et interfaces à connaître
int x = r.nextInt();
// x entier quelconque (2^32 valeurs possibles toutes équiprobables)
int y = r.nextInt(200);
// y dans l'intervalle [ 0 ... 200 [
boolean b = r.nextBoolean();
double d1 = r.nextDouble();
// d1 dans l'intervalle [ 0.0 ... 1.0 [
double d2 = r.nextGaussian();
// d2 double (valeur moyenne = 0.0 et déviation standard = 1)
D. La classe Objects
La classe Objects28 contient une série de méthodes statiques utilitaires relatives
aux objets.
Les méthodes suivantes sont de simples variantes des méthodes équivalents de la
classe Object :
compare(), equals(), deepEquals(), ...
[ elles permettent juste d'écrire Objects.equals(o1, o2) à la place de
o1.equals(o2) ]
D'autres méthodes de la classe Objects sont par contre fort pratiques lorsqu'une
171
variable de type référence peut (ou pas) contenir une référence nulle :
hashCode(Object o)
retourne o.hashCode() ssi o est non-nul, et null sinon.
toString(Object o, String msg)
retourne o.toString() ssi o est non-nul, et la chaîne msg sinon.
Rappel
Lorsqu'une référence o est nulle, une exception est lancée si on exécute
o.nomDeMethode() ou o.nomAttribut.
E. Localisation et internationalisation
Plusieurs classes java sont disponibles pour faciliter « l'internationalisation » des
programmes :
classe Locale : permet l'identification d'une localisation en termes de langue et
de région (utilise les normes ISO 639 et 15924 pour les langues et les
alphabets et ISO 3166 pour les régions) ;
classe ResourceBundle : permet d'isoler et gérer les données devant être
localisées ;
classe Formatter (cf. Entrées-sorties p 42) : permet l'affichage des nombres,
dates, etc. selon la localisation ;
classe Scanner (cf. Les classes Scanner et Pattern p 168) : permet la saisie des
nombres selon la localisation ;
classe Currency : permet la manipulation des symboles correspondants aux
différentes devises (selon la norme internationale ISO 421729) ;
...
29 - La norme ISO 4217 définit une correspondance entre les noms, codes, et symboles des différentes
monnaies. Ainsi, le code numérique pour l'Euro est 978, le code sous forme de chaîne est "EUR" et le
symbole corespondant '€'.
172
Autres classes et interfaces à connaître
Conseil
Penser au tutoriel d'Oracle30 (sentier « Internationalization ») pour approfondir ces
notions de localisation et d'internationalisation, et apprendre comment les mettre en
œuvre en Java avec quelques exemples.
30 - http://docs.oracle.com/javase/tutorial/
173
Documentation
XVI -
automatique
(javadoc) XVI
Mise en œuvre :
Nécessite d'insérer dans le code des commentaires spécifiques selon la
syntaxe :
/** bla-bla ...
(sur une ou plusieurs lignes)
*/
javadoc NomClasse.java produit automatiquement des fichiers HTML
décrivant la classe et intégrant ces commentaires
racine = index.html
Remarque
Les commentaires javadoc se placent juste avant les déclarations de :
- packages
- classes
- interfaces
- méthodes
- attributs
Par défaut, seuls les éléments publics et protégés apparaissent (car ce sont les
seuls qu'ont à connaître les utilisateurs de la classe)
175
Attention
Javadoc est conçu pour documenter des packages/classes/interfaces Java afin de
faciliter leur utilisation lors de l'écriture de programmes.
Le lecteur de cette documentation est donc, typiquement, un programmeur qui
souhaite utiliser un code Java pré-existant le plus rapidement possible (sans
forcément en connaître tous les détails).
Javadoc n'est pas conçu pour :
documenter les détails d'implantation à l'intérieur des méthodes, ou les choix
techniques effectués lors de la mise au point du programme utiliser pour cela
les commentaires ordinaires de Java ;
produire un mode d'emploi du programme à l'intention de l'utilisateur final
pour cela, joindre une notice au programme et/ou prévoir une page d'aide dans
l'IHM.
176
XVII - Annotations
XVII
Annotations 177
Annotations standards (prédéfinies) en Java 178
Définition d'annotations 178
Le « checker framework » 179
A. Annotations
Définition
Métadonnées attachées à un élément du code source (se placent juste avant
l'élément annoté).
Ces métadonnées peuvent être exploitées :
lors de la compilation (vérifications sémantiques, optimisations, ...) ;
lors de l'exécution par la machine virtuelle Java (optimisations) ;
lors de l'exécution par le code (via l'introspection) ;
par des outils externes (javadoc, outils d'analyses, d'optimisation, ...)
Remarque
Tout ou presque peut être annoté dans un code java (déclarations, affectations,
invocations de méthodes, ...)
Syntaxe
1. annotations marqueurs : @TypeDAnnotation
2. annotations paramétrées : @TypeDAnnotation("valeur")
3. annotations multi-paramétrées : @TypeDAnnotation(attribut1 = "valeur1",
attribut2 = "valeur2", ...)
NOTA-BENE : chaque paramètre a un type (int, double, boolean, String, tableau, ...)
Exemple
class Mere {
public void demarrer() { ... }
public boolean ajuster(double[]) { ... }
}
177
// erreur de compilation « grâce » à l'annotation !
// ...
@Override
public boolean ajuster(double) { ... }
// erreur de compilation « grâce » à l'annotation !
}
Usages principaux
permet de spécifier plus formellement certains aspects du code
typage plus rigoureux et/ou plus précis, possibilité de vérifications
automatiques additionnelles ;
code plus fiable ;
permet d'expliciter l'intention du programmeur
code plus lisible, plus facile à maintenir ;
permet d'inclure dans le code des directives destinées au compilateur, à la JVM
ou à des outils manipulant le code source ou le bytecode.
C. Définition d'annotations
Possibilité de définir ses propres annotations
accessibles lors de l'exécution (introspection) ou depuis des outils externes.
// .......
178
Annotations
D. Le « checker framework »
Permet d'étendre l'ensemble des vérifications effectuées sur le code par rapport à ce
que réalise le compilateur Java.
Intérêt :
détecter/prévenir de nombreux bugs ;
expliciter avec précision l'intention du programmeur.
Mise en œuvre sous Java 8 : non fourni en standard, à télécharger/installer ; s'utilise
ensuite sous forme d'un « plugin » dans le compilateur java (disponible pour javac,
Eclipse et la plupart des compilateurs Java)
31 - L'utilisation systématique de telles annotations est une alternative à l'usage de la notation /** ...
*/ ; elle peut permettre de structurer/formaliser le contenu des commentaires produits par javadoc ; elle
permet en outre leur inclusion dans le bytecode produit en cas d'utilisation combinée de @Documented et
@Retention(RetentionPolicy.RUNTIME).
179
Graphisme et
XVIII -
Interface Homme-
Machine (IHM) XVIII
Introduction 181
Composants prédéfinis d'AWT 182
Utilisation des conteneurs 184
Gestionnaires de présentation 184
Événements et programmation événementielle 186
Dessiner 192
Couleurs 193
Polices de caractères 194
Images 194
Dimensions de l'écran et des composants 195
Applet vs application 196
Ecrire une applet 196
Ecrire une application graphique 201
Swing 203
Pour aller plus loin... 205
A. Introduction
Deux sortes de programmes graphiques en Java
1. Les appliquettes (Applet)
- Elles peuvent fonctionner par le truchement d'un navigateur : Firefox, IE,
Safari, Chrome, ...
- ou via un programme spécifique : appletviewer
2. Les applications indépendantes
- Lancées exactement comme n'importe quelle application (non graphique)
181
Ce qu'il faut pour créer une IHM
Des composants graphiques élémentaires
Un (ou des) conteneur(s)
Un gestionnaire de présentation associé à chaque conteneur
(éventuellement par défaut)
Si besoin, des dessins (points, courbes, images, ...)
Ajouter les composants graphiques au(x) conteneur(s) par l'intermédiaire du
gestionnaire de présentation
Ecouter les événements associés aux composants graphiques (clavier, souris,
focus, choix, ...)
NOTA-BENE : Eclipse est écrit en Java avec une IHM programmée avec le package
SWT.
182
Graphisme et Interface Homme-Machine (IHM)
Frame fenêtre
Menu menu
183
Nom Fonction
D. Gestionnaires de présentation
Principe
La disposition des composants dans un conteneur est assurée par un «
gestionnaire de présentation » ou « Layout Manager »
Chaque conteneur a son propre LayoutManager qui place automatiquement les
184
Graphisme et Interface Homme-Machine (IHM)
Remarque
L'interface gestionnaire de présentation s'appelle LayoutManager, mais les
méthodes se nomment setLayout(...) et getLayout() [sans Manager après
Layout].
Il est possible de spécifier un gestionnaire de présentation lors de la création
d'un Panel :
Panel c = new Panel(new GridLayout(2,4));
(pour un Frame ce n'est pas possible, il faut impérativement le créer puis
invoquer setLayout()).
FlowLayout
Fonctionnement du FlowLayout : de gauche à droite puis de haut en bas en
centrant, taille des composants fixe
BorderLayout
Fonctionnement du BorderLayout : 5 places prédéfinies, tailles ajustées selon la «
région »
GridLayout
Fonctionnement du GridLayout : Tableau en lignes, colonnes. Ajout par ligne puis
par colonne
185
Remarque
Il existe d'autres gestionnaires de présentation pré-définis dans AWT : CardLayout,
GridBagLayout, ...
Il en existe d'autres encore dans Swing (voir plus loin).
186
Graphisme et Interface Homme-Machine (IHM)
Catégories d'événements
Les événements AWT sont groupés en catégories
Chaque catégorie correspond à une classe prédéfinie en Java (et héritant d'AWTEvent)
Le nom de l'interface à implanter pour l'écoute = catégorie + « Listener »
Le nom des méthodes associées commence par le nom de la catégorie
Le paramètre passé à chaque méthode est un événement dont le type est une
classe de nom = catégorie + « Event »
187
Classification des événements par catégories vs
composants
188
Graphisme et Interface Homme-Machine (IHM)
c.addActionListener(o), ...)
quand un événement se produit sur le composant c, il est transmis à tous les
récepteurs enregistrés chez lui pour ce type d'événement, cela par appel de sa
méthode correspondante (e.g., pour appui sur bouton souris,
o.mousePressed(evt) pour tous les o concernés, et où evt est l'événement)
Classes « adaptateurs »
Pour chaque interface XxxListener est prédéfinie aussi une classe XxxAdapter qui
implante l'interface avec des méthodes toutes vides
Intérêt : un objet intéressé par une seule sous-classe d'événement (e.g. clic souris),
peut être défini comme héritant de la classe adaptateur correspondante, et du coup
n'avoir à redéfinir que la méthode souhaitée (e.g. hériter de la classe MouseAdapter
en redéfinissant uniquement mouseClicked())
NOTA-BENE : cette technique n'est possible que pour les classes qui n'héritent pas
d'une autre classe !
189
Où écrire une méthode de gestion d'événements ?
Plusieurs possibilités :
1. faire implanter l'interface récepteur adéquate par l'applet, la fenêtre principale,
ou la principale classe de l'interface graphique : efficace dans les cas les plus
simples
2. définir une classe dédiée qui implante l'interface récepteur adéquate (ou mieux,
qui hérite de l'adaptateur ad hoc) : efficace mais multiplie le nombre de classes
3. créer « à la volée » (juste au moment de l'enregistrer comme écouteur) une
classe qui implante l'interface récepteur adéquate : efficace mais réduit la
lisibilité du code
190
Graphisme et Interface Homme-Machine (IHM)
public FermezMoi() {
super(TITRE); // invoque le constructeur de la classe mère
lab = new Label("Fermez la fenêtre pour sortir du programme !");
add(BorderLayout.NORTH, lab);
// Désignation d'une instance de la classe EcouteurFenetre
// pour écouter les évts « Window » sur la Frame :
addWindowListener(new EcouteurFenetre());
// ...
}
public CliquezDedans() {
super(TITRE); // invoque le constructeur de la classe mère
texte = new TextArea(msg);
add(BorderLayout.NORTH, texte);
texte.addMouseListener (
// Création « à la volée » d'un écouteur des clics souris :
// on crée une instance de classe anonyme, héritant de
// MouseAdapter pour éviter d'écrire les méthodes non
191
// pertinentes ici
new MouseAdapter () {
public void mouseClicked (MouseEvent e) {
String s = String.format( "%s\n x=%d ; y=%d",
msg, e.getX(),e.getY() );
texte.setText(s);
}
}
);
// ...
}
F. Dessiner
Les méthodes qui permettent de dessiner utilisent un « contexte graphique »
(instance d'une sous-classe de la classe abstraite Graphics) propre au composant
dans lequel on dessine (Canvas, Panel, Applet en tant que Panel, Frame,...)
Ces méthodes sont généralement invoquées depuis le corps de la méthode
paint(Graphics g)
Principales méthodes disponibles en Java pour dessiner :
g.drawLine(int x, int y, int x2, int y2) : dessine une ligne entre (x,
y) et (x2, y2)
g.drawRect(int x, int y, int w, int h) : dessine un contour
rectangulaire de dimension w, h à partir de (x, y)
g.fillRect (int x, int y, int w, int h): dessine un rectangle plein
[ autres formes : RoundRect, 3DRect, Arc, Oval, Polygon, etc... ]
g.drawString(String s, int x, int y) : dessine la chaîne s en (x, y)
g.drawImage(Image im, int x, int y, this) : dessine l'image im à partir
de (x, y)
...
Remarque
Repère utilisé par ces fonctions : origine en haut à gauche du composant avec
l'axe des abscisses orientée vers la droite et celui des ordonnées vers le bas
Angles : exprimés en degrés
Arcs et ovales : définis par leur rectangle englobant
192
Graphisme et Interface Homme-Machine (IHM)
Une variable « g » de type Graphics doit donc être perçue comme un paquet de
paramètres implicites, autrement dit un ensemble de valeurs prises en compte lors
de chaque appel d'une méthode de la série drawXXX() ou fillXXX()et qui définissent
l'endroit où on dessine, les couleurs à utiliser, etc.
Lorsque nécessaire on peut modifier tout ou partie de ces paramètres par appel des
méthodes setXXX() de la classe Graphics (voir exemples ci-après). La modification
affectera toutes les opérations de dessins effectuées postérieurement à cet appel.
Si besoin, on peut dupliquer un contexte graphique par appel de : Graphics g2 =
g.create(). On peut ensuite positionner des valeurs différentes dans g et g2 (par
exemple pour les choix de couleurs) ce qui permet ensuite de basculer entre plusieurs
« styles » au fil d'un dessin complexe : il suffira d'invoquer selon les besoins
g.drawXXX() ou g2.drawXXX() pour dessiner dans l'un ou l'autre style (mais vers une
même destination).
G. Couleurs
Couleur courante
Les dessins sur un Graphics g se font avec la « couleur courante » :
- pour consulter : Color g.getColor()
- pour changer : void g.setColor(Color c)
La classe Color
Constructeur : Color(int r, int v, int b)
avec 0 <= r,v,b <= 255
Couleurs usuelles constantes de classe : Color.BLACK, Color.RED,
Color.BLUE, ...
Remarque
Beaucoup d'autres constructeurs et méthodes sont disponibles dans la classe
Color (voir documentation en-ligne).
Si besoin de davantage de précision dans les nuances de couleurs, le package
java.awt.color permet la manipulation de couleurs conformément aux
spécifications de l'ICC32 (norme ISO 15076-1).
193
H. Polices de caractères
Fonte courante
Chaque Graphics et Component a une « fonte courante » consultable/modifiable par
les méthodes :
Font getFont()
setFont(Font)
Fontes disponibles
Polices disponibles sur toutes plates-formes : Serif, SansSerif, Monospaced, Dialog et
DialogInput
Liste complète des polices disponibles (spécifique à la machine utilisée) par appel à :
String[] Toolkit.getDefaultToolkit().getFontList()
La classe Font
Constructeur : Font(String nom, int style, int taille)
où nom est du type Helvetica, style est une des constantes Font.BOLD,
Font.ITALIC, Font.PLAIN (ou une combinaison par |), et taille est la dimension en «
points »
Tests de disponibilité effective : boolean canDisplay(char), int
canDisplayUpTo(String), ...
Remarque
Beaucoup d'autres constructeurs et méthodes sont disponibles dans la classe
Font (voir documentation en-ligne).
Si besoin de davantage de puissance dans la manipulation des polices de
caractères (métrique, ...) package java.awt.font
I. Images
Classe Image
Chargement par la méthode getImage(url_base,name) de Applet, ou bien, hors des
applets, par la méthode getImage(name) de la classe Toolkit (on obtient un Toolkit
par getToolkit(), ou bien par Toolkit.getDefaultToolkit())
Affichage dans un Graphics : boolean drawImage(Image i, int x, int y,
ImageObserver o)
Quelques méthodes de la classe Image :
int getHeight(ImageObserver)
int getWidth(ImageObserver)
Image getScaledInstance(int l, int h, int method)
Graphics getGraphics() pour pouvoir dessiner dessus
Remarque
Formats d'images supportés en standard : BMP, GIF, JPEG, PNG et WBMP
A savoir :
- getImage() rend toujours la main immédiatement (le chargement effectif
194
Graphisme et Interface Homme-Machine (IHM)
Exemple :
Pour connaître les dimensions d'un composant (en fait, de son rectangle englobant) :
Dimension getSize()
int getWidth() et int getHeight()
195
Pour modifier les dimensions d'un composant :
setSize(Dimension d)
setMinimumSize(Dimension d)
setMaximumSize(Dimension d)
setPreferedSize(Dimension d)
Attention
Sauf cas très particuliers, ne pas invoquer setSize() sur les composants dont
la taille est gérée par un gestionnaire de présentation (LayoutManager).
L'effet des méthodes setSize(), setMinimumSize(), ... n'est absolument pas
garanti : en pratique, il s'agit d'une requête émise par le programmeur et qui
ne sera satisfaite que dans la mesure du possible par le gestionnaire de
géométrie et le système d'exploitation.
K. Applet vs application
Une applet étant un code téléchargé sur le réseau puis exécuté au sein d'un
navigateur, Java impose un certain nombre de restrictions de sécurité ( accès aux
fichiers, connexions réseau, lancement d'autres programmes, etc...) => certaines
applications ne peuvent pas être des applets
Une applet nécessite de créer un fichier HTML (balise <APPLET>) en plus du fichier
.java
Applet Application
196
Graphisme et Interface Homme-Machine (IHM)
NOTA-BENE : pas de main (une applet n'est pas un programme Java ordinaire)
<HTML>
<HEAD>
<TITLE> Exemple </TITLE>
</HEAD>
<BODY>
<APPLET code=MonApplet.class width=800 height =300>
<br>
Le navigateur n'a pas pu charger une applet !
</APPLET>
</BODY>
</HTML>
197
NOTA-BENE : lors du chargement de l'applet, le navigateur (ou appletviewer) :
1. rapatrie le fichier .class ;
2. charge la classe dans la JVM ;
3. crée une instance de cette classe ;
4. lui applique init(), puis start() ;
5. lui applique update() quand nécessaire.
Complément
En théorie, la méthode start() (resp. stop()) est exécutée à chaque fois que l'applet
est exposée ou réexposée (resp. masquée) ; par exemple lors des navigation avant
arrière, changement d'onglet etc...
En pratique, les navigateurs usuels ne respectent pas forcément cette « règle du jeu
» définie par les auteurs de Java ce qui a pour effet que ces méthodes sont invoquées
moins souvent qu'elles devaient l'être.
198
Graphisme et Interface Homme-Machine (IHM)
199
Exemple : Une applet animée simple (sans thread) :
affiche un disque dont le rayon varie au fil du temps
import java.applet.*;
import java.awt.*;
200
Graphisme et Interface Homme-Machine (IHM)
dr* = -1;
}
r += dr ;
}
try { Thread.sleep (dt); }
catch (InterruptedException e) {}
repaint () ;
}
}
En pratique
1. Créer une fenêtre principale :
- créer une classe dérivant par exemple du conteneur Frame (ou Jframe en
Swing)
- y définir une méthode main qui instanciera cette classe (création d'un objet
de la cette classe principale = création de la fenêtre principale de l'IHM)
2. Conteneurs et composants :
- déclarer les autres composants graphiques comme attributs de cette classe
- dans le constructeur, créer les composants graphiques et les ajouter au(x)
conteneurs (en particulier le conteneur Frame correspondant à l'application
elle-même)
- si besoin, modifier les layoutManager par défaut pour obtenir la
présentation voulue
201
(éléments à y dessiner par l'une des méthodes de la série g.drawXXX())
- invoquer la méthode repaint() pour rafraichir les dessins lorsque nécessaire
// constructeur de ma classe :
public TestBouton(String titre) {
super(titre); // invoque le constructeur de la classe mère
b = new Button ("Cliquer ici !"); // crée le bouton
b.addActionListener (new EcouteurBouton()); //écouter
add(BorderLayout.NORTH, b); // ajoute le bouton b à la Frame
pack(); // agence les composants de la Frame
setVisible(true); //rend visible la Frame
}
Remarque
On aurait pu ne pas créer cette classe et coder l'écoute du bouton dans la classe
TestBouton. Pour cela, il aurait fallu que TestBouton implante l'interface
ActionListener et qu'on écrive la méthode ActionPerformed ci-dessus dans la
classe TestBouton. L'écoute serait déclarée comme ceci :
b.addActionListener(this)
202
Graphisme et Interface Homme-Machine (IHM)
N. Swing
Introduction
Swing = package standard Java (import javax.swing) = complément et/ou alternative
à AWT :
permet la réalisation d'IHMs plus sophistiquées qu'avec AWT seul
modèle d'événements commun avec AWT (mais avec des types d'événements
additionnels)
203
Composants Swing ayant leur équivalent en AWT
La plupart des composants graphiques usuels d'AWT ont leur équivalent Swing, qui a
le même nom avec un J devant :
JComponent : ancêtre de tous les composants Swing (sauf JApplet, JDialog,
JFrame)
JButton : bouton usuel
JCheckBox : cases à cocher « indépendantes »
JLabel : texte affiché par le programme
JList : liste « scrollable » de choix
JTextField, JTextArea : pour entrer du texte
JPanel : conteneur de base pour grouper des composants
JDialog : fenêtre secondaire (« esclave »)
JMenu, JMenuBar, JMenuItem, JPopupMenu : pour les menus
JScrollBar : barre de défilement
JScrollPane : pour donner une vue « scrollable » d'un seul composant
JWindow : fenêtre sans barre de titre ni bordure
Ces équivalents Swing ont généralement plus de fonctionnalités que leurs homologues
AWT
Conteneurs :
JOptionPane : boites de dialogue créables et affichables par un simple appel
de fonction :
204
Graphisme et Interface Homme-Machine (IHM)
JOptionPane.showMessageDialog(...);
message + 1 bouton OK
int r=JOptionPane.showConfirmDialog(...);
message + boutons style Oui / Non / Annuler
int r=JOptionPane.showOptionDialog(...);
message + choix de boutons
String s=JOptionPane.showInputDialog(...);
message + zone saisie texte + boutons OK / Annuler
JSplitPane : pour afficher deux composants côte à côte (ou l'un au-dessus de
l'autre), et avec ligne de séparation déplaçable par l'utilisateur
JTabbedPane : regroupement de plusieurs composants accessibles via des
onglets
JFileChooser : fenêtre de sélection de fichier sorte de FileDialog de AWT
mais en mieux)
JInternalFrame : pour disposer de sous-fenêtres dans une fenêtre (sortes de
« bureaux virtuels »)
Conseil
Penser à consulter la documentation en-ligne des classes Java, rechercher
des exemples, .... Parmi les nombreux tutoriaux disponibles en-ligne, celui
d'Oracle33 comporte par exemple deux sentiers très complets intitulés « Creating a
GUI With JFC/Swing » et « Creating a JavaFX GUI ».
33 - http://docs.oracle.com/javase/tutorial/
205
206
Processus légers
XIX -
(threads)
XIX
A. Programmation multi-threadée
Un « thread » ou « processus léger » est une séquence d'instructions
exécutées séquentiellement
207
Remarque
Un programme « normal » sans appel explicite à des instructions qui créent des
threads :
s'exécute dans un seul thread qui va « dérouler » les instructions écrites par le
programmeur en commençant par la première ligne de la fonction main()
mais d'autres threads peuvent avoir été lancés par Java pour optimiser de manière
transparente pour le programmeur certaines tâches dans la machine virtuelle
B. Thread
Un thread Java est un fil d'exécution interne au programme, représenté par un objet
(instance de la classe Thread) qui possede :
une instruction courante
un état (actif, inactif, en attente, ...)
un nom (facultatif)
Attention
Pour qu'un thread s'exécute, il faut
1. le créer ;
2. ensuite, le démarrer
C. Classe Thread
Démarrage par invocation de la méthode start() pré-programmée dans la
classe Thread
start() fait appel à la méthode run()
Arret quand on sort de run() par fin normale ou exception
D. Création de threads
Deux bonnes manieres pour créer un thread :
soit creer une classe derivee de Thread, et redéfinir sa méthode run()
ou bien, creer une classe implantant l'interface Runnable, donc ayant une
méthode run(), puis créer un Thread avec ce Runnable en parametre du
constructeur
208
Processus légers (threads)
Exemple :
Class Test implements Runnable {
private Thread t;
private boolean suspendThread=false, stopThread=false;
public void run() {
while ( !stopThread ) {
if ( !suspendThread ) {
// ... (tâche de fond du thread)
}
}
}
public static void main(String[] args) {
t = new Thread(this);
t.start();
// ...
suspendThread = true; //suspension
// ...
suspendThread = false; //redemarrage
// ...
stopThread = true; //arret definitif
}
}
F. Exemple de thread
209
G. Synchronisation des données
Gestion des conflits de modification de données par verrou (« lock ») sur les
méthodes déclarées avec le mot-clé synchronized
durant toute l'exécution par un thread d'une méthode synchronisée, aucun
autre thread ne peut appeler simultanément une autre méthode synchronisée
du même objet
Possibilité de faire un « bloc synchronisé » exigeant un lock sur un objet
donné :
synchronized (obj) {
//...
}
Exemple
Exemple de bloc synchronisé :
synchronized (System.out) {
// ICI plusieurs invocations de println()
// devant impérativement s'afficher
// à la suite.
}
210
Processus légers (threads)
Remarque
Pour invoquer wait(), il faut avoir un lock sur l'objet la méthode doit être
synchronisée
La méthode notifyAll() réveille tous les threads en attente sur l'objet,
notify() en réveille au plus un (mais on ne sait pas lequel !)
On peut faire t.join(timeout) pour bloquer au maximum timeout
millisecondes
I. Blocages
La programmation avec threads nécessite de faire très attention à ce qu'aucun
blocage mutuel (ou « deadlock ») ne puisse se produire.
Méthodes à connaître :
getPriority()
setPriority(int p) avec p entre Thread.MIN_PRIORITY et
Thread.MAX_PRIORITY
211
sleep(long milliseconds) : met en sommeil le thread courant
yield() : interrompt le thread courant pour permettre à un autre de prendre
la main
K. Groupement de threads
La Classe ThreadGroup permet de regrouper des threads que l'on veut pouvoir traiter
de la même façon (par exemple les suspendre tous ensemble, modifier la priorité de
tous en même temps, …)
Conseil
Il existe beaucoup d'autres classes (et méthodes) disponibles en java pour développer
des programmes multi-threadés efficaces et fiables.
34 - http://docs.oracle.com/javase/tutorial/
212
Processus légers (threads)
qu'ils sont systématiquement mis à jour avec chaque nouvelle version du langage ─
or ce point est particulièrement important concernant les aspects concurrents du
langage qui ont tendance à évoluer plus fréquemment que le reste (introduction de
nouveaux modèles conceptuels pour la synchronisation, le positionnement des
threads sur les cœurs, etc.)
213
Programmation
XX -
réseau
XX
Paquetage java.net 215
Accès aux protocoles Internet 215
Exemple d'utilisation de la classe URL 216
Connexion réseau bas niveau 216
Exemple de Client 217
Exemple de serveur 217
Penser à utiliser la documentation 218
A. Paquetage java.net
Le package java.net permet :
la manipulation des URL
l'accès aux protocoles standards de l'Internet (http, ftp, mail, ...)
la communication inter-processus, la création d'architectures de type « clients-
serveur »
215
C. Exemple d'utilisation de la classe URL
import java.net.*;
import java.io.*;
class VisuHTML {
public static void main(String[] args) {
try {
URL url = new URL(args[0]);
URLConnection c = url.openConnection();
c.connect();
String type = c.getContentType();
if ( type.startsWith("text") ) {
InputStream in = c.getInputStream();
InputStreamReader isr = new InputStreamReader( in );
BufferedReader br = new BufferedReader( isr );
// NOTA-BENE : readLine() possible sur un BufferedReader
String ligne;
while ( (ligne=br.readLine() ) != null) {
System.out.println(ligne);
}
br.close();
}
else {
System.out.println("Fichier de type " + c.getContentType());
}
}
catch(Exception e) { System.out.println(e); }
}
}
Une « socket » = une « prise » (au sens de prise électrique) = l'extrémité d'une
connexion
216
Programmation réseau
E. Exemple de Client
import java.net.*; import java.io.*;
class ClientMiroir {
public static void main(String[] arg) {
try {
Scanner sc = new Scanner(System.in);
// ouverture socket (port=9999, host=arg[0]) :
Socket client = new Socket(arg[0], 9999);
// ouverture de deux flux sur socket :
OutputStream out = client.getOutputStream();// flux écriture
InputStream in = client.getInputStream(); // flux lecture
while (true) {
String s = sc.nextLine(); // lecture d'une ligne au clavier
out.write(s.getBytes()); // envoi des bytes au serveur
out.write('\n');
out.flush();
// lecture sur socket :
byte [] buf = new byte[1000];
in.read(buf);
s = new String(buf);
System.out.println(s); // affichage à l'écran
}
}
catch (IOException e) { System.out.println(e); }
}
}
F. Exemple de serveur
import java.util.*; import java.net.*; import java.io.*;
class ServeurMiroir {
public static void main(String[] arg) {
try {
// mise en route du serveur sur port 9999 :
ServerSocket serveur = new ServerSocket(9999);
Socket client = serveur.accept(); // attente connexion client
InputStream is = client.getInputStream(); // flux lecture
OutputStream out = client.getOutputStream();// flux ecriture
// fonctionnement du serveur :
StringBuffer buf = new StringBuffer();
do {
int c = is.read(); // lecture caractere par caractere
if (c == -1) { break; } // fin de flux
if (c != '\n') { buf.append( (char) c ); } // cas général
else { // traitement des fins de ligne sur flux lecture
buf.reverse();
out.write(buf.toString().getBytes());
out.flush();
buf = new StringBuffer();
}
} while (true);
} catch (IOException e) { System.err.println(e); }
}
}
217
G. Penser à utiliser la documentation
Conseil
Il existe beaucoup d'autres classes (et méthodes) disponibles en java pour mettre en
place des architectures distribuées, échanger des données, etc.
Penser au tutoriel d'Oracle35 sur le sujet pour approfondir ces aspects du langage (le
tutoriel d'Oracle est organisé sous forme de sentiers dont un sentier intitulé « Custom
Networking » qui permet de découvrir plus en détail les principaux éléments de java
liés à la programmation réseau.)
35 - http://docs.oracle.com/javase/tutorial/
218
Annexe : ressources
XXI -
complémentaires sur
Java XXI
Ce support de cours ne saurait remplacer un ouvrage de référence sur le langage
Java, et encore moins l'ensemble des documentations, cours et bases d'exemples
disponibles via la page du cours sur le site web de l'Ecole.
Concernant spécifiquement le langage Java, il serait vain de vouloir tout apprendre
par avance : une fois les bases du langage maîtrisés et les différents paradigmes bien
assimilés, il convient de se dire qu'étant donné la maturité du langage, tout problème
qu'on est susceptible de rencontrer avec telle ou telle classe a, très probablement, été
déjà surmonté, et largement documenté – il suffit donc de savoir trouver rapidement
les éléments de solutions nécessaires en utilisant au mieux :
1. la documentation de référence ;
2. les bases d'exemples ;
3. les tutoriaux.
Apprendre à exploiter aux mieux ces ressources est donc primordial pour
programmer efficacement.
Aussi, il importe en premier lieu de savoir quelles ressources sont disponibles, leurs
différences, et quand/comment les utiliser : c'est l'objet de cette annexe.
Documentation de référence
Diagramme cliquable en forme de table des matières (« Java Platform
Standard Edition Documentation ») 36 : donne accès à l'ensemble de la
documentation relative à l'édition de Java utilisée 37 et en particulier aux
documentations :
- des outils tels que javac, jar, javadoc, javah, ...
- des technologies de déploiement telles que Java Web Start
- des packages standards (regroupées par thèmes : Input/Output, Math,
Sound, ...)
- de la machine virtuelle
NOTA-BENE : chaque clic sur un thème, une technologie, ... ouvre une
page qui rassemble à la fois les tutoriaux et les manuels (APIs 38)
correspondants.
Conseil
Dans la mesure du possible (espace disque suffisant), il est recommandé
d'installer une copie physique de toute la documentation de référence
Java sur son disque dur afin de pouvoir y accéder sans latence, et a fortiori en
l'absence de connexion internet.
36 - Toute la documentation de référence est disponible sur le site d'Oracle à la fois en mode téléchargement
(on récupère alors un fichier compressé à installer sur son disque dur) et en mode consultation :
http://docs.oracle.com/javase
37 - J2SE dans le cadre de ce cours.
38 - API = Application Programming Interface (en français : Interface de programmation)
219
Il faut maîtriser au moins deux modes de navigation dans la
documentation de référence :
a. si on sait dans quelle classe, ou package, se trouve ce qu'on cherche il
faut partir de la page qui rassemble les manuels de toutes les APIs
standards (celle avec la liste des packages en haut à gauche et la listes des
classes et interfaces en dessous) ; il convient donc d'avoir à tout instant
cette page sous la main dans son navigateur (à ajouter à sa liste de
favoris) ;
b. sinon il faut partir de la page avec le diagramme cliquable (à ajouter aussi
à sa liste de favoris) et explorer de manière descendante les thématiques
proposées jusqu'à atteindre le tutoriel et/ou l'API recherché.
A noter pour les débutants complets : « Programmation Java pour les enfants, les
parents et les grands-parents »41 (en principe totalement inutile après ce cours mais à
conseiller, comme suggéré dans le titre, pour les enfants, cousins, neveux, grands-
parents, amis, voisins, ... qui voudraient s'initier à l'informatique à travers Java).
39 - http://jexamples.com
40 - http://code.ohloh.net/
41 - http://java.developpez.com/livres/javaEnfants
220
Annexe : ressources complémentaires sur Java
Remarque
Le site http://www.java.com (géré par Oracle) est destiné aux utilisateurs de
programmes Java : il inclut un outil pour vérifier la bonne installation de la
technologie Java sur sa machine, des conseils sur l'installation du JRE, ...
221
Annexe : ressources
XXII -
complémentaires sur
l'algorithmique XXII
Contrairement aux techniques de programmation – et a fortiori aux langages
informatiques – qui évoluent à un rythme relativement rapide, les connaissances en
algorithmique n'évoluent que lentement et s'appuient sur un socle désormais très
large et de nature pérenne, à l'image de l'algèbre élémentaire ou de la physique
classique.
Il est donc logique que les meilleures ressources pour approfondir ses connaissances
dans ce domaine soient des livres et pas des sites webs.
Parmi les meilleures ouvrages pour aller plus loin à l'issue de ce cours :
Algorithm Design par John Kleinberg & Eva Tardos, Pearson Education :
ouvrage excellent car très complet et relativement facile à lire.
The Art of Computer Programming, volumes I-IVa (également connu sous
son acronyme TAOCP) par Donald Knuth, Addison Wesley : ouvrage de
référence, de nature quasi-encyclopédique bien qu'écrit pas un seul auteur, pas
vraiment facile à lire mais d'une rigueur absolue.
223
Index
225
163 Comparable (interface) Deprecated (annotation)
case (mot clé).. . p.38, 55 p.153 p.178
casting............. p.35 Comparator (interface) dérivée (classe). p.130
catch (mot clé). . p.91, 93, 94 p.153 dessiner........... p.192
ceil()................ p.160 compareTo()..... p.53 destroy().......... p.162, 196
chaînage........... p.112, 120 compareToIgnoreCase() destructeur....... p.84
chaînes de caractères p.53 Dimension (classe) p.195,
p.53, 168 compatibilité ascendante 195
chaînes modifiables p.53 p.20 directive........... p.177
chaînes non modifiables compilation....... p.45, 124 disjoint().......... p.151
p.53 complexité........ p.67, 77 do (mot clé)...... p.39
char (mot clé). . . p.27 Component (classe) p.182 documentation automatique
Character (classe) p.27, composant graphique (notion) p.21, 31, 175
162, 163 ....................... p.182 Documented (annotation)
charAt()............ p.53 concaténation.... p.53 p.178
checked (exceptions) p.94 concurrent (package) double (mot clé) p.28, 162
checker framework p.179 p.211 double-buffering p.194
chemin............. p.118 const (mot clé). . p.29 drawImage()..... p.192, 194
Class (classe).... p.164 constantes........ p.29, 30, 56 drawLine()........ p.192
class (mot clé)... p.80 constructeur...... p.81, 131 drawRect()........ p.192
classe (notion). . p.79 constructeur par recopie drawString()..... p.192
classe abstraite. p.133 p.81 droit d'auteur.... p.65
classe anonyme. p.186 Constructor (classe) p.164 durée............... p.167
classe effective. . p.132 Container (classe) p.182 dynastique (numérotation)
classe fille (ou classe dérivée) contains()......... p.Erreur : p.118
....................... p.130 source de la référence non Eclipse.............. p.21, 134
classe mère (ou super-classe) trouvée écouteur d'événements
....................... p.130 containsAll()...... p.156 (notion)............ p.186
classe non-dérivable p.133 containsKey().... p.157 éditions (de Java) p.22
classes anonymes p.128 containsValue(). p.157 effective (classe) p.132
classes enveloppes p.162 conteneur (notion) p.184 efficacité........... p.67
classes internes (ou nichées) contentPane...... p.203 elements()........ p.158
....................... p.128 contexte graphique p.192 ElementType..... p.178
classes locales... p.128 continue (mot clé) p.41 ellipse.............. p.62
CLASSPATH....... p.123 contrôlées (exceptions) else (mot clé).... p.37
clear().............. p.Erreur : p.94 encapsulation.... p.123, 130,
source de la référence non conventions de nommage 130
trouvée p.30 en place (tris). . . p.69
client-serveur.... p.216 conversion (opérateur de) ensemble.......... p.156
Clojure (langage) p.15, p.35, 160 en-tête............. p.57
22 corps................ p.57 entiers (nombres) p.28,
clone()............. p.136, 142 createImage()... p.194 32, 162
Cloneable (interface) p.136, Currency (classe) p.172 entrées-sorties. . p.42
142 Dalvik............... p.22 entrySet()......... p.157
close().............. p.101 deadlock (notion) p.211 Enum (classe). . . p.164
Closeable (interface) p.142 décidabilité....... p.66 enum (mot clé). p.40, 55,
cœurs............... p.211 décidable (problème ou 89, 164
Collection (interface) p.Erreur fonction)........... p.66 EnumMap (classe) p.158
: source de la référence non déclaration (de variable) EnumSet (classe) p.158
trouvée p.30, 30 enveloppes (classes) p.162
collection (notion) p.149 déclaration (de variables) equals()............ p.134
Collections (classe) p.151 p.48 Error (classe).... p.94
Color (classe).... p.193 deepEquals()..... p.48 espace de nommage p.123
color (package). p.193 deepToString(). . p.48 événement (notion) p.186
commentaires. . . p.31, 175 default (mot clé) p.38, 146 événementielle (style de
compact (notion) p.125 DelayQueue (classe) p.157 programmation) p.186
226
Index
Exception (classe) p.93 Formatter (classe) p.42, goto (mot clé). . . p.41
exceptions........ p.91, 95 172 Graphics (classe) p.192
exceptions contrôlées (ou forName()......... p.137, 164 Graphics2D (classe) p.192
non)................. p.94 Fortran (langage) p.15 GRD (parcours). p.119
exec().............. p.162 freeMemory().... p.162 green threads (notion)
exécution.......... p.45 frequency()....... p.151 p.211
exit()............... p.161 fuite de mémoire (notion) GridLayout (classe) p.184
expression rationnelle p.48 Groovy (langage) p.22
(notion)............ p.168 function (package) p.144 GWT................. p.22
expression régulière (notion) FunctionalInterface hashCode()....... p.134, 171
....................... p.168 (annotation)...... p.144, 178 HashMap (classe) p.158
extends (mot clé) p.129, Garbage collector (GC) HashSet (classe) p.134, 156
141 p.48, 84, 161 HashTable (classe) p.158
Externalizable (interface) gc()................. p.161 Haskell (langage) p.15
p.143 GDR (parcours). p.119 headMap()........ p.157
fdlibm.............. p.161 généalogique (numérotation) héritage............ p.129, 141
feuille............... p.118 ....................... p.118 heure............... p.161
fichiers............. p.100, 101, generics (types génériques heuristique........ p.67
103 paramétrés)...... p.150 hexadécimal...... p.28
Field (classe)..... p.165 générique (programmation) hôte................. p.216
FIFO................. p.116 p.136 ICC.................. p.193
File (classe)...... p.108 gestionnaire de présentation IEEE-754.......... p.28
file (type)......... p.116, 156 (notion)............ p.184 if (mot clé)........ p.37
file d'attente...... p.117 getAnnotations() p.164, 165, IllegalArgumentException
FileInputStream (classe) 166 p.137
p.106 getAudioClip(). . . p.196 Image (classe). . p.194
FileOutputStream (classe) getBackground() p.193 image (formats supportés)
p.105 getBytes()........ p.217 p.194
FileReader (classe) p.103 getChars()........ p.53 ImageIO (classe) p.194
fill()................. p.151 getClass()......... p.134, 164 ImageObserver (interface)
fille (classe)...... p.130 getColor()......... p.193 p.194
fillRect()........... p.192 getContentPane() p.203 impérative (style de
final (mot clé). . . p.29, 56, getDeclaredFields() p.164 programmation) p.186
133, 133 getDeclaredMethods() implantation (d'une interface)
finalize()........... p.134 p.164 ....................... p.141
finally (mot clé). p.91, 93 getFontList()..... p.194 implements (mot clé)
firstKey().......... p.157 getForeground() p.193 p.141
float (mot clé). . . p.28, 162 getGraphics().... p.194 import (mot clé) p.124
floatValue()....... p.163 getHeight()....... p.195 indexOf().......... p.154
floor().............. p.160 getID()............. p.186 InetAddress (classe) p.215
flottants (nombres) p.28, getImage()....... p.194 inférer.............. p.Erreur :
32, 161, 162 getInputStream() p.216 source de la référence non
FlowLayout (classe) p.184 getInterfaces(). . p.164 trouvée
flush().............. p.101 getLayout()....... p.184 infinity.............. p.28
Flushable (interface) p.142 getModifiers().... p.165 infixé................ p.119, 120
focus................ p.203 getOutputStream() p.216 init()................ p.196
fonction............ p.57 getParameterType() p.166 insertion (tri). . . . p.71
Font (classe)..... p.194 getProperty().... p.161 instance............ p.79
font (package)... p.194 getReturnType() p.166 instanceof (mot clé) p.83,
for (mot clé)..... p.40 getRuntime(). . . . p.162 130
forêt................. p.118 getScaledInstance() p.194 instant.............. p.167
ForkJoinPool (classe) p.211 getScreenSize(). p.195 int (mot clé)...... p.28, 162
format()........... p.42 getSource()....... p.186 interface (mot clé) p.139
formats de fichiers audio getType()......... p.165 interface de marquage
p.196 getWidth()........ p.195 p.142
Formattable (interface) GIF (format d'image) p.194 Interfaces fonctionnelles
p.42 Gosling, James. . p.18 p.144
227
interfaces internes (ou JFrame (classe). p.203 long (mot clé). . . p.28, 162
nichées)........... p.128 JOptionPane (classe) p.203 loop()............... p.196
internationalisation (notion) JPEG (format d'image) main().............. p.25, 45, 60
p.172 p.194 Map (interface).. p.157
interne (classe ou interface) JRadioButton (classe) marker interface p.142
p.128 p.203 marqueur......... p.142
introspection (notion) JRE (Java Runtime marshalling....... p.105
p.137, 177 Environment).... p.21 masquage......... p.130
intValue()......... p.163 JRuby (langage) p.22 masquage (notion) p.131
invocation (de méthode) JTextPane (classe) p.203 Math (classe).... p.160
p.59 JVM.................. p.19 math (package). p.160, 163
invoke()........... p.166 Jython (langage) p.22 MathContext (classe) p.163
isInfinite()........ p.163 keys().............. p.158 MAX_VALUE...... p.163
isLetter(), isDigit(), keySet()........... p.157 max()............... p.151, 160
isWhiteSpace(), etc. p.163 Knuth, Donald. . . p.65, 223 membre (de classe) p.80
isNaN()............. p.163 Label (classe).... p.196 memory leak (notion)
ISO 4217.......... p.172 label (mot clé)... p.41 p.48
isProbablePrime() p.163 lambda expression p.18, mère (classe).... p.130
Iterable (interface) p.40 144 métaclasse........ p.164
itérateur (notion) p.154 lang (package). . p.159 métadonnée...... p.177
Iterator (interface) p.154 langage binaire.. p.15 Method (classe). p.166
JApplet (classe). p.203 langages de programmation méthode........... p.79, 80,
JAR.................. p.219 p.15 81, 130, 166
java2D (package) p.205 langages de programmation méthode abstraite p.132
Java2D (package) p.219 logique............. p.15 méthode de classe p.87
java2s.com (site web) langages fonctionnels méthode non-redéfinissable
p.42, 168, 219 p.15 p.133
java3D (package) p.205 langages impératifs p.15 Méthodes par défaut p.146
javac (commande) p.196 langages orientés objets méthode statique p.87
Java card.......... p.22 p.15 MIN_VALUE....... p.163
Java Developer Network (site langages rationnels (notion) min()............... p.151, 160
web)................ p.219 p.168 ML, CAML (langages) p.15
javadoc............ p.21, 31, lastKey().......... p.157 MMIX............... p.65
178 LayoutManager (interface) modInverse().... p.163
javadoc (commande) p.175 p.184 modulo............. p.32
Java EE, J2EE (Java length()............ p.53 monnaie........... p.172
Enterprise Edition) p.22, length (pour les tableaux) Moore (loi de).... p.67
219 p.48 mot-clé (notion) p.25
JavaFX............. p.181, 205, licences............ p.21 motif (notion).... p.168
219 LIFO................. p.113 MouseAdapter (classe)
javah............... p.63 linéarisation...... p.105 p.186
Java ME, J2ME (Java Micro LinkedBlockingQueue (classe) multi-cœurs...... p.211
Edition)............ p.22 ....................... p.157 musicaux (formats de
Java Native Interface (JNI) LinkedList (classe) p.151, fichiers)............ p.196
p.63 152, 154 MVC................. p.203
JavaScript (langage) p.19, lisibilité............. p.30 Nahshorn.......... p.19
22 Lisp (langage). . . p.15 namespace....... p.123
Java SE, J2SE (Java Standard List (interface)... p.152, 154 Nan (NotANumber) p.28,
Edition)............ p.22 liste (type)........ p.110 32
Jazelle.............. p.15 listener (notion). p.186 native (mot clé). p.63
JCheckBox (classe) p.203 ListIterator (interface) native thread (notion)
JComponent (classe) p.203 p.151, 155 p.211
JDialog (classe). p.203 Locale (classe). . p.172 NEGATIVE_INFINITY p.163
JDK (Java Development Kit) localisation (notion) p.172 NetBeans.......... p.21, 134
p.21 lock (notion)..... p.210 new (mot clé).... p.35, 47,
JFileChooser (classe) p.203 loi de Moore...... p.67 53, 82
228
Index
229
p.161 subSet()........... p.156 TreeSet (classe) p.156
seek().............. p.107 substring()........ p.53 tri « en place ». . p.69
sélection (tri).... p.70 subtractExact().. p.160 tri bulle............ p.72
sérialisation, désérialisation Sun.................. p.18 trim()............... p.53
p.105 super (mot clé).. p.131, 131 tri par insertion. p.71
Serializable (interface) super-classe...... p.130 tri par sélection. p.70
p.101, 105, 142, 143 SupressWarnings tri rapide.......... p.74
ServerSocket (classe) (annotation)...... p.178 try (mot clé)..... p.91, 93
p.216 surchage.......... p.62 type (notion de) p.Erreur :
Set (interface)... p.156 swing (package) p.203 source de la référence non
setBackground() p.193 switch (mot clé). p.38, 55 trouvée
setColor()......... p.193 SWT................. p.181, 182, type abstrait..... p.139
setFont().......... p.194 219 type booléen..... p.27, 162
setForeground() p.193 synchronized (mot clé) type caractère... p.27, 162,
setJMenuBar()... p.203 p.210 163
setLayout()....... p.184 System (classe). p.42, 161 type énuméré.... p.40, 55,
setMaximumSize() p.195 tableaux........... p.48, 134 89, 158, 164
setMinimumSize() p.195 table d'association (type) types entiers..... p.28, 162
setPreferedSize() p.195 p.157 types flottants... p.28, 162
setPriority()...... p.211 tags................. p.175 types primitifs. . . p.Erreur :
setSeed()......... p.170 tailMap()........... p.157 source de la référence non
setSize()........... p.195 TAOCP.............. p.65, 223 trouvée, 26
setVisible()....... p.201 Target (annotation) p.178 unchecked (exceptions)
Shape (classe). . p.192 temps.............. p.167 p.94
short (mot clé). . p.28, 162 ternaire (opérateur) p.35 Unicode............ p.27
shuffle()........... p.151 tests................ p.33, 35, UnsupportedOperationExcepti
signature.......... p.57 37, 38 on.................... p.Erreur :
signum().......... p.160 this()................ p.81 source de la référence non
sleep()............. p.208, 211 this (mot clé).... p.84 trouvée
Smalltalk (langage) p.15, Thread (classe). p.208 update()........... p.196
15 ThreadGroup (classe) URL (classe)...... p.215
Socket (classe). . p.216 p.212 URLConnection (classe)
SortedMap (interface) ThreadLocalRandom (classe) p.215
p.157 ....................... p.170 util (package).... p.167
SortedSet (interface) p.156 threads (notion) p.207 validate().......... p.184
Source (menu d'Eclipse) throw (mot clé). p.95 valueOf().......... p.53
p.134 Throwable (classe) p.94 variable............ p.Erreur :
sous-classe....... p.130 throws (mot clé) p.96 source de la référence non
sous-type......... p.134 ThumbEE.......... p.15 trouvée, 30, 36, 59
spécialisation (notion) time (package). . p.167 Vector (classe). . p.154
p.131 toArray().......... p.Erreur : verrou (notion).. p.210
split()............... p.53, 53 source de la référence non versions du langage p.18
Stack (classe). . . p.155 trouvée VHDL (langage). p.15
start().............. p.196 toDegrees()...... p.160 visibilité............ p.88, 127
static (mot clé). . p.85, 87 toIntExact()...... p.160 void (mot clé). . . p.58
stop()............... p.196 toLowercase(), volatile (mot clé) p.210
strict floating point p.161 toUpperCase(), etc. p.53, waitFor().......... p.162
strictfp............. p.161 163 WBMP (format d'image)
StrictMath (classe) p.161 Toolkit (classe). . p.195 p.194
String (classe)... p.53 toRadians()....... p.160 while (mot clé). . p.39
StringBuffer (classe) p.53 toString()......... p.134, 163, windowClosing() p.186
StringBuilder (classe) 171 wrapper............ p.162
p.53 totalMemory().. . p.162 writeDouble().... p.105
Stroke (classe). . p.192 transformateur. . p.111 writeExternal(). . p.143
structure de données p.109 transient (mot clé) p.143 writeInt().......... p.105
subMap().......... p.157 TreeMap (classe) p.158 writeObject()..... p.105, 143
230
Index
231