Académique Documents
Professionnel Documents
Culture Documents
1
2.4 Les packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.4.2 Packages en Java . . . . . . . . . . . . . . . . . . . . . . . 42
2.5 Les classes abstraites et interfaces . . . . . . . . . . . . . . . . . . 43
2.5.1 Classes et méthodes abstraites . . . . . . . . . . . . . . . 43
2.5.2 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.5.3 Exemple d’utilisation des interfaces . . . . . . . . . . . . . 46
2.6 Spécialisation naturelle et substituabilité de Liskov . . . . . . . . 50
2.6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.6.2 Spécialisation naturelle . . . . . . . . . . . . . . . . . . . 51
2.6.3 Principe de Substituabilité (ou Principe de Liskov) . . . . 51
2.7 Les assertions et les exceptions . . . . . . . . . . . . . . . . . . . 53
2.7.1 Conception par contrats . . . . . . . . . . . . . . . . . . . 53
2.7.2 Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.7.3 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.7.4 Bonnes pratiques . . . . . . . . . . . . . . . . . . . . . . . 61
2.8 Les énumérations . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.8.2 Énumérations en Java (Depuis Java 5) . . . . . . . . . . . 61
2.8.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.9 Les annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.9.2 Définition d’une annotation . . . . . . . . . . . . . . . . . 64
2.9.3 Composition d’annotations . . . . . . . . . . . . . . . . . 64
2.9.4 Annoter un élément de code . . . . . . . . . . . . . . . . . 65
2.9.5 Annotations de l’API Java . . . . . . . . . . . . . . . . . 66
2.9.6 Méta-annotations ou Annotations d’annotations . . . . . 67
2.9.7 Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.10 Les Collections d’objets . . . . . . . . . . . . . . . . . . . . . . . 71
2.10.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.10.2 L’interface Collection<E> . . . . . . . . . . . . . . . . . 73
2.10.3 L’interface List . . . . . . . . . . . . . . . . . . . . . . . 73
2.10.4 L’interface Map . . . . . . . . . . . . . . . . . . . . . . . . 75
2.10.5 L’interface Set . . . . . . . . . . . . . . . . . . . . . . . . 78
2.10.6 Associations UML en Java . . . . . . . . . . . . . . . . . . 79
2.11 Les itérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
2.11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 79
2.11.2 Les itérateurs et itérables de l’API Java . . . . . . . . . . 80
2.11.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
2.12 Tri, comparaison, et clonage d’objets . . . . . . . . . . . . . . . . 88
2.12.1 Tri et Comparaison . . . . . . . . . . . . . . . . . . . . . . 88
2.12.2 Clonage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.13 La généricité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
2.13.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 90
2.13.2 Paramétrage des propriétés d’une classe générique . . . . 92
2.13.3 Généricité, héritage et instanciation . . . . . . . . . . . . 92
2
2.13.4 Généricité et sous-typage . . . . . . . . . . . . . . . . . . 93
2.13.5 Généricité bornée . . . . . . . . . . . . . . . . . . . . . . . 93
2.13.6 Le principe de l’effacement de type . . . . . . . . . . . . . 97
2.13.7 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
2.14 Les flux d’I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
2.14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 102
2.14.2 Le package java.io . . . . . . . . . . . . . . . . . . . . . 105
2.14.3 Le package java.nio . . . . . . . . . . . . . . . . . . . . 126
2.14.4 Le package java.nio.charset . . . . . . . . . . . . . . . 132
2.14.5 Le package java.nio.file . . . . . . . . . . . . . . . . . 133
2.15 Les classes imbriquées (nested classes) . . . . . . . . . . . . . . . 143
2.15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 143
2.15.2 Les classes imbriquées statiques (nested static classes) . . 143
2.15.3 Les classes internes (internal classes) . . . . . . . . . . . . 146
2.15.4 Les classes locales (local classes) . . . . . . . . . . . . . . 149
2.15.5 Les classes anonymes (anonymous classes) . . . . . . . . . 151
2.16 Interfaces fonctionnelles, lambda expressions et références de
méthodes/constructeurs (Depuis Java 8) . . . . . . . . . . . . . . 153
2.16.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 153
2.16.2 Interfaces fonctionnelles . . . . . . . . . . . . . . . . . . . 154
2.16.3 Lambda expressions . . . . . . . . . . . . . . . . . . . . . 162
2.16.4 Références de méthodes ou de constructeurs . . . . . . . . 165
2.17 Streams et collectors (Depuis Java 8) . . . . . . . . . . . . . . . 166
2.17.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 166
2.17.2 La classe Optional<T> . . . . . . . . . . . . . . . . . . . . 168
2.17.3 L’interface Stream<T> . . . . . . . . . . . . . . . . . . . . 169
2.17.4 Création de streams . . . . . . . . . . . . . . . . . . . . . 174
2.18 La réflexivité (l’introspection) . . . . . . . . . . . . . . . . . . . . 187
2.18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 187
2.18.2 La classe Class<T> . . . . . . . . . . . . . . . . . . . . . . 188
2.18.3 La classe AccessibleObject . . . . . . . . . . . . . . . . 190
2.18.4 La classe Executable . . . . . . . . . . . . . . . . . . . . 190
2.18.5 La classe Field<T> . . . . . . . . . . . . . . . . . . . . . . 190
2.18.6 La classe Method . . . . . . . . . . . . . . . . . . . . . . . 191
2.18.7 La classe Constructor<T> . . . . . . . . . . . . . . . . . . 192
2.18.8 L’interface AnnotatedElement . . . . . . . . . . . . . . . 192
2.18.9 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
2.19 Les dates (Nouvelle API depuis Java 8) . . . . . . . . . . . . . . 203
2.19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 203
2.19.2 L’interface Temporal . . . . . . . . . . . . . . . . . . . . . 203
2.19.3 L’interface TemporalUnit . . . . . . . . . . . . . . . . . . 203
2.19.4 L’interface TemporalAdjuster . . . . . . . . . . . . . . . 204
2.19.5 L’énumération ChronoUnit . . . . . . . . . . . . . . . . . 204
2.19.6 L’énumération DayOfWeek . . . . . . . . . . . . . . . . . . 204
2.19.7 L’énumération Month . . . . . . . . . . . . . . . . . . . . . 205
2.19.8 L’interface ChronoLocalDate . . . . . . . . . . . . . . . . 205
3
2.19.9 L’interface ChronoLocalDateTime<D extends ChronoLocalDate>206
2.19.10 L’interface ChronoZonedDateTime<D extends ChronoLocalDate>206
2.19.11 La classe Instant . . . . . . . . . . . . . . . . . . . . . . 207
2.19.12 La classe LocalDate . . . . . . . . . . . . . . . . . . . . . 207
2.19.13 La classe LocalTime . . . . . . . . . . . . . . . . . . . . . 211
2.19.14 La classe LocalDateTime . . . . . . . . . . . . . . . . . . 215
2.19.15 La classe ZonedDateTime . . . . . . . . . . . . . . . . . . 221
2.19.16 La classe TemporalAdjusters . . . . . . . . . . . . . . . . 222
2.19.17 La classe Period . . . . . . . . . . . . . . . . . . . . . . . 222
2.19.18 La classe Duration . . . . . . . . . . . . . . . . . . . . . . 223
2.19.19 La classe ZoneId . . . . . . . . . . . . . . . . . . . . . . . 223
2.19.20 La classe ZoneRules . . . . . . . . . . . . . . . . . . . . . 224
2.19.21 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
2.20 JVM et la modularité (Depuis Java 9) . . . . . . . . . . . . . . . 230
2.20.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 230
2.20.2 Contraintes de manipulation des modules . . . . . . . . . 230
2.20.3 Syntaxe de définition d’un module . . . . . . . . . . . . . 231
2.20.4 CLI ajoutée par JDK pour les modules (Depuis Java 9) . 231
4
4.7 Le pattern Fork/Join . . . . . . . . . . . . . . . . . . . . . . . . 259
4.7.1 Pré-requis . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
4.7.2 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
4.7.3 Processus . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
4.7.4 Implémentation en Java (Depuis Java 7) . . . . . . . . . . 261
1.1 Introduction
5
• interprétation : la plateforme d’exécution Java JRE (Java
Run Environment) contenant la machine virtuelle Java JVM
(Java Virtual Machine) ;
• bytecode : code intermédiaire et portable obtenu par la com-
pilation du code source Java (i.e. le même quelle que soit la
plateforme de développement du code source Java) ;
• JRE : plateforme d’exécution Java propre à chaque plate-
forme et peut être intégrée au sein d’un navigateur web pour
exécuter des Java applets.
6. applications développées en Java :
• applications GUI ou CLI (clients lourds)
• applications web (front-end applets ou back-end applications)
(clients légers)
• applications mobiles (smartphone, PDA, etc.)
6
• bytecode : fichier .class contenant du code précompilé illisible
par les humains et déchiffré uniquement par la JVM.
3. JRE : plateforme d’exécution Java propre à chaque plateforme
et peut être intégrée au sein d’un navigateur web pour exécuter des
Java applets.
4. JDK (Java Development Kit) : le kit de développement Java
contenant le JRE et des outils de développement, de compilation et
de débogage.
7
1.2 Types, variables et opérateurs
1.2.3 Commentaires :
// commentaire monoligne
/*
commentaire
multi-ligne
*/
/**
commentaires
8
javadoc
**/
1.2.4 Variables
1. conventions de nommage :
• camelCase pour les types primitifs ;
• CamelCase pour les types complexes ;
• SNAKE_CASE pour les constantes ;
2. contraintes de nommage :
• sensitive à la casse ;
• que des caractères alphanumériques ;
• sans caractères spéciaux ou blancs.
3. syntaxes :
// déclaration
type nomVariable;
// affectation
nomVariable = valeur;
// déclaration et initialisation
type nomVariable = valeur;
1.2.5 Opérateurs
9
1.2.5.2 Opérateurs d’affectation
10
symbol description utilisation remarques
& et binaire a &b -
| ou binaire a |b -
^ ou exclusif binaire (xor) a ^b -
<< décalage de bit à gauche a << b décalage de b bits à gauche
>> décalage de bit à droite a >> b décalage de b bits à droite
d = 2.99999999;
f = (float)d; //conversion d'un double en un float
f = 1.24567f;
d = (double)d; //conversion d'un float en un double
11
f = 1.23f;
d = 2.99999999;
i = (int)f; //conversion d'un float en un int
i = (int)d; //conversion d'un double en un int
if (expressionBooleene1){
/*code si <expressionBooleene1> vaut true*/
}
else if (<expressionBooleene2>){
/*code si <expressionBooleene2> vaut true*/
}
...
else {
/*code sinon*/
}
1.3.2 Switch
12
break;
...
default:
/*code sinon*/
}
while(<expression_booléene>){
/*code*/
}
do {
/*code*/
} while(expression_booléene);
13
1.5 Les méthodes de classe (fonctions)
14
// tableau vide à deux dimensions ayant "lignes" lignes et "colonnes" colonnes
type nomTableauMulti[][] = new type[lignes][colonnes];
package generic.test;
import java.util.Scanner;
15
public static String modeConversion(Scanner scanner){
System.out.println("Veuillez choisir un mode de conversion :");
System.out.println("1- Celsius -> Fahrenheit");
System.out.println("2- Fahrenheit -> Celsius ");
int choix = scanner.nextInt();
scanner.nextLine();
return (choix == 1)? "Celsius" : "Fahrenheit";
}
} while(cont);
scanner.close();
}
}
16
2 Programmation Orientée Objet en Java
/*
* description : renvoie un nouveau string désignant le même string mais
avec des caractères minuscules (avec aucun effet sur les chiffres)
*/
public String toLowerCase();
/*
* description : renvoie un nouveau string désignant le même string mais
avec des caractères majuscules (avec aucun effet sur les chiffres)
*/
public String toUpperCase();
/*
* description : renvoie le caractère à "index" si celui-ci est valide
(i.e. ne dépasse pas la longueur du string), sinon renvoie -1
*/
public char charAt(int index);
/*
* description : renvoie le sous-string du string en commençant par l'indice
"beginIndex" [et se terminant à l'indice "end - 1"]
tant que les indices sont valides,
sinon renvoie un string vide
*/
public String substring(int beginIndex[, int endIndex]);
/*
* description : renvoie l'indexe de la première occurrence du
caractère "character" ou du premier caractère du string "string"
en commençant la recherche depuis le début du string appelant
17
(i.e. depuis l'indice 0)
*/
public int indexOf(String string | char character);
/*
* description : renvoie l'indexe de la première occurrence du
caractère "character" ou du premier caractère du string "string"
en commençant la recherche depuis la fin du string appelant
(i.e. depuis l'indice à l'indice string.length() - 1)
*/
public int lastIndexOf(String string | char character);
/*
* description : retourne la représentation String de l'objet de type
générique "object"
(équivalent de object.toString())
*/
public static String valueOf(T object);
/*
* description : base^exponent
*/
public static double pow(double base, double exponent);
/*
* description : une valeur pseudo-aléatoire entre 0 et 1
*/
public static double random();
/*
* description : le sinus de l'angle en radians a
*/
public static double sin(double a);
18
/*
* description : le cosinus de l'angle en radians a
*/
public static double cos(double a);
/*
* description : la tangente de l'angle en radians a
*/
public static double tan(double a);
/**
* Retourne un générateur de nombres pseudo-aléatoires
* en utilisant "seed".
*/
public Random(long seed)
/**
* Retourne un stream de valeurs doubles pseudo-aléatoires
* entre 0 (inclus) et 1 (exclus).
*/
public DoubleStream doubles()
/**
* Retourne un stream de valeurs doubles pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound)
/**
* Retourne un stream de "streamSize" valeurs doubles pseudo-aléatoires
* entre 0 (inclus) et 1 (exclus).
19
*/
public DoubleStream doubles(long streamSize)
/**
* Retourne un stream de "streamSize" valeurs doubles pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberB
/**
* Retourne un stream de valeurs entières pseudo-aléatoires
*/
public IntStream ints()
/**
* Retourne un stream de valeurs entières pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public IntStream ints(double randomNumberOrigin, double randomNumberBound)
/**
* Retourne un stream de "streamSize" valeurs entières pseudo-aléatoires
*/
public IntStream ints(long streamSize)
/**
* Retourne un stream de "streamSize" valeurs entières pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public IntStream ints(long streamSize, double randomNumberOrigin, double randomNumberBound)
/**
* Retourne un stream de valeurs entières longues pseudo-aléatoires
*/
public LongStream longs()
/**
* Retourne un stream de valeurs entières longues pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public LongStream longs(double randomNumberOrigin, double randomNumberBound)
/**
* Retourne un stream de "streamSize" valeurs entières longues pseudo-aléatoires
*/
public LongStream longs(long streamSize)
20
/**
* Retourne un stream de "streamSize" valeurs entières longues pseudo-aléatoires
* entre randomNumberOrigin (inclus) et randomNumberBound (exclus).
*/
public LongStream longs(long streamSize, double randomNumberOrigin, double randomNumberBound
/**
* Retourne la prochaine valeur booléen pseudo-aléatoire générée
*/
public boolean nextBoolean()
/**
* Retourne le prochain tableaux de bytes pseudo-aléatoires généré
*/
Generates random bytes and places them into a user-supplied byte array.
public void nextBytes(byte[] bytes)
/**
* Retourne la prochaine valeur double pseudo-aléatoire générée
*/
public double nextDouble()
/**
* Retourne la prochaine valeur float pseudo-aléatoire générée
*/
public float nextFloat()
/**
* Retourne la prochaine valeur entière pseudo-aléatoire générée
*/
public int nextInt()
/**
* Retourne la prochaine valeur entière pseudo-aléatoire générée
* entre 0 (inclus) et bound (exclus).
*/
public int nextInt(int bound)
/**
* Retourne la prochaine valeur entière longue pseudo-aléatoire générée
*/
public long nextLong()
/**
* Affecter "seed" comme seed de ce générateur
21
*/
public void setSeed(long seed)
2.2.1.1 Classes
1. définition : une abstraction d’un ensemble d’éléments partageant
des propriétés communes (i.e. des caractéristiques et des comporte-
ments)
2. syntaxe de déclaration rudimentaire :
visibilite class NomClass{
/*attributes*/
...
/*methods*/
...
}
2.2.1.2 Objets/Instances
1. définition : un élément d’une classe obtenu en attribuant des valeurs
aux caractéristiques définies dans la classe.
2. opérateur d’accès aux propriétés d’un objet : objet.propriete
2.2.2.1 Attributs
1. définition : caractéristiques structurelles d’une classe désignant son
état (i.e. variables de types primitifs ou complexes définies au sein de la
classe)
2. types : attributs d’instance et attributs de classe (statiques)
22
nomAttribut;
this.nomAttribut;
2.2.2.2 Méthodes
1. définition : comportements dynamiques d’une classe (i.e. fonctions
définies au sein de la classe)
2. types : méthodes d’instance et méthodes de classe (statiques)
3. passage de paramètres :
• paramètre de type primitif : passage par valeur.
• paramètre de type complexe : passage par référence.
• tous les paramètres d’une méthode/fonction en Java sont con-
sidérés comme des paramètres ayant la direction “in” par défaut.
• les paramètres d’une méthode/fonction sont initialisés par les
arguments passés lors de l’invocation de la méthode/fonction.
4. variables locales :
• définition : des variables déclarées au sein d’une méth-
ode/fonction
• portée : le corps de la méthode dans lequelle elles étaient
déclarées
• visibilité : aucune visibilité explicitée.
• caractéristique : non initialisées par défaut.
23
2.2.2.2.1 Méthodes d’instance
1. définition : comportements permettant de manipuler les attributs
d’instance.
2. syntaxes :
/*définition d'une méthode d'instance*/
/*==================================*/
visibilite typeRetour nomMethode([type1 p1[, type2 p2[, ...[, typeN pN]]]]){
/*code*/
[return expression;] // expression doit être de type "typeRetour", si typeRetour différent
}
24
2.2.2.3 Initialisations par défaut
1. pour les attributs :
2.2.3.1 Constructeurs
1. définition : une méthode particulière dont le rôle consiste à con-
struire des instances d’une classe.
2. rôle :
• constuire des instances d’une classe en initialisant les attributs,
éventuellement via des arguments passés.
• signaler à la JVM qu’il faut réserver de l’espace mémoire pour
l’objet que l’on veut construire.
25
3. syntaxes :
// définition d'un constructeur
NomClass([params]){
/*initialisation des attributs et d'autres instructions*/
}
2.2.3.2 Destructeur
26
1. définition : une méthode particulière permettant de détruire une
instance d’une classe.
2. remarque : en Java, un destructeur n’est pas explicité, mais une
méthode finalize() est appelée implicitement quand le garbage col-
lector détruit un objet qui n’est plus référencé.
2.2.4.1 Encapsulation
1. définition : le principe d’encapsulation consiste à rendre la visibil-
ité des attributs d’une classe private, qui ne seront accessibles qu’à
travers des méthodes d’accès en lecture/écriture.
2. utilités :
• une interface de manipulation simplifiée et abstraction de
l’implémentation interne des classes.
• une mesure de sécurité permettant d’empêcher le monde ex-
térieur de modifier la structure interne des classes.
2.2.4.2 Getters/Setters
1. définition : pour chaque attribut d’une classe, une paire de méthodes
publiques spéciales sont utilisées pour y accéder en accord avec le
principe d’encapsulation :
• getter (accesseur) : accès en lecture.
• setter (mutateur) : accès en écriture.
2. syntaxes :
// définition rudimentaire d'un getter
public type getAtt() {return att; }
27
2.3 Héritage et polymorphisme
2.3.1 Introduction
2.3.2.1 Généralisation
1. définition : mécanisme consistant à réunir les objets possédant des
caractéristiques communes dans une nouvelle classe plus générale.
2. superclasse ou classe mère : la classe la plus générale obtenue.
3. sous-classes ou classes filles : les classes à partir desquelles la super-
classe est généralisée.
4. exemple : une classe Bateau et une classe Voiture peuvent se
généraliser en une superclasse Vehicule dont ils deviennent sous-
28
classes.
2.3.2.2 Spécialisation
1. définition : mécanisme consistant à différencier à partir d’une classe
(superclasse) plusieurs sous-classes partageant des caractéristiques
communes.
2. propriétés :
• ces caractéristiques peuvent être éventuellement redéfinies par
les sous-classes selon leur point de vue.
• de nouvelles caractéristiques peuvent être éventuellement inté-
grées au sein des sous-classes, afin de les distinguer de la super-
classe.
3. exemple : une classe Bateau qui peut se spécialiser en deux sous-
classes BateauAVoile et BateauAMoteur.
2.3.2.3 Héritage
1. définition : la relation d’héritage entre une superclasse A et une
sous-classe B peut être exprimée par l’expression : « B est A mais A
n’est pas forcément B ».
2. concrétisation : lors d’une généralisation/spécialisation, on dit que
les sous-classes héritent d’une superclasse ou étendent une super-
classe.
3. propriétés :
• les propriétés d’une superclasse (i.e. attributs et méthodes) sont
héritées par les sous-classes.
• les sous-classes peuvent éventuellement redéfinir certaines pro-
priétés et en ajouter davantage.
2.3.2.4 Discriminants
1. définition :
• critère utilisé pour la classification des objets dans des sous-
classes à partir d’une superclasse.
• étiquette les relations de spécialisation/généralisation.
2. exemple :
2.3.2.5 Contraintes
1. définition : annotations circonscrites par des accolades décrivant la
relation entre un ensemble de sous-classes et leur superclasse.
2. types : il existe quatre types classés en deux paires complémen-
taires :
29
Figure 2: “Exemple d’utilisation de discriminants”
2.3.2.5.1 Analyse
1. il existe d’autres types d’appartement que “luxes” et “normaux” → con-
trainte incomplet.
2. un appartement ne peut pas être luxe et normal en même temps → con-
trainte disjoint.
3. un appartement est soit privé, soit pour une entreprise, et il n’existe pas
d’autre cas → contrainte complet.
4. un appartement peut être utilisé à la fois pour un usage privé et pour un
usage entreprise → contrainte chevauchement.
30
Figure 3: “Exemple d’utilisation de contraintes”
31
2.3.4 Héritage en Java
2.3.4.2.1 Principes
1. single responsibility : pour chaque classe désignant un concept, sa
seule responsabilité est de s’occuper des propriétés qu’elle définit.
2. delegation : les propriétés héritées sont déléguées aux superclasses
correspondantes pour leur gestion.
32
2.3.4.2.2 Conventions pour la superclasse
1. toujours écrire un constructeur par défaut.
2. remarque : toutes les classes en Java héritant de la classe Object, le
constructeur par défaut de celle-ci est le premier à être appelé lors
de l’invocation d’un constructeur de n’importe quelle classe pendant
l’instanciation d’un objet.
33
2. Package private ou default (i.e. aucune valeur n’est explicitée) : la
classe est accessible uniquement par les éléments du même pack-
age la contenant.
(la moins ouverte) private < Package private < protected < public (la
plus ouverte)
34
• il est toujours possible d’accéder à l’implémentation
de la méthode masquée par la superclasse directe via
super.methode().
• on n’utilise généralement super.methode() que dans la nouvelle
définition de la méthode methode() au niveau de la sous-classe.
2.3.5.1 Introduction
1. définition : la capacité d’un même morceau de code d’avoir des
comportements différents selon le contexte.
2. étymologie : en grec, poly : plusieurs ; morphe : forme.
35
2.3.5.2 Les résolutions des liens statique et dynamique
36
4. syntaxes :
// transtypage
type1 nomVar;
type2 autreVar = (type2) nomVar; // conversion du type de "nomVar" en "type2"
// test de type
/*
* à l'exécution, si le type dynamique de "instance" désigne "NomClasse" ou
l'une de ses sous-classes, retourne "true", sinon retourner "false"
*/
instance instanceof NomClasse; // instanceof est un opérateur de test de type
2.3.5.5 Upcast
1. définition : affecter une instance d’une sous-classe à une variable
d’une superclasse, où le transtypage est effectué implicitement.
2. principe : ce comportement est toujours possible vu la nature de
la relation d’héritage, indiquant qu’un objet d’une sous-classe est
forcément inclus dans l’extension de la superclasse.
3. conséquence : la variable de la superclasse aura accès uniquement
aux propriétés héritées par la sous-classe de la superclasse.
4. syntaxe :
SuperClasse sup = new SousClass();
4. exemples :
// upcast possible car tout étudiant est forcément une personne
Personne p = new Etudiant();
Personne pers;
Etudiant e = new Etudiant();
pers = e;
2.3.5.6 Downcast
1. définition : l’inverse du Upcast : affecter une instance d’une super-
classe à une variable d’une sous-classe, où le transtypage doit être
effectué explicitement.
2. principe : ce comportement est parfois possible vu la nature de la
relation d’héritage, indiquant qu’un objet d’une sous-classe est for-
cément inclus dans l’extension de la superclasse, mais l’inverse n’est
pas toujours vrai.
3. conséquence : le transtypage est possible uniquement si l’instance
de la superclasse est obtenue par instanciation de la sous-classe ou
de l’une de ces sous-classes (i.e. via un Upcast)
37
4. remarque : le Downcast ne doit se faire qu’en cas de nécessité absolue.
5. syntaxe :
SuperClasse sup = new SousClasse();
SousClasse sous = (SousClasse) sup;
6. exemple :
// downcast possible car p contient une instance de type statique Etudiant
Personne p = new Etudiant();
Etudiant e = (Etudiant) p;
/*
* description : retourner une représentation lisible de l'objet
sous forme d'un String
*/
public String toString();
/*
* description : retourner un code de hachage entier identifiant l'objet
* remarque : deux objets ayant le même code de hachage ne sont pas forcément
identiques (collision possible des codes de hachage)
*/
public int hashCode();
/*
* description : retourner le type de la classe de l'objet à l'exécution
*/
38
public final Class<?> getClass();
/*
* description : cloner l'objet
* remarque : une classe souhaitant redéfinir le cloneage d'un objet
doit implémenter l'interface "Cloneable" et redéfinir la méthode avec
une visibilité "public"
*/
protected Object clone();
/*
* description : retourner le code de hachage des attributs d'un objet
*/
public static int hash(Object att1[, ...]);
/*coercition de o en "type"*/
type transtypedO = (type) o;
39
/*si tous les attributs de type primitif de l'objet courant
ne correspondent pas aux attributs de type primitif de transtypedO,
renvoyer false*/
if (!(this.attSimple1 == transtypedO.attSimple1
&& this.attSimple2 == transtypedO.attSimple2
&& ...
&& this.attSimpleN == transtypedO.attSimpleN))
return false;
/* hashCode() */
@Override
public int hashCode(){
int prime = premier; //choix d'un nombre premier
int result = 1; //initialisation du résultat
40
result = prime*result + attSimple1;
result = prime*result + attSimple2;
...
result = prime*result + attSimpleK;
/*retour du résultat*/
return result;
}
Depuis Java 7 (en utilisant la classe Objects)
/* equals() */
public boolean equals (Object o){
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
/* hashCode() */
public int hashCode(){
return Objects.hash(this.att1, this.att2, ..., this.attN);
}
2.4.1 Introduction
2.4.1.1 Définition
1. regroupement logique de classes assurant un classement thématique
sous forme d’une hiérarchie d’inclusion de dossiers.
41
2. les packages sont reliés par des relations de dépendance.
2.4.1.2 Intérêts
1. meilleure structuration, traçabilité et lisibilité d’une application.
2. portabilité des classes d’une application à une autre.
42
import paquet.NomClasse; // importer la classe NomCLasse du paquet "paquet"
import paquet.*; // importer tout le contenu du paquet "paquet"
• remarque : raccourci en Eclipse pour inclure les importations
manquantes automatiquement et les organizer : ctrl + shift +
o.
2.5.2 Interfaces
2.5.2.1 Introduction
1. définition : une interface se limite à présenter des services fournis sous
forme d’une classe complétement abstraite implémentée par des
43
classes concrètes dans une relation de sous-typage (i.e. la classe con-
crète est un sous-type d’une interface) pour assurer le polymorphisme
des comportements implémentés.
2. utilité : les interfaces :
• sont plus abstraites que les classes abstraites et peuvent assurer
une meilleure réutilisation.
• permettent de découpler le fonctionnement (implémentation)
d’un comportement de son interfaçage (interface).
3. services fournis par une interface :
• avant Java 7 :
1. méthodes d’instance publiques et abstraites : public et
abstract.
2. attributs de classe publiques et constants : public,
static, et final.
• depuis Java 8 : les services supplémentaires suivants :
1. méthodes d’instance publiques ayant un comportement
par défaut : public et default.
2. méthodes de classe publiques : public et static.
3. des types internes : classes imbriqueés statiques ou non
statiques (cf. Les classes imbriquées).
4. une interface ne contient pas :
• de constructeurs ;
• d’attributs privés ;
• d’attributs d’instance ;
• d’implémentations des méthodes publiques abstraites
(hormis les méthodes statiques et celles ayant un comportement par
défaut)
5. remarques :
• les modifieurs public, abstract, final et static peuvent être
omis lorsqu’il n’y a pas d’ambiguïté.
• il existe une relation de sous-typage interne entre toute inter-
face et la classe java.lang.Object.
// définition d'une interface
public interface NomInterface {
/*attributs de classe publiques et statiques*/
type1 att1;
type2 att2;
…
typek attN;
/*méthodes*/
//méthodes d'instance publiques et abstraites
typeRetour1 m1([params]);
typeRetour2 m2([params]);
…
44
typeRetourK mK([params]);
/*
* affectation polymorphe possible en vue de la relation de sous-typage
entre "Object" et toute interface définie
*/
Object o = i;
45
3. peut implémenter plusieurs interfaces → dépasser les
limites de l’héritage simple entre les classes et assurer une
meilleure classification des concepts.
• si la classe :
1. n’implémente pas toutes les méthodes abstraites de
l’interface, alors elle doit être déclarée abstraite ;
2. hérite d’une classe et implémente une interface, l’expression
d’héritage doit précéder celle d’implémentation lors de la
définition de la classe.
public class NomClasse [extends SuperClasse,] implements NomInterface[, I1[, I2[, ...]]{/*co
/*methods*/
//default methods
protected void manger(){
System.out.println("Je mange de la viande");
}
//abstract methods
public abstract void deplacement();
public abstract void crier();
46
package openclassrooms.animaux;
// l'interface Rintintin
package openclassrooms.animaux;
/*methods*/
//inherited abstract methods
public void crier(){
System.out.println("Je miaule sur les toits !");
47
}
}
/*methods*/
//inherited abstract methods
public void crier(){
System.out.println("Je rugis dans la savane !");
}
}
/*methods*/
//inherited abstract methods
public void crier(){
System.out.println("Je grogne très fort !");
}
}
48
public Loup(){}
/*methods*/
//inherited abstract methods
public void crier(){
System.out.println("Je hurle à la lune !");
}
}
/*methods*/
//inherited abstract methods from Canin
public void crier(){
System.out.println("J'aboie sans raison !");
}
49
// la classe concrète Test
package openclassrooms.animaux;
2.6.1 Introduction
50
qui peuvent être parfois antagonistes.
51
3. utilités :
• vérifier un programme en limitant les erreurs à l’exécution
(i.e. le programme compile bien et pas d’erreurs de compilation) mais
demande le fait d’anticiper.
• imposer :
1. des restrictions sur les signatures lors de la redéfinition des
méthodes héritées.
2. des conditions comportementales apparentes notamment sur
les contrats (cf. Les assertions et les exceptions)
• appliquer avec un risque réduit des upcasts via des affectations
polymorphes.
4. exemple : les aliments frais ne sont pas des aliments dans le contexte
du comportement :
• on ne peut pas ranger les aliments frais dans tous les lieux où
on range des aliments.
• il faut un lieu réfrigéré aux aliments frais.
• ainsi les aliments et les aliments frais ne se comportent pas de
la même manière.
2.6.3.1 Restrictions sur les signatures des méthodes lors d’une redéf-
inition
1. les paramètres peuvent varier dans le sens inverse de la redéfinition
: contravariance des types de paramètres.
2. les types de retour peuvent varier dans le même sens de la redéfini-
tion : covariance des types de retour.
3. les pré-conditions sont affaiblies (cf. Les assertions et les exceptions)
4. les post-conditions sont renforcées (cf. Les assertions et les exceptions)
52
Figure 4: “Contravariance des types de paramètres selon le principe de Liskov”
1. définition :
• la mise en place de règles sur les classes et les méthodes pour
leur vérification.
• les règles établissent des contrats entre les objets (en matière
de leurs responsabilités respectives) qui collaborent pendant
l’exécution d’un programme.
2. portée :
• les invariants des classes :
1. définition : règles sur des objets.
2. exemples : une voiture a 4 roues, l’âge d’une personne est
positif, etc.
• les invariants des algorithmes :
1. définition : des propriétés vérifiées en certains points in-
ternes d’une méthode.
2. exemple : à la fin de l’itération i dans la recherche d’un maxi-
mum d’un tableau, la variable max contient la plus grande valeur
trouvée entre les itérations 0 et i.
• les invariants de flux :
53
1. définition : des propriétés vérifiés en certains points in-
ternes d’un flux de données.
2. exemple : ce point du programme ne peut être atteint.
• les axiomes des types abstraits de données :
1. définition : des propriétés qui doivent être vérifiées sur les
méthodes d’un type abstrait de données.
2. exemple : après avoir empilé un élément dans une pile, celui-ci
apparaît au sommet de la pile.
• les pré-conditions :
1. définition : les propriétés vérifiées à l’entrée d’une méth-
ode (i.e. avant l’invocation).
2. exemple : une méthode qui est appelée en dehors de son domaine
de définition (e.g. dépiler une pile vide, renseigner une mauvaise
valeur d’un paramètre, etc.)
3. remarque : la responsabilité du client de la méthode.
• les post-conditions :
1. définition : les propriétés vérifiées à la sortie d’une méth-
ode (i.e. après l’invocation).
2. exemple : à la fin d’un tri d’un tableau, le tableau est trié.
3. remarque : la responsabilité de la méthode (i.e. du concep-
teur de la méthode) envers son client.
3. historique :
• approche à objets : Bertrand Meyer.
• mise en oeuvre dans un langage de programmation : Eiffel
(d’une manière native).
4. mise en oeuvre en Java :
• les assertions ;
• les exceptions ;
• autres méthodes : spécifications, preuves formelles, conception et
réalisation des tests unitaires, etc.
2.7.2 Assertions
54
gramme.
• une fois que le programme est mis au point, on doit se
débarasser des assertions dans le code final avant sa mise en
production.
4. syntaxes :
assert expressionBooleene; // expression représentant le prédicat à vérifier
/*
* en cas de non respect de du prédicat,
* le résultat retourné par l'erreur contiendra le
* résultat de objet.toString()
*/
assert expressionBooleene : objet;
2.7.3 Exceptions
2.7.3.1 Introduction
1. erreur : une erreur liée à la JVM : manque des ressources, assertions
non respectées, etc.
2. exception : mécanisme de gestion des erreurs consistant à :
• signaler les erreurs pouvant se produire pendant l’exécution
d’un programme et les capturer.
• revenir à un fonctionnement normal ou arrêter le programme
proprement, afin d’éviter les arrêts brutaux d’un programme.
55
2. description : la superclasse de toutes les exceptions et erreurs en
Java.
3. quelques attributs :
• un message d’erreur.
• l’état de la pile des appels des méthodes.
4. quelques méthodes :
// constructors
Throwable();
Throwable(String message);
...
/*
* description : renvoie le message d'erreur
*/
public String getMessage();
/*
* description : imprimer l'état de la pile des appels des méthodes
dans la sortie des erreurs standard
*/
public void printStackTrace();
classe description
NullPointerException l’invocation d’une propriété sur un
objet null
ArrayIndexOutOfBoundException la sortie des bornes d’un tableau
56
classe description
ArithmeticException la division par zéro par exemple
NumberFormatException la conversion d’un String en un
nombre n’ayant pas le format
approprié
NegativeArraySizeException la création d’un tableau avec une
taille négative
57
Figure 5: “Hiérarchie des classes d’erreur de Throwable”
58
1. soit la capturer et la traiter dans un bloc de contrôle particulier
dans le corps du programme : le bloc try-catch[-finally]
2. soit la transmettre à la classe d’exception correspondante déclarée
dans la signature de la méthode m() : approche à priviliégier si
l’exception correspond à une exception de bas niveau (i.e. prédéfinie
dans l’API Java).
// définir une méthode capturant et traitant une exception
visibilite [static] nomMethode([params]) [throws NomException1[, ...]]{
...
/*
* description : quand une exception est levée dans un bloc try (Bloc 0),
l'exécution de celui-ci s'interrompt.
*/
try{/*Bloc 0*/ }
/*
* description : les clauses catch sont examinées par ordre de leur déclaration
jusqu'à trouver une classe nomExceptionI désignant celle de l'instance
de l'exception levée ou l'une de ses superclasses dans l'hiérarchie
d'héritage des exceptions :
a. si on en trouve une, alors le bloc I de la clause catch capturant
l'exception sera exécuté et le programme reprend
son exécution après les clauses catch suivantes.
b. si on n'en trouve aucune alors : l'exception ne sera pas capturée,
mais elle sera transmise à la méthode et l'exécution de celle-ci termine.
*
* remarque : (il faut que la méthode déclare la classe de l'exception dans la
clause "throws" de sa signature, sinon il y aura
une erreur de compilation)
*/
catch(NomException1 e1){/*Bloc 1*/ }
catch(NomException2 e2){/*Bloc 2*/ }
...
catch(NomExceptionN eN){/*Bloc N*/ }
/*
* description : si le bloc finally est fournis, il sera exécuté en tout cas
qu'il s'agit d'une exception capturée ou pas
* utilité : désallouer des ressources allouées, etc.
*/
[finally{/*Bloc N+1*/ }]
...
}
59
2. description : une interface spécifiant les méthodes à implémenter
par des classes désignant des ressources en Java qui souhaitent être
refermées automatiquement et proprement en cas d’erreur.
3. possède une seule méthode :
/*
* description : appelée automatiquement à la fin d'un bloc try
sur chaque ressource pouvant lever une exception de type Exception
*/
void close() throws Exception;
} catch(){/*code*/ }
...
3. remarques :
• l’ordre de fermeture des ressources déclarées est inverse à celui
de leur déclaration dans l’expression attachée à l’instruction
try.
• les ressources instanciées d’une manière imbriquée au sein
d’autres ressources (e.g. FileInputStream et BufferedInputStream)
ne sont pas fermées. Il faut les instancier à part avant de les
passer comme arguments aux autres ressources, afin d’être
fermées.
60
2.7.4 Bonnes pratiques
2.8.1 Introduction
61
2. les valeurs des énumérations sont des objets et s’utilisant comme des
attributs publiques statiques et constants.
3. conventions de nommage :
• des énumérations : idem que les classes.
• des valeurs des énumérations : /^([A-Z]_)+$/.
// définition d'une énumérations
visibilite enum NomEnum {
VALEUR1,
VALEUR2,
...
VALEURN
}
// méthodes
/*
* description : retourne l'ensemble des valeurs stockées dans l'énumération
sous forme d'un tableau d'éléments
*/
public static T[] values;
/*
* description : le nom de la valeur de l'énumération
*/
public String toString();
4. remarques :
• possibilité d’ajouter des attributs, des constructeurs et des
méthodes pour personnaliser la création des valeurs de
l’énumération et leurs comportements ;
• le constructeur n’aura aucun modificateur de visibilité et sera
déclaré privé par défaut pour préserver les valeurs définies
dans l’énumération.
2.8.3 Exemple
// l'énumération Langage
package generic.test;
/*values*/
JAVA("Langage JAVA", "Eclipse"),
C("Langage C", "Code Blocks"),
C_PLUS_PLUS("Langage CPlusPlus", "Visual Code"),
PHP("Langage PHP", "Visual Studio");
62
/*attributes*/
private String name = "";
private String editor = "";
/*constructor*/
Langage(String name, String editor){
this.name = name;
this.editor = editor;
}
/*methods*/
public void getEditor(){
System.out.println("Editeur " + this.editor);
}
//toString()
@Override
public String toString(){
return this.name;
}
}
// Classe de test
package generic.test;
2.9.1 Introduction
1. définition :
• les annotations sont des méta-données relatives à un pro-
gramme.
63
• méta-données : des informations qui peuvent être associées à des
éléments de code : classes, interfaces, variables, méthodes, pack-
ages
2. utilités :
• à la compilation ou au moment du déploiment :
1. le compilateur s’en sert pour détecter des erreurs et/ou pour
supprimer des warnings.
2. l’outil JDK javadoc s’en sert pour générer de la documen-
tation.
3. possibilité d’exploiter les annotations pour générer du
code, des fichiers XML de documentation, vérifier des
propriétés, etc.
• à l’exécution : certaines annotations peuvent être examinées
par introspection (cf. La réflexivité)
1. définir une annotation consiste à définir une interface avec une syn-
taxe particulière :
• préfixer interface par @ ;
• définir des méthodes :
1. définissant des sortes d’attributs avec possiblement des
valeurs par défaut ;
2. sans paramètres ;
3. sans une clause throws ;
4. ayant un type de retour vérifiant l’expression régulière :
/^(<type_primitif>|<type_complexe>|<enumeration>|annotation)(\[\])?$
2. syntaxe :
// définition d'une annotation
visibilite @interface NomAnnotation{
typeRetour1 methodeAnnotation1()[ default valeurDefaut1]
typeRetour2 methodeAnnotation2()[ default valeurDefaut2]
...
typeRetourN methodeAnnotationN()[ default valeurDefautN]
}
3. remarque : si l’annotation ne contient qu’une seule méthode, on
peut l’appeler value() ce qui simplifiera l’écriture des valeurs lors
de l’utilisation de l’annotation.
64
2. solution : composition d’annotations : une annotation peut se
composer d’autres annotations.
1. mode d’utilisation :
• placer l’annotation juste au dessus de l’élément concerné ;
• affecter une valeur à chaque méthode de l’annotation en sup-
primant ses parenthèses ;
• possiblement :
1. n’affecter aucune valeur à une méthode d’annotation pos-
sédant une valeur par défaut ;
2. omettre le nom de la méthode lors de l’affectation d’une
valeur si l’annotation ne contient qu’une seule méthode
nommée value().
2. syntaxe :
@<annotation>(
//affectation d'une valeur à toute méthode de l'annotation
methodeAnnotation1 = valeur1,
methodeAnnotation2 = valeur2,
...
methodeAnnotationN = valeurN
//éventuellement affecter une valeur à une méthode ayant une valeur par défaut
[, methodeAnnotationParDefaut1 = nouvelleValeur]
[, ...]
//éventuellement affecter une annotation à une méthode ayant
//comme type de retour annotation en adoptant le même mode d'utilisation
//ci-dessus pour affecter les valeurs à ses méthodes
[, methodeAnnotationRetourAnnotation = NomAnnotation(/*affectation de valeurs*/ )]
[, ...]
)
element[{/*code*/ }]
3. remarques :
• si un élément est annoté par plusieurs annotations, l’ordre de
leur utilisation n’est pas important.
• si une annotation est composée d’autres annotations, le mode
d’utilisation ci-dessus des annotations s’utilise récursivement
sur chacune d’elles (i.e. affecter une valeur à chaque méthode de
chaque annotation composante).
• si l’élément annoté désigne un package il faut :
1. créer un fichier package-info.java, placé automatiquement à
la racine du package à annoter ;
2. au sein du fichier créé, préfixer l’instruction package
nom.package; par le mode d’utilisation des annotations
65
ci-dessus pour annoter le package.
/*
* description : retourne true si l'annotation courante est
logiquement équivalent à l'annotation désigné par "obj",
false sinon
*/
boolean equals(Object obj);
/*
* description : retourne le code de hachage de l'annotation courante
*/
int hashCode();
/*
* description : retourne une description en String de l'annotation courante
*/
String toString();
66
3. effet : à la compilation :
• le compilateur vérifie qu’une méthode de signature compatible
(au sens de la redéfinition) existe dans une superclasse de la classe
courante.
• si la méthode annotée n’est héritée d’aucune superclasse, alors
on aura une erreur de compilation.
• si la méthode annotée est bien héritée mais n’a pas une signa-
ture compatible alors on aura une erreur de compilation.
67
2. description : l’annotation A portée par @Documented apparaîtra
dans la documentation générée par les outils de génération de doc-
umentation tels que Javadoc.
3. effet : à l’exécution.
68
il faut affecter les valeurs énumérées souhaitée de ElementType
pour indiquer les éléments de code qui peuvent être annotés par
l'annotation annotée
*/
public abstract ElementType[] value();
4. effet : à l’exécution.
69
// répéter l'annotation d'un élément annoté par A avec des
// valeurs différentes
A(valeur1)
A(valeur2)
...
A(valeurN)
element{/*code*/ }
4. méthode :
/*
* description : lors de l'utilisation de cette méthode d'annotation,
il faut affecter le fichier bytecode de l'annotation conteneur
de l'annotation A que l'on utilisera pour répéter l'utilisation
de l'annotation A sur un élément annoté par cette dernière
*/
public abstract Class<? extends Annotation> value();
5. effet : à l’exécution.
2.9.7 Javadoc
// remarque : on peut aussi inclure du code HTML dans les commentaires javadoc.
70
* mais non renseigné si la méthode n'admet pas de paramètres
* @return description du résultat retourné par
* un(e) méthode/ constructeur non renseigné si la méthode
* n'admet pas de type de retour
* @throws listeClassesException la liste des exceptions transmises par
* un(e) méthode/ constructeur quand elles sont levées, avec une
* description de la raison pour lever l'execption pour chaque exception
* @see Element un lien hypertext vers la documentation
* de l'élément référencé (une classe, méthode, etc.)
* @since classeVersion la version de la classe depuis laquelle
* l'élément documenté existe
* @deprecated indiquer que l'élément documenté est obsolète
* depuis une version spécifique et renseigner les éventuels
* éléments alternatives pouvant être utilisés.
**/
2.10.1 Introduction
1. définition : une collection Java est une classe définissant une struc-
ture de données destinée à regrouper plusieurs objets (e.g. une pile,
une file, une liste chaînée, un ensemble, un tableau associatif, etc.)
2. package : toutes les collections sont définies au sein du package
java.util (à importer manuellement).
3. description des méthodes : pour chaque type de collections sont
définies des méthodes permettant de :
• manipuler les éléments stockés : ajout/suppresion d’éléments.
• fournir des informations sur la collection manipulée : taille, si
la collection est vide, etc.
4. hiérarchie des collections :
• des interfaces :
1. rôle :
– fournir des méthodes communes à tous les types de
collection ;
– fournir des méthodes plus spécialisées à des collections
plus spécifiques.
71
2. exemples : java.util.Collection, java.util.Map,
java.util.List, java.util.Set, java.util.SortedSet,
java.util.SortedMap, etc.
• des classes abstraites :
1. rôle :
– factoriser du code ;
– implémenter quelques méthodes de quelques interfaces
qui seront communes à toutes leurs sous-classes con-
crètes ;
– proposer des méthodes abstraites supplémentaires.
2. exemples : java.util.AbstractMap, java.util.AbstractList,
etc.
• des classes concrètes :
1. rôle : implémenter les méthodes abstraites héritées depuis
des classes abstraites ou des interfaces relatives aux collec-
tions.
2. exemples : java.util.Vector, java.util.ArrayList,
java.util.Hashtable, etc.
5. remarque : depuis Java 5, les collections en Java implémentent
l’interface Iterable<T> qui permet de parcourir leurs éléments :
• via des itérateurs (cf. Les itérateurs) ;
• via des boucles for généralisées ou adaptées aux objets
itérables.
72
2.10.2 L’interface Collection<E>
/*
* retourne possiblement un stream parallèle sur les éléments de la
collection courante
* remarque : l'API des streams s'occupera de décomposer la requête
pour qu'elle soit exécutée en parallèle si
l'architecture de la machine le permet
*/
default Stream<E> parallelStream();
/*
73
* description : retourne true si "object" est contenu dans la liste,
false sinon
*/
public boolean contains(Object object);
/*
* description : retourne l'élément à l'index "index" de la liste
si "index" est valide, sinon lève l'exception IndexOutOfBoundException
*/
public E get(int index);
/*
* description : ajoute l'élément "element" à la fin de la liste et
retourne true en cas de succès, false sinon
*/
public boolean add(E element);
/*
* description : supprime l'élément à l'index "index" de la liste
si "index" est valide, sinon lève l'exception IndexOutOfBoundException
*/
public E remove(int index);
/*
* description : vide tout le contenu de la liste
*/
public void clear();
/*
* description : retourne un itérateur de listes sur la liste
*/
public ListIterator<E> listIterator();
74
5. quelques méthodes :
// mêmes méthodes que LinkedList<E>, avec les opérations suivantes
/*
* description : supprime "object" de la liste
s'il est contenu dedans et renvoie true,
sinon renvoie false
*/
public boolean remove(Object object);
/*
* description : retourne true si la liste est vide, false sinon
*/
public boolean isEmpty();
75
K getKey();
/*
* description : retourne la valeur de la paire
*/
V getValue();
/*
* description : écrase la valeur ancienne "old" de la paire par "value"
et retourne "old"
*/
V setValue(V value);
/*
* description : retourne true si le dictionnaire est vide, false sinon
*/
public boolean isEmpty();
/*
* description : retourne true si "key" est une clé du dictionnaire,
false sinon
*/
public boolean containsKey(Object key);
/*
* description : retourne true si "value" est une valeur associée
à une/plusieurs clés du dictionnaire, false sinon
*/
public boolean containsValue(Object value);
/*
* description : retourne la valeur indexée par la clé "key" dans le
dictionnaire, si "key" est une clé du dictionnaire,
sinon retourne null
76
*/
public V get(Object key);
/*
* description :
- si "key" est déjà une clé du dictionnaire,
écrase la valeur déjà présente par "value" et retourne la valeur écrasée
- sinon, ajoute la paire "key"/"value" au dictionnaire et retourne null
*/
public V put(K key, V value);
/*
* description :
- si "key" est une clé du dictionnaire, la supprime et
retourne la valeur qu'elle indexe
- sinon retourne null
*/
public V remove(Object key);
/*
* description : vide tout le contenu du dictionnaire
*/
public void clear();
/*
* description : retourne une énumération des clés du dictionnaire
*/
public Enumeration<K> keys();
/*
* description : retourne une énumération des valeurs indexées du dictionnaire
*/
public Enumeration<V> elements();
/*
* description : retourne une collection des valeurs indexées du dictionnaire
*/
public Collection<V> values();
77
2.10.5 L’interface Set
/*
* description : retourne true si l'ensemble est vide, false sinon
*/
public boolean isEmpty();
/*
* description : retourne true si "object" est contenu dans l'ensemble,
false sinon
*/
public boolean contains(Object object);
/*
* description : ajoute l'élément "element" à l'ensemble et
retourne true si l'ensemble contient déjà l'élément, false sinon
*/
public boolean add(E element);
/*
* description : supprime "object" de l'ensemble
s'il est contenu dedans et renvoie true,
78
sinon renvoie false
*/
public boolean remove(Object object);
/*
* description : vide tout le contenu de l'ensemble
*/
public void clear();
/*
* description : retourne un itérateur sur l'ensemble
*/
public Iterator<E> iterator();
/*
* description : renvoie un tableau contenant les éléments
de l'ensemble
*/
public Object[] toArray();
2.11.1 Introduction
79
• abstraction des détails d’implémentation du parcours d’un ob-
jet itérable par itérateur ;
• la structure interne de l’objet itérable peut changer, sans af-
fecter son parcours via un itérateur.
5. approche :
• l’objet itérable donne accès à un/plusieurs itérateurs via des
méthodes ;
• chaque itérateur possède des méthodes divers permettant de ma-
nipuler les éléments d’un objet itérable telles que :
1. savoir le premier élément, l’élément courant ou le prochain élé-
ment ;
2. savoir s’il existe un prochain élément ;
3. détruire l’élément courant ;
4. etc.
6. remarque : toutes les collections sont itérables.
80
2. description : une interface proposant les méthodes à implémenter par
n’importe quelle itérateur, paramétrée par le type des objets à itérer.
3. méthodes :
public interface Iterator<E>{
/*méthodes abstraites*/
/*
* description : renvoie true s'il existe encore des éléments à parcourir,
false sinon
*/
boolean hastNext();
/*
* description : renvoie le prochain élément à parcourir s'il en existe
sinon, lève l'exception NoSuchElementException
*/
E next(); //renvoie le prochain élément itéré
/*
* description : supprimer le dernier élément parcouru par l'itérateur
*/
default void remove();
/*
* description : appliquer le traitement "action" sur chaque élément
qu'il reste à parcourir jusqu'à la fin du parcours
ou jusqu'à ce que "action" lève une exception
*/
default void forEachRemaining(Consumer<? super E> action){
while(this.hastNext())
action.accept(this.next());
}
}
81
aux objets itérables, utilisant implicitement un itérateur
généré automatiquement pour ce faire.
3. méthodes :
public interface Iterable<T>{
/*méthodes abstraites*/
/*
* description : retourner un itérateur sur l'objet itérable
*/
Iterator<T> iterator();
/*
* description : appliquer le traitement "action" sur chaque élément
jusqu'à la fin du parcours ou jusqu'à ce que "action" lève une exception
*/
default void forEach(Consumer<? super E> action){
for (E element : this)
action.accept(element);
}
/*
* description : retourner un "spliterator" sur
les éléments de l'objet itérable
*/
default SplIterator<E> spliterator();
}
4. remarques :
• il est conseillé de supprimer un élément d’une collection
itérable pendant son parcours via la méthode remove()
de Iterator<E> et non pas via la méthode remove() de
Collection<E> qui pourra provoquer un comportement in-
défini.
• toutes les modifications nécessaires pour s’adapter à la sup-
pression d’un élément d’une collection itérable pendant son
parcours (i.e. changement de la taille de la liste, changement des in-
dexes, etc.) par la méthode remove() de Iterator<E> sont prises
en compte automatiquement par l’itérateur.
82
méthodes de parcours et de manipulation des éléments d’une liste
itérable plus efficaces et s’appliquant à des endroits précis de la liste.
3. quelques méthodes :
public interface ListIterator<E> extends Iterator<E>{
/*méthodes abstraites*/
/*
* description : renvoie true s'il existe encore des éléments à parcourir,
false sinon
*/
boolean hastNext();
/*
* description : renvoie le prochain élément à parcourir s'il en existe
sinon, lève l'exception NoSuchElementException
*/
E next(); //renvoie le prochain élément itéré
/*
* description : renvoie l'index du prochain élément à parcourir
s'il en existe, sinon retourne la taille de la liste
*/
int nextIndex();
/*
* description : renvoie true s'il existe encore des éléments à parcourir
dans le sens inverse, false sinon
*/
boolean hasPrevious();
/*
* description : renvoie le prochain élément à parcourir dans le sens inverse
s'il en existe, sinon lève l'exception NoSuchElementException
*/
E previous();
/*
* description : renvoie l'index du prochain élément à parcourir
dans le sens inverse, s'il en existe,
sinon retourne -1
*/
int previousIndex();
/*
* description : supprimer le dernier élément parcouru par l'itérateur
83
*/
void remove();
/*
* description : remplace le dernier élément parcouru par l'itérateur
par "object"
*/
void set(E object);
/*
* description :
- si l'élément suivant à parcourir est retourné par next(),
insère "object" juste avant l'élément
- si l'élément suivant à parcourir est retourné par previous(),
insère "object" juste après l'élément
- si la liste est vide, insère l'élément juste avant le curseur
implicite utilisé par l'itérateur
*/
void add(E object);
}
/*
* description : retourne le prochain élément à énumérer, s'il existe,
sinon lève l'exception NoSuchElementException
*/
E nextElement();
84
2.11.3 Exemple
// La classe BonbonPez
package iterators;
/*constructors*/
public BonbonPez() {}
public BonbonPez(String marque, double prix) {
this.marque = marque;
this.prix = prix;
}
/*methods*/
//Getters & setters
public String getMarque() {return this.marque;}
public void setMarque(String marque) {this.marque = marque;}
//toString
@Override
public String toString() {
return this.marque+" ("+this.prix+")";
}
}
// La classe DistributeurBonbonPez
package iterators;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
85
/*methods*/
public void remplit(HashMap<String, Double> bonbons) {
int i = 0;
for (Map.Entry<String, Double> entry: bonbons.entrySet()) {
if (i < 12) {
tube[i] = new BonbonPez(entry.getKey(), entry.getValue());
i++;
}
}
}
//toString
@Override
public String toString() {
String output = "";
for (BonbonPez bonbon : this.tube)
output += bonbon + " | ";
return output;
}
}
// La classe IterateurPez
package iterators;
import java.util.Iterator;
/*constructors*/
public IterateurPez(BonbonPez[] tube) {
this.tube = tube;
}
/*methods*/
//implemented Iterator<BonbonPez> methods
@Override
86
public boolean hasNext() {
return curseur < 12;
}
@Override
public BonbonPez next() {
BonbonPez bonbon = tube[curseur];
tube[curseur] = null;
curseur++;
return bonbon;
}
}
// La classe Test
package iterators;
import java.util.HashMap;
bonbons.put("Chocolat", 1.0);
bonbons.put("Framboise", 2.0);
bonbons.put("Cerise", 2.0);
bonbons.put("Vanille", 1.0);
bonbons.put("Menthe", 2.5);
bonbons.put("Ananas", 1.5);
bonbons.put("Pomme", 1.5);
bonbons.put("Lait", 2.0);
bonbons.put("Fraise", 1.5);
bonbons.put("Banane", 1.0);
bonbons.put("Figue", 1.8);
bonbons.put("Citron", 2.0);
87
}
}
88
2.12.1.3 La classe Collections
1. package : java.util (à importer manuellement)
2. description : une classe fournissant des méthodes statiques pour
manipuler des collections d’objets.
3. quelques méthodes :
/*
* description : méthode statique permettant de trier une liste
selon l'ordre naturel défini sur ses éléments de type T
(i.e. l'ordre défini via la méthode "compareTo()"
de l'interface "Comparable<T>")
*/
public static <T extends Comparable<? super T>> void sort(List<T> list);
/*
* description : méthode statique permettant de trier une liste
selon l'ordre défini par le comparateur "c" sur ses éléments de type T
(i.e. l'ordre défini via la méthode "compare()"
de l'interface "Comparator<T>")
*/
public static <T> void sort(List<T> list, Comparator<? super T> c);
2.12.2 Clonage
89
2.13 La généricité
2.13.1 Introduction
6. exemples :
• classe générique : pile paramétrée par le type T des éléments
stockés (Integer, String, Voiture, etc.) : Pile<T>.
• méthode générique : fonction de recherche paramétrée par
le type T des éléments à rechercher dans un tableau : boolean
recherche(T[] tableau, int taille, T element).
90
• principe : une stratégie “homogène” pour représenter la
généricité en utilisant une instance de la classe Object pour
désigner n’importe quel type possible et paramétrer le
concept ou la méthode.
• inconvénients :
1. faire des tests de type :
– code non extensible, vu qu’il faut faire un test de type
pour chaque type possible ;
– difficulté de contrôler les types.
2. faire des coercitions de type pour invoquer des méthodes
spécifiques au type réel sur un objet générique de type
Object.
2. approche depuis Java 5 :
• principe : une stratégie “hétérogène” pour représenter la
généricité en utilisant un type formel qui peut être lié à un
type réel parmis une gamme de types réels existants (ou
à venir) bien définie par des contraintes de liaison, et qui peut
paramétrer un concept ou une méthode.
• avantages :
1. permettre la généricité des classes, interfaces et méthodes
(d’instance ou de classe) ;
2. rendre l’API des collections générique ;
3. exemple :
/* instanciation d'une pile d'entiers, en utilisant le type complex "Integer"
* et non pas le type primitif "int"
*/
- Pile<Integer> pile = new Pile<Integer>();
/*
* (Depuis Java 7)
* syntaxe alternative en utilisant l'inférence automatique du type
* concret lié au paramètre formel d'un modèle générique
*/
- Pile<Integer> pile = new Pile<>();
91
• unboxing : une classe wrapper en un type primitif équivalent.
3. exemple :
int i = new Integer(12); // \equiv int i = 12; (unboxing)
double d = new Double(12.25); // \equiv double d = 12.25 (unboxing)
Double D = 12.0; // \equiv Double D = new Double(12.0) (boxing)
Character C = 'C'; // \equiv Character = new Character('C') (boxing)
92
Figure 9: “Généricité et Héritage en Java”
// une classe concrète héritant d'une instanciation complète d'une classe générique
public class Agenda extends Dictionnaire<Date, String>{/*code*/ }
1. principe :
• soient la classe générique Classe<T>, les classes concrètes A, B
, et les classes concrètes Classe<B> et Classe<A> obtenues par
l’instanciation de Classe<T> en liant le paramètre générique T
respectivement aux types concrets A et B.
• en supposant que B hérite de A, ceci n’implique pas que Classe<B>
hérite de Classe<A>.
2. justification : deux classes concrètes obtenues par l’instanciation
complète d’une même classe générique sont indépendantes du point
de vue de typage, quelles que soient les relations (e.g. héritage) qui
existent entre les types de leurs paramètres réels liés au paramètre
générique de la classe générique instanciée.
2.13.5.1 Introduction
93
Figure 10: “Généricité et Sous-typage en Java”
94
public interface Comparable<A>{/*code*/ }
public OrderedSet<A extends Comparable<A>>{/*code*/ }
/*
* lors de l'instanciation d'une classe générique
*/
ClasseGenerique<?> cg = new ClasseGenerique<TypeConcret>();
/*
* lors de la définition d'une méthode dont le type générique
* ne figure pas dans son corps
*/
portee [static] typeRetour nomMethode(ClasseGenerique<?,?> instance){
// instructions ne contenant pas le paramètre générique de la méthode
}
/*
*- remarque : avec cette utilisation, on ne peut pas
utiliser des expressions nécessitant de connaître le type du paramètre
générique à la compilation
*/
Paire<?, ?> paire = new Paire<Integer, String>();
// pas d'erreur parce que toString() ne dépend pas du type générique
95
System.out.println(paire);
// erreur de compilation, parce que setFirst() dépend du type générique
paire.setFirst(12);
/*
* Utilisation 2
*==============
* utilisation de "?" avec le mot-clé "extends" pour rendre
* le type générique instanciable
* par n'importe quel type concret et :
1. toutes ses sous-classes (si type concret = classe (abstraite))
2. toutes ses sous-interfaces ou classes l'implémentant
(si type concret = interface)
*/
/*
*lors de l'instanciation d'une classe générique
*/
ClasseGenerique<? extends TypeConcret> instanceConcrete = new ClasseGenerique<>([params]);
/*
/*
* lors de la définition d'une méthode dont le type générique
* ne figure pas dans son corps
*/
visibilite [static] typeRetour nomMethodeGenerique(? extends TypeConcret[, params]){/*code*/
/*
* Utilisation 3
*==============
* utilisation de "?" avec le mot-clé "super" pour rendre
* le type générique d'une classe générique instanciable
* par n'importe quel type concret et :
1. toutes ses superclasses (si type concret = classe (abstraite))
2. toutes ses super-interfaces (si type concret = interface)
*/
/*
*lors de l'instanciation d'une classe générique
*/
ClasseGenerique<? super TypeConcret> instanceConcrete = new ClasseGenerique<>([params]);
/*
/*
* lors de la définition d'une méthode dont le type générique
* ne figure pas dans son corps
96
*/
visibilite [static] typeRetour nomMethodeGenerique(? super TypeConcret[, params]){/*code*/ }
5. exemples de l’API Java :
class AbstractCollection<E>{
...
public boolean addAll(Collection<? extends E> c){/*code*/ }
...
}
class LinkedBlockingQueue<E>{
public int drainTo(Collection<? super E> c){/*code*/ }
}
97
// avant l'effacement de type
class Paire<A, B>{
private A first;
private B second;
...
}
2.13.7 Exemple
import java.util.Collection;
import java.util.List;
/*constructors*/
public Paire(){}
public Paire(A first, B second){
this.first = first;
this.second = second;
}
/*methods*/
//getters
public A getFirst(){return first;}
public B getSecond(){return second;}
98
//setters
public void setFirst(A first){this.first = first;}
public void setSecond(B second){this.second = second;}
//toString
@Override
public String toString(){
return "(" + first + ", " + second + ")";
}
//other methods
public static <X> void copyFirstTab(Paire<X, ?> p, X tab[], int i){
if (i>=0 && i<tab.length)
tab[i] = p.getFirst();
}
// L'interface Saisissable
package genericity.test;
import java.util.Scanner;
// La classe StringSaisissable
package genericity.test;
import java.util.Scanner;
99
private String string;
/*constructors*/
public StringSaisissable(String string){this.string = string;}
/*methods*/
//toString
@Override
public String toString(){
return this.string;
}
// La classe PaireSaisissable
package genericity.test;
import java.util.Scanner;
/*constructors*/
public PaireSaisissable(){}
public PaireSaisissable(A first, B second){
this.first = first;
this.second = second;
}
/*methods*/
//getters
public A getFirst(){return first;}
public B getSecond(){return second;}
//setters
public void setFirst(A first){this.first = first;}
public void setSecond(B second){this.second = second;}
100
//toString
@Override
public String toString(){
return "(" + first + ", " + second + ")";
}
// La classe Test
package generics;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
101
List<Integer> li = new LinkedList<>();
lo.add(5);
li.add(5);
p3.takeListFirst(lo);
/*
* marche bien parce que Integer est une sous-classe d'Object
* et on a spécifié ? extends A pour le paramètre générique
* utilisé comme paramètre de la méthode prendreListFirst()
*/
p3.takeListFirst(li);
Paire<Integer, Integer> p4 = new Paire<Integer, Integer>(9, 10);
Collection<Object> co = new LinkedList<Object>();
/*
* marche bien parce que Object est une super-classe d'Integer
* et on a specifié ? super A pour le paramètre générique
* utilisé comme paramètre de la méthode copyFirstColl(
*/
p4.copyFirstToCollection(co);
}
}
2.14.1 Introduction
102
3. System.err : sortie standard des erreurs (par défaut, l’écran).
/*
* description : récupérer la ligne parsée par le scanner sous forme d'un int
sans positionner la tête de lecture au début de la ligne suivante
(doit être suivie d'un appel à nextLine() pour ce faire)
* remarques :
- des méthodes ayant la signature nextType() sont définies pour
tous les autres types primitifs (byte, short, long, float, double, boolean)
sauf "char", qui peut être récupéré à partir de nextLine()
*
*/
public int nextInt();
/*
* description : retourne true si le chemin désigne un fichier,
false sinon
*/
public boolean isFile();
103
/*
* description : retourne true si le chemin désigne un dossier,
false sinon
*/
public boolean isDirectory();
/*
* description : retourne le nom du fichier désigné par le chemin
*/
public String getName();
/*
* description : retourne le chemin absolu du fichier désigné par le chemin
*/
public String getAbsolutePath();
/*
* description : retourne le nom du dossier parent du
fichier désigné par le chemin,
*/
public String getParent();
/*
* description : retourne la liste des fichiers/dossiers contenus
dans le dossier désigné par le chemin
*/
public File[] listFiles();
/*
* description : retourne la liste des dossiers racines
du système de fichier de la machine
*/
public static File[] listRoots();
/*
* description : supprime le fichier/dossier désigné par le chemin
et retourne true si le fichier/dossier est supprimé, false sinon
*/
public boolean delete();
/*
* description : créer un dossier désigné par le chemin
et retourne true si le dossier est créé, false sinon
*/
public boolean mkdir();
104
2.14.1.3.1 Exemple
package iostreams;
import java.io.File;
try {
int i = 1;
if (i%4 == 0)
System.out.println("\n");
i++;
}
} catch (NullPointerException e) {
continue;
}
}
}
}
2.14.2.1 Introduction
105
Description : le premier package de Java pour les E/S. Il permet de créer des
flux de lecture/d’écriture d’octets/de caractères pour plusieurs types
de sources de données, et propose des mécanismes permettant de pré-
traiter les données avant d’effectuer les opérations d’E/S.
/*
* description : fermer le flux et libérer les ressources associées
*/
public void close() throws IOException;
106
Figure 12: “Hiérarchie des classes Reader et Writer de java.io en Java”
107
2.14.2.3 La classe OutputStream
1. package : java.io (à importer manuellement)
2. description : une classe abstraite, superclasse de toutes les classes
modélisant des flux d’écriture d’octets dans une destination.
3. quelques méthodes :
/*
* description : écriture de b.length octets dans un flux d'écriture
*/
public void write(byte[] b) throws IOException;
/*
* description : fermer le flux et libérer les ressources associées
*/
public void close() throws IOException;
108
2.14.2.5.1 Exemple
package iostreams;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
System.out.println();
buffer = new byte[8];
}
System.out.println("Copie terminée");
} catch(IOException e) {
e.printStackTrace();
}
}
}
109
2.14.2.7 La classe FilterOutputStream
1. package : java.io (à importer manuellement)
2. description : une classe abstraite, superclasse de toutes les classes
modélisant des fonctionnalités pour traiter et/ou transformer les
octets à écrire à partir d’un flux d’écriture de base encapsulé avant
de les écrire dans la destination.
2.14.2.9.1 Exemple
package iostreams;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
110
/*préparation d'un buffer pour la lecture*/
byte[] buffer = new byte[8];
} catch (IOException e) {
e.printStackTrace();
}
}
}
111
/*
* description : lecture des octets en tant qu'un "char"
du flux de lecture
*/
public final char readChar() throws IOException;
/*
* description : lecture des octets en tant qu'un "byte"
du flux de lecture
*/
public final byte readByte() throws IOException;
/*
* description : lecture des octets en tant qu'un "short"
du flux de lecture
*/
public final short readShort() throws IOException;
/*
* description : lecture des octets en tant qu'un "int"
du flux de lecture
*/
public final int readInt() throws IOException;
/*
* description : lecture des octets en tant qu'un "long"
du flux de lecture
*/
public final long readLong() throws IOException;
/*
* description : lecture des octets en tant qu'un "float"
du flux de lecture
*/
public final float readFloat() throws IOException;
/*
* description : lecture des octets en tant qu'un "double"
du flux de lecture
*/
public final int readDouble() throws IOException;
112
1. package : java.io (à importer manuellement)
2. description : une classe permettant d’écrire directement des types
primitifs dans le flux d’écriture encapsulé.
3. quelques méthodes :
/*
* description : écriture d'un booléen "v" dans le flux d'écriture
*/
public final void writeBoolean(boolean v) throws IOException;
/*
* description : écriture d'un entier "v" en tant que "char"
* dans le flux d'écriture
*/
public final void writeChar(int v) throws IOException;
/*
* description : écriture d'un String "v" dans le flux d'écriture
le flux
*/
public final void writeChars(String v) throws IOException;
/*
* description : écriture d'un entier "v" en tant que "byte"
* dans le flux d'écriture
*/
public final void writeByte(int v) throws IOException;
/*
* description : écriture d'un entier "v" en tant que "short"
* dans le flux d'écriture
*/
public final void writeShort(int v) throws IOException;
/*
* description : écriture d'un entier "v"
* dans le flux d'écriture
*/
public final void writeInt(int v) throws IOException;
/*
* description : écriture d'un long "v"
* dans le flux d'écriture
*/
public final void writeLong(long v) throws IOException;
113
/*
* description : écriture d'un float "v"
* dans le flux d'écriture
*/
public final void writeFloat(float v) throws IOException;
/*
* description : écriture d'un double "v"
* dans le flux d'écriture
*/
public final void writeDouble(int v) throws IOException;
2.14.2.12.1 Exemple
package iostreams;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
try {
//création du fichier et écriture de types primitifs dedans
dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("sdz.txt")));
dos.writeBoolean(true);
dos.writeChar('C');
dos.writeByte(100);
dos.writeShort(2);
dos.writeInt(1024);
dos.writeLong(123456789L);
dos.writeFloat(100.52f);
dos.writeDouble(12.05);
dos.close();
114
//lecture des types primitifs du fichier
dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream("sdz.txt")));
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
dis.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(dis != null)
dis.close();
if(dos != null)
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
115
2.14.2.14 Le mot-clé transient
Un attribut précédé par transient sera ignoré lors de la sérialisation.
2.14.2.16.1 Exemple
// La classe Notice dont les objets ne seront pas sérialisés
package iostreams;
/*constructors*/
public Notice() {
this.langue = "Français";
}
116
/*methods*/
//toString
@Override
public String toString() {
return "Langue de la notice : " + langue;
}
}
import java.io.Serializable;
/*constructors*/
public Game(String nom, String style, double prix) {
super();
this.nom = nom;
this.style = style;
this.prix = prix;
this.notice = new Notice();
}
/*methods*/
//Getters & setters
public String getNom() {
return nom;
}
117
public double getPrix() {
return prix;
}
//toString
@Override
public String toString() {
return "Game [nom=" + nom + ", style=" + style + ", prix=" + prix + "]";
}
}
// La classe Test
package iostreams;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
try {
//création d'un fichier et sérialisation d'objets dedans
oos = new ObjectOutputStream(
new BufferedOutputStream(
118
new FileOutputStream("game.txt")));
oos.close();
games.add((Game)ois.readObject());
games.add((Game)ois.readObject());
games.add((Game)ois.readObject());
} catch(IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (ois != null)
ois.close();
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
119
2.14.2.18 La classe ByteArrayOutputStream
1. package : java.io (à importer manuellement)
2. description : idem que la classe BufferedOutputStream mais un peu
plus limitée.
/*
* description : écriture d'un tableau de caractères dans
le flux d'écriture
*/
public void write(char[] cbuf) throws IOException;
/*
* description : écriture d'un string dans
le flux d'écriture
*/
public void write(String str) throws IOException;
120
2. description : une classe désignant un tampon de caractères de taille
adaptative utilisé comme intermédiaire lors de la lecture depuis le
flux de lecture de caractères.
3. remarque : la méthode void close() n’a aucun effet sur un
CharArrayReader.
/*
* description : convertit les caractères du tampon en un String
et le retourne
*/
public String toString();
/*
* description : retourne la taille du tampon
*/
public int size();
/*
* description : vide le contenu du stream
*/
public char[] reset();
4. remarque : la méthode void close() n’a aucun effet sur un
CharArrayWriter.
2.14.2.23 Exemple
package iostreams;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
121
public class Test {
try {
//écriture de caractères dans le flux d'écriture de caractères
caw.write("Hey there everyone");
System.out.println(caw);
/*
* création d'un flux de lecture de caractères sur
* le contenu du flux d'écriture
*/
car = new CharArrayReader(caw.toCharArray());
} catch (IOException e) {
e.printStackTrace();
}
}
}
122
1. package : java.io (à importer manuellement)
2. description : une classe désignant un tampon de taille adap-
tative utilisé comme un intermédiaire lors de l’écriture dans le
flux d’écriture de caractères et qui peut être utilisé ensuite pour
construire un String.
3. remarques :
• mêmes méthodes que CharArrayWriter.
• la méthode void close() n’a aucun effet sur un StringWriter.
2.14.2.26 Exemple
package iostreams;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
try {
//écriture de caractères dans le flux d'écriture d'un string
sw.write("Hey there everyone");
System.out.println(sw);
/*
* création d'un flux de lecture de string depuis
* le contenu du flux d'écriture du string
*/
sr = new StringReader(sw.toString());
123
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
124
* remarque : T peut désigner : boolean, int, long, float,
double, char, char[], String, Object
*/
public void print(T object)
/*
* description : imprimer l'objet de type T dans le flux
avec un retour à la ligne
* remarque : T désigne les mêmes types que ceux utilisés
avec la méthode print(T object)
*/
public void println(T object)
/*
* description : impression formatée d'objets (printf() du langage C)
*/
public PrintWriter printf(String format, Object ... args);
2.14.2.31.1 Exemple
package iostreams;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
try {
//création d'un flux d'écriture de caractères dans un fichier
fw = new FileWriter("test_fw.txt");
String content = "Bonjour à tous mes amis !\n"
+ "\tComment allez vous ?\n";
fw.write(content);
fw.close();
125
int i;
content = "";
while((i = fr.read()) != -1)
content += (char) i;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fw != null)
fw.close();
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.14.3.1 Introduction
1. description :
• le package de Java pour les E/S depuis Java 4 (nio = New I/O),
améliorant les performances sur le traitement des fichiers, du
réseau et des buffers, en traitant les données par blocs au lieu
d’octets/caractères et en permettant d’effectuer des E/S non blo-
quantes.
• il est surtout utilisé pour le traitement des flux sur le réseau,
pour faire de la programmation distribuée et pour permettre
l’évolutivité des serveurs.
2. concepts fondateurs :
• canal ou channel : un flux de lecture/écriture sur une source
de données amené à travailler avec un buffer dont nous définis-
sons la taille.
• tampon ou buffer : un stockage intermédiaire des données.
• sélecteur ou selector : un multiplexeur permettant de choisir
un canal parmis plusieurs pour permettre la concurrence et
126
l’aspect non bloquant des E/S.
/*
* description : écrire la séquence d'octets depuis le ByteBuffer
dans le canal
et retourne le nombre d'octets écrits
*/
public int write(ByteBuffer source) throws IOException;
/*
* description : retourne la taille du fichier du canal
*/
public long size() throws IOException;
127
*/
public final int capacity();
/*
* description : met "position" à 0, "limit" à "capacity"
et prépare le buffer pour l'écriture
(i.e. lire depuis un canal)
*/
public final Buffer clear();
/*
* description : met "limit" à "position", remet "position" à 0
et prépare le buffer pour la lecture
(i.e. écrire dans un canal)
*/
public final Buffer flip();
/*
* description : remet "position" à 0 et
prépare le buffer pour la lecture
(i.e. écrire dans un canal)
*/
public final Buffer rewind();
/*
* description : retourne le contenu du buffer sous forme d'un array
*
* remarque : est spécialisé pour retourner le buffer
selon le type primitif de la classe l'implémentant
par exemple Object -> byte[] pour un ByteBuffer
*/
public abstract Object array();
128
Figure 13: “Hiérarchie des Buffers de java.nio en Java”
129
pour un buffer de type "byte"
*/
public static CharBuffer allocate(int capacity)
2.14.3.10.1 Exemple
130
package iostreams;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
while(bis.read() != -1);
} catch (IOException e) {
e.printStackTrace();
131
}
}
}
2.14.4.1 Introduction
1. description : un package définissant des charsets, encodeurs et dé-
codeurs pour faire des traductions entre les octets et les caractères
Unicode.
/*
* description : le charset ISO Latin 1
*/
public static final Charset ISO_8859_1;
/*
* description : le charset UTF-8
*/
public static final Charset UTF_8;
132
2.14.5 Le package java.nio.file
2.14.5.1 Introduction
1. description : une amélioration du package java.nio pour les E/S
depuis Java 7, notamment pour les systèmes de fichiers.
2. nouveautés :
• meilleure gestion des exceptions de la classe java.io.File ;
• accès complet au système de fichiers avec le support des liens
durs et symboliques ;
• introduction de méthodes utilitaires sur les chemins des
fichiers/dossiers via la classe java.nio.file.Files : déplace-
ment et copie de fichier, lecture/écriture binaire du texte, etc.
;
• remplacement de java.io.File par l’interface java.nio.file.Path.
3. remarque : la classe java.io.File est toujours utilisable pour la
rétrocompatibilité, mais l’interface java.nio.file.Path est à priv-
ilégier.
/*
* description : crée un dossier ayant le chemin "dir"
selon les propriétés du fichier spécifiées par "attrs"
et retourner son chemin
*/
public static Path createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException;
/*
* description : retourne true si le fichier
désigné par le chemin "path" existe, false sinon
et retourner son chemin
*/
public static boolean exists(Path path, LinkOption... options);
133
/*
* description : supprimer un fichier/dossier ayant le chemin "path"
*/
public static void delete(Path path) throws IOException;
/*
* description : supprimer un fichier/dossier ayant le chemin "path"
s'il existe et retourner true si le fichier est supprimé
false sinon (i.e. s'il n'existe pas)
*/
public static boolean deleteIfExists(Path path) throws IOException;
/*
* description : retourne true si le fichier
désigné par le chemin "path" est un dossier, false sinon
*/
public static boolean isDirectory(Path path);
/*
* description : copier le contenu du fichier désigné par "source"
dans le fichier désigné par "destination" selon les options de
copie spécifiées par "options"
et retourner le chemin de la destination
*/
public static Path copy(Path source, Path destination, CopyOption... options)
throws IOException;
/*
* description : déplacer/renommer le fichier désigné par "source"
(vers l'endroit désigné) par "destination" selon les options de
copie spécifiées par "options"
et retourner le chemin de la destination
*/
public static Path move(Path source, Path destination, CopyOption... options)
throws IOException;
/*
* description : écrire les octets dans le tableau d'octets "bytes"
dans le fichier désigné par "path" ouvert selon
les options spécifiées par "options"
et retourne le chemin du fichier
*/
public static Path write(Path path, byte[] bytes, OpenOption... options)
throws IOException;
134
/*
* description : ouvre un dossier et retourne
un "DirectoryStream" pour itérer sur les entrées
du dossier ouvert
*/
public static DirectoryStream<Path> newDirectoryStream(Path dir)
throws IOException;
/*
* description : ouvre un dossier et retourne
un "DirectoryStream" pour itérer sur les entrées
du dossier ouvert et filtrer ceux ne matchant pas
le motif spécifié par "pattern"
*/
public static DirectoryStream<Path> newDirectoryStream(Path dir, String pattern)
throws IOException;
/*
* description : ouvre un fichier avec un "InputStream" selon les options
spécifiées par "options"
et retourne un flux de lecture dessus
*/
public static InputStream newInputStream(Path path, OpenOption... options)
throws IOException;
/*
* description : ouvre un fichier avec un "OutputStream" selon les options
spécifiées par "options"
et retourne un flux d'écriture dessus
*/
public static OutputStream newOutputStream(Path path, OpenOption... options)
throws IOException;
/*
* description : ouvre un fichier avec un "BufferedReader"
*/
public static BufferedReader newBufferedReader(Path path)
throws IOException;
/*
* description : ouvre un fichier avec un "BufferedReader"
et l'encodage "cs"
*/
public static BufferedReader newBufferedReader(Path path, Charset cs)
throws IOException;
135
/*
* description : ouvre un fichier avec un "BufferedWriter" selon les options
d'ouverture spécifiées par "options"
et retourne un flux d'écriture dessus
*/
public static BufferedReader newBufferedWriter(Path path, OpenOption... options)
throws IOException;
/*
* description : ouvre un fichier avec un "BufferedWriter"
et l'encodage "cs" selon les options
d'ouverture spécifiées par "options"
et retourne un flux d'écriture dessus
*/
public static BufferedReader newBufferedWriter(Path path, Charset cs, OpenOption... options)
throws IOException;
/*
* description : retourne un stream contenant les lignes du fichier
désigné par le chemin "path"
*/
public static Stream<String> lines(Path path) throws IOException;
/*
* description : retourne un stream contenant les lignes du fichier
désigné par le chemin "path" selon le charset "cs"
*/
public static Stream<String> lines(Path path, Charset cs) throws IOException;
/*
* description : retourne le nom du fichier désigné par
le "Path" courant sous forme d'un "Path"
*/
136
Path getFileName();
/*
* description : retourne le nom du dossier parent du
fichier désigné par le "Path" courant sous forme d'un "Path"
*/
Path getParent();
/*
* description : retourne un "Path" à partir d'une URI
*/
public static Path get(URI uri);
137
/*
* description : retourne le système de fichiers par défaut
*/
public static FileSystem getDefault();
138
2. description : une interface marqueur définissant la manière de dé-
placer/copier un fichier.
/*
* description : la valeur de la propriété
*/
T value();
2.14.5.13.1 Exemples
// Exemple d'utilisation des paths
package iostreams;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Hashtable;
139
System.out.println("File is directory ? " + Files.isDirectory(path));
System.out.println("File name : " + path.getFileName());
System.out.println("File parent : " + path.getParent());
System.out.println("File absolute path : " + path.toAbsolutePath() + "\n");
}
try {
//créer un dossier
System.out.println("Before creating directory: ");
properties(paths.get("created"));
Files.createDirectories(paths.get("created"));
//créer un fichier
System.out.println("Before creating file: ");
properties(paths.get("test/created.txt"));
Files.createFile(paths.get("test/created.txt"));
//copier un fichier
System.out.println("Before copying file: ");
properties(paths.get("test/copy.txt"));
Files.copy(paths.get("test/test.txt"), paths.get("test/copy.txt"),
StandardCopyOption.REPLACE_EXISTING);
140
System.out.println("After copying file: ");
properties(paths.get("test/copy.txt"));
//renommer un fichier
System.out.println("Before renaming file: ");
properties(paths.get("test/renamed.txt"));
Files.move(paths.get("test/copy.txt"), paths.get("test/renamed.txt"),
StandardCopyOption.REPLACE_EXISTING);
//déplacer un fichier
System.out.println("Before moving file: ");
properties(paths.get("moved.txt"));
Files.move(paths.get("test/renamed.txt"), paths.get("moved.txt"),
StandardCopyOption.REPLACE_EXISTING);
//supprimer un fichier
System.out.println("Before deleting file: ");
properties(paths.get("test/to_be_deleted.txt"));
Files.delete(paths.get("test/to_be_deleted.txt"));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("After creation of directory: ");
}
}
/*
* Exemple d'itération sur le contenu des racines du FS
en utilisant DirectoryStream
*/
package iostreams;
141
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
int i = 0;
//afficher uniquement les fichiers anciens de la racine
System.out.println("Fichiers anciens de la racine");
System.out.println("===========================");
for (Path oldFile: oldFiles) {
System.out.println("\t\t" + oldFile);
i++;
checkForNewLine(i);
}
System.out.println();
i = 0;
//afficher tout le contenu de la racine
System.out.println("contenu de la racine");
System.out.println("===========================");
for(Path file: listing) {
System.out.println("\t\t" + file + (Files.isDirectory(file)? "/" : ""));
i++;
checkForNewLine(i);
}
142
} catch(IOException e) {
e.printStackTrace();
}
}
}
}
2.15.1 Introduction
1. définition : une classe imbriquée est une classe définie au sein d’une
autre classe, appelée la classe englobante.
2. utilités : structuration thématique du code (idem que les packages,
mais moins verbeux)
3. contraintes d’utilisation :
• selon la visibilité choisie pour la classe imbriquée, celle-ci peut
être cachée au monde extérieur et uniquement accessible par
sa classe englobante ;
• sous certaines conditions, la classe imbriquée aura accès à la
partie privée de la classe englobante et inversement.
4. types :
• classes imbriquées statiques (nested static classes)
• classes imbriquées non statiques incluant :
1. les classes internes ;
2. les classes locales ;
3. les classes anonymes.
143
1. si Imbr est public, alors elles auront le même comportement
que la classe Engl.
2. si Imbr est private, alors elles n’auront aucun accès à Imbr.
3. si Imbr est protected ou sans visibilité :
– si Cs sont dans le même package que Imbr ou l’héritent,
alors elles auront le même comportement que la classe
Engl.
– sinon, n’auront aucun accès à Imbr
3. syntaxes :
// instanciation de la classe imbriquée statique
// syntaxe à privilégier
Engl.Imbr inst = new Engl.Imbr();
/*
* syntaxe alternative équivalente, mais à éviter
car ne permet pas de préciser qu'il s'agit d'une classe
imbriquée statique
*/
Imbr inst = new Imbr();
4. exemple :
// La classe Liste
package nested_classes;
/*constructors*/
public Cellule() {}
public Cellule(int value) {
this.value = value;
}
/*methods*/
public String essai() {
Liste l = new Liste();
return "" + Liste.nbListes + l.premier;
144
}
//ToString
@Override
public String toString() {
return String.valueOf(this.value);
}
/*constructors*/
public Liste() {
this.premier = null;
Liste.nbListes++;
}
/*methods*/
public int getPremier() {return this.premier.value;}
public static int getNbListes() {return Liste.nbListes;}
//ToString
@Override
public String toString() {
String output = "(";
Liste.Cellule cell = this.premier;
while(cell != null) {
output += cell.toString() + " ";
cell = cell.suivante;
}
output += ")";
return output;
}
}
145
// La classe Test
package nested_classes;
l.ajouteTete(10);
System.out.println(l); // (10)
l.ajouteTete(20);
System.out.println(l); // (20 10)
l.ajouteTete(30);
System.out.println(l); // (30 20 10)
System.out.println("Nombre de listes créées " + Liste.getNbListes()); // 1
l = new Liste();
System.out.println("Nombre de listes créées " + Liste.getNbListes()); // 2
}
}
146
2. une instance de la classe Internal ne peut accéder aux at-
tributs d’une instance Engl si cette dernière ne lui est pas
associée.
3. utilisation :
• création d’une instance de la classe englobante Engl.
• création d’une/plusieurs instances de la classe interne
Internal exclusivement à travers l’instance créée de la classe
englobante Engl.
4. syntaxes :
// création d'une instance de la classe englobante
Engl englobante = new Engl();
/*
* référencement des propriétés de la classe englobante dans le corps d'une
méthode de la classe interne
*/
Engl.this.attribut; // référencer un attribut de la classe englobante
Engl.this.methode(); // invocation d'une méthode de la classe englobante
5. exemple :
// La classe Personne
package nested_classes;
/*inner class*/
protected class Adresse{
/*attributes*/
private String ville = "N/A";
private String pays = "N/A";
/*constructor*/
public Adresse(String ville, String pays) {
this.ville = ville;
this.pays = pays;
}
/*methods*/
//ToString
147
@Override
public String toString() {
return this.ville + ", " + this.pays;
}
} //end of Adresse inner class
/*constructors*/
public Personne(String nom, String ville, String pays) {
this.nom = nom;
this.adresse = new Personne.Adresse(ville, pays);
}
/*methods*/
//Getters & Setters
public String getNom() {return this.nom;}
public void setNom(String nom) {this.nom = nom;}
//ToString
@Override
public String toString() {
return this.nom + " habite à " + this.adresse;
}
}
// La classe Test
package nested_classes;
148
}
}
class Local{
/*corps*/
}
import java.util.Scanner;
149
public class Autorisation {
/*attributes*/
private int num;
/*constructors*/
public Autorisation() {}
/*methods*/
public String saisieNumTel(Scanner scanner) {
System.out.println("Saisie numéro de téléphone");
String code = "+";
/*local class*/
class NumTel{
/*attributes*/
private String indicatif;
private String numeroLocal;
/*methods*/
public String saisie(Scanner scanner) {
System.out.println("Saisie indicatif");
this.indicatif = scanner.next();
// La classe Test
package nested_classes;
import java.util.Scanner;
150
}
}
1. définition :
• une variante d’une classe locale ne possèdant pas de nom.
• une expression de définition et d’instanciation simultanée
d’une classe à une seule utilisation.
2. utilisation :
• création d’un concept support abstrait (classe abstraite ou inter-
face) ;
• création d’une classe anonyme fournissant des implémentations
des éléments abstraits (i.e. méthodes abstraites) du concept
support créé.
3. propriétés :
• ne peuvent pas être déclarées abstract ou static ;
• ne peuvent pas définir de constructeur ;
• automatiquement déclarées final et donc ne permettent pas
l’héritage.
4. syntaxes :
// définition du concept support sous forme d'une interface
visibilite interface ISupport{
/*autres éléments*/
typeRetour1 nomMethod1([params]);
typeRetour2 nomMethod2([params]);
...
typeRetourK nomMethod3([params]);
}
151
visibilite typeRetour nomMethode([params]){
import java.util.Scanner;
// La classe AutorisationAnonyme
package nested_classes;
import java.util.Scanner;
/*methods*/
public String saisieNumTel(Scanner scanner) {
System.out.println("Saisie numéro de téléphone");
String code = "+";
/*classe anonyme*/
Saisissable saisissable = new Saisissable() {
/*attributes*/
private String indicatif;
private String numeroLocal;
152
/*methods*/
@Override
public String saisie(Scanner scanner) {
System.out.println("Saisie indicatif");
this.indicatif = scanner.next();
}
}; //fin de la classe anonyme
return code + saisissable.saisie(scanner);
}
}
// La classe Test
package nested_classes;
import java.util.Scanner;
2.16.1 Introduction
153
2.16.2 Interfaces fonctionnelles
2.16.2.1 Introduction
1. définition : Une interface fonctionnelle est une interface devant re-
specter les contraintes suivantes :
• a exactement une méthode abstraite qui n’a pas la même
signature qu’une méthode de la classe Object (on parle d’une
interface SAM ou Single Abstract Method interface) ;
• peut être introduite via l’annotation FunctionalInterface
(recommandé mais non obligatoire).
• peut hériter de plusieurs méthodes abstraites qui peuvent se
substituer les unes aux autres à condition que l’une soit plus spé-
cifique que l’autre ;
• peut avoir des méthodes default ou static ;
2. utilité : une instance d’une interface fonctionnelle est une lambda
expression ou une référence de méthode/constructeur (i.e. une fonc-
tion du premier ordre).
3. conception en Java : une hiérarchie d’interfaces fonctionnelles :
• package : java.util.function.
• contenu : signatures de méthodes du premier ordre.
4. exemple d’application en Java : dans le cadre des streams, des
méthodes qui attendent des instances d’interfaces fonctionnelles
en paramètre incluent : filter(), map(), forEach(), etc.
154
@FunctionalInterface
public interface Function<T, R> {
/*
* description : une fonction invoquée sur un paramètre de type générique "T"
et retournant un résultat de type "R"
*/
R apply(T t);
/*
* description : applique la fonction appelante sur l'entrée
puis applique "after" sur le résultat R1 de l'application de la fonction
courante, et retourne le résultat final
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after);
}
2.16.2.3.1 Exemple
package function;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
/*
* description : méthode prenant une liste de Personne et utilisant
* l'interface fonctionnelle "func" pour retourner leurs noms
*/
public static List<String> transformToListString(List<Personne> list,
Function<Personne, String> func){
List<String> names = new ArrayList<>();
return names;
}
/*
* description : méthode prenant une liste de Personne et utilisant
* l'interface fonctionnelle "func" pour retourner leurs ages
*/
155
public static List<Integer> transformToListInt(List<Personne> list,
Function<Personne, Integer> func){
List<Integer> ages = new ArrayList<>();
return ages;
}
156
2.16.2.5 L’interface fonctionnelle DoubleFunction<R>
1. package : java.util.function (à importer manuellement)
2. description : une interface fonctionnelle générique acceptant en
entrée un paramètre de type double et renvoyant un résultat de
type générique R.
3. quelques méthodes :
/**
* description : une fonction invoquée sur un paramètre de type "double"
et retournant un résultat de type générique "R"
*/
@FunctionalInterface
public interface DoubleFunction<R> {
R apply(double value);
}
157
public interface ToDoubleFunction<T> {
double applyAsDouble(T value);
}
2.16.2.9.1 Exemple
package function;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
158
public static void main(String[] args) {
List<Personne> personnes = Arrays.asList(
new Personne(10, "toto"),
new Personne(20, "titi"),
new Personne(30, "tata"),
new Personne(40, "tutu")
);
2.16.2.10.1 Exemple
package function;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
159
List<Personne> personnes = Arrays.asList(
new Personne(10, "toto"),
new Personne(20, "titi"),
new Personne(30, "tata"),
new Personne(40, "tutu")
);
160
@FunctionalInterface
public interface Supplier<T> {
/*
* description : une méthode n'acceptant aucun paramètre en entrée
mais retournant un résultat de type "T"
*/
T get();
}
2.16.2.12.1 Exemple
package function;
import java.util.function.Supplier;
// retourne "hello"
System.out.println(stringSupplier.get());
161
2.16.2.14 L’interface fonctionnelle UnaryOperator<T>
1. package : java.util.function (à importer manuellement)
2. description : une interface fonctionnelle générique acceptant un
paramètre en entrée du type générique T et retournant un résultat
du même type générique T.
162
faire une classe anonyme → simplification de code et amélioration
de sa visibilité.
2. syntaxe : ([params]) -> corps :
• -> : l’opérateur de définition d’une lambda expression.
• si params consiste d’un seul paramètre, on peut omettre les par-
enthèses l’encapsulant (sauf si le paramètre est typé) ;
• si corps consiste d’une seule instruction retournant un résultat
on peut omettre les accolades définissant son bloc et le mot-clé
return ;
• on peut optionnellement typer les paramètres d’une lambda
expression : le type du paramètre sera inféré à partir de
l’instance de l’interface fonctionnelle utilisant la lambda
expression dans la définition de la méthode encapsulée).
3. exemple : définir une méthode de tri que l’on passera à la méthode
sort() de la classe Collections.
4. portée : les lambda expressions peuvent accéder à certains élé-
ments de leur environnement :
• des méthodes ;
• des attributs (modifiables au sein de l’expression) ;
• des variables locales et paramètres de méthodes (en lecture
uniquement et donc non modifiables au sein de l’expression).
5. exemples :
/*
* Lambda expression à :
- sans typage de paramètres
- syntaxe simplifiée du corps.
*/
(a, b) -> a + b;
/*
* Lambda expression à :
- sans typage de paramètres
- syntaxe complète du corps.
*/
d -> {return d.getAnneeCreation() >= 2012;}
/*
* Lambda expression à :
- typage de paramètres
- syntaxe simplifiée du corps.
*/
(DossierEntreprise d) -> d.getAnneeCreation() >= 2012;
/*
* Lambda expression à :
163
- typage de paramètres
- syntaxe complète du corps.
*/
(int a, int b) -> {return a + b;}
/*
* implémentation d'une interface par le biais d'une classe anonyme
et d'une lambda expression
*/
// L'interface fonctionnelle "Dialoguer"
package test;
@FunctionalInterface
public interface Dialoguer {
void parler(String question);
}
// La classe Test
package test;
164
2.16.4 Références de méthodes ou de constructeurs
/*
* référencement de la méthode size() de la classe List<String>
*/
List<String>::size;
/*
* référencement du constructeur par défaut de la classe Arraylist<String>
*/
ArrayList<String>::new;
2.16.4.0.1 Exemple
package function;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
165
//Conversion d'un String en un double en utilisant une lambda expression
ToDoubleFunction<String> stringToDoubleLambda = str -> Double.parseDouble(str);
/*
* Conversion d'un String en un double en utilisant
* une référence à une méthode statique d'une classe
*/
ToDoubleFunction<String> stringToDoubleRef = Double::parseDouble;
/*
* Affichage d'un String en référençant la méthode d'instance
* de l'attribut statique "out" de la classe "System"
*/
Consumer<String> stringPrinterRef = System.out::println;
2.17.1 Introduction
1. besoin :
166
• les collections/itérateux/tableau/flux stockent leurs éléments
et permettent un accès aux données en lecture/écriture.
• une taille croissante de ceux-ci fait que les traitements peuvent
devenir inefficaces, fastidieux et chronophages.
2. définition : les streams :
• une séquence d’éléments provenant d’une source, supportant
des opérations d’aggrégat séquentielles ou parallèles consistant
de traitements intermédiaires ou finales.
• une description déclarative des éléments telle que :
1. pas de stockage des données de la source : les éléments
sont calculés dynamiquement à la demande d’une manière
paresseuse (Lazy Computation)
2. pas d’accès aux données de la source et donc pas de mod-
ification de ceux-ci.
3. pas de réutilisation d’un stream une fois qu’il est utilisé
complètement : il faut recréer un nouveau stream à partir
de la même source pour ce faire.
4. pas de taille limite sur les streams sans terminaison ex-
plicite des traitements dessus (i.e. le stream reste ouvert en
face des traitements intermédiaires).
3. types de traitements :
• traitements intermédiaires :
1. des méthodes conservant l’état ouvert du stream associé à
une source et permettant de créer des streams intermédiaires
à partir de lui.
2. peuvent être chaînées jusqu’à tomber sur un traitement fi-
nal.
3. exemples :
– filtrage :
1. par un prédicat : filter(predicate);
2. enlevant des doublons : distinct();
3. réduisant la taille : limit(max);
4. sautant les n premiers élément : skip(n);
5. etc.
– projection :
1. en se basant sur une fonction : map(fonction).
2. en se basant sur une fonction retournant des streams spé-
cialisées : mapToInt(fonction), mapToDouble(fonction),
etc.
• tri : sorted().
• traitements terminales :
1. des méthodes consistant à terminer le calcul et à consom-
mer le stream en fournissant un résultat final.
2. exemples :
– application d’une procédure à tous les éléments d’un
stream : forEach(consumer).
167
– matching des éléments par un prédicat :
1. pour vérifier que tous les éléments ou n’importe
quel élément le satisfont : allMatch(predicate),
anyMatch(predicate);
2. en récupérant le premier ou n’importe quel élément
le satisfont : findFirst(); findAny().
• la réduction ou le regroupement via un collector : reduce(init,
accumulator), collect(collector).
4. calcul paresseux (lazy) :
• principe : le calcul des méthodes intermédiaires est chargé par
la JVM et est effectué si possible en une seule passe.
• contraste avec les collections/itérateurs/tableaux/flux : si
le calcul est décomposé en plusieurs passes, il n’y a pas
d’optimisation effectuée.
5. avantages :
• lisibilité du code : syntaxe déclarative pour le traitement des
données.
• amélioration des performances : calcul paresseux et sous cer-
taines conditions avec possibilité de parallélisation.
6. collector : une opération de réduction/regroupement d’éléments
d’une collection.
/*
* description : retourne true si une valeur non nulle est présente,
false sinon
168
*/
public boolean isPresent();
/*
* description : retourne "other" si une valeur non nulle n'est pas présente
*/
public T orElse(T other);
169
Stream<T> filter(Predicate<? super T> predicate);
/*
* description : supprimer les doublons du stream
*/
Stream<T> distinct();
/*
* description : limiter la taille du stream à "maxSize" éléments
*/
Stream<T> limit(long maxSize);
/*
* description : sauter les n premiers éléments du stream
*/
Stream<T> skip(long n);
/*
* description : tri les éléments du stream selon l'ordre
naturel sur le type "T"
*/
Stream<T> sorted();
/*
* description : tri les éléments du stream selon l'ordre
défini par le comparateur "comparator" sur le type "T"
*/
Stream<T> sorted(Comparator<? super T> comparator);
/*projection*/
/*
* description : appliquer la méthode définie par l'interface fonctionnelle
"mapper" à chaque élément du stream et retourner le stream résultant.
* La méthode prend en entrée le type "T" des éléments du stream ou l'une de ses
superclasses et retourne un résultat de type "R"
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/*
* description : appliquer une méthode définie par l'interface fonctionnelle
"mapper" à chaque élément du stream et retourner un stream
d'entiers matérialisé par le type "IntStream".
* La méthode prend en entrée le type "T" des éléments du stream ou l'une de ses
superclasses et retourne un "int"
*/
IntStream mapToInt(ToIntFunction<?super T> mapper);
170
/*
* description : appliquer une méthode définie par l'interface fonctionnelle
"mapper" à chaque élément du stream et retourner un stream
de doubles matérialisé par le type "DoublStream".
* La méthode prend en entrée le type "T" des éléments du stream ou l'une de ses
superclasses et retourne un "double"
*/
DoubleStream mapToDouble(ToDoubleFunction<?super T> mapper);
// méthodes finales
/*
* description : applique la procédure définie par l'interface fonctionnelle
désignant un consumer "action"
*/
void forEach(Consumer<? super T> action);
/*
* description : vérifie si tous les éléments du stream respectent
le prédicat défini par l'interface fonctionnelle désignant un Predicate
"predicate"
*/
boolean allMatch(Predicate<? super T> predicate);
/*
* description : vérifie s'il existe au moins un élément du stream respectant
le prédicat défini par l'interface fonctionnelle désignant un Predicate
"predicate"
*/
boolean anyMatch(Predicate<? super T> predicate);
/*
* description : retourne une description éventuellement vide
du premier élément du stream
*/
Optional<T> findFirst();
/*
* description : retourne une description éventuellement vide
de n'importe quel élément du stream
*/
Optional<T> findAny();
/*
* description : accumule la valeur de chaque élément du stream
en utilisant l'opérateur binaire "accumulator" et en commençant
171
depuis la valeur initiale définie par "identity"
et retourne le résultat
*/
T reduce(T identity, BinaryOperator<T> accumulator);
/*
* description : compte le nombre d'éléments dans le stream
*/
long count();
/*
* description : effectue une opération de réduction sur les éléments
du stream courant en utilisant le Collector "collector"
*/
<R,A> R collect(Collection<? super T, A, R> collector);
/*
* description : crée un stream contenant les éléments "values"
de type générique "T"
*/
static <T> Stream<T> of(T... values);
/*
* description : retourne une séquence ordonnée infinie en appliquant
la fonction unaire "f" itérativement sur les éléments générés
en commençant par l'élément initial "seed"
*/
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f);
/*
* description : retourne une séquence infinie non ordonnée où
chaque élément du stream est généré par le supplier "s"
* remarque : utilisé pour générer des streams constants ou aléatoires, etc.
*/
static <T> Stream<T> generate(Supplier<T> s);
172
*/
int sum();
/*
* description : opération de réduction retournant
la possiblement la moyenne des éléments du stream
*/
OptionalDouble average();
/*
* description : opération de réduction retournant
la possiblement la moyenne des éléments du stream
*/
OptionalDouble average();
173
arithmétique d'une séquence d'éléments de type "T"
et la retourner sous forme d'un "double"
*/
public static <T> Collector<T, ?, Double> averagingDouble(
ToDoubleFunction<? super T> mapper);
/*
* description : retourne un Collector permettant de calculer la moyenne
arithmétique d'une séquence d'éléments de type "T"
et la retourner sous forme d'un "double"
*/
public static <T> Collector<T, ?, Double> averagingInt(
ToIntFunction<? super T> mapper);
/*
* description : retourne un Collector implémentant une opération de
"group by" sur les éléments de la séquence de type "T"
selon la fonction de classification "classifier"
et retournant les résultats dans un Map
*/
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(
Function<? super T, ? extends K> classifier);
/*
* description : retourne un Collector permettant d'accumuler
les éléments de la séquence de type "T" et les retournant
en tant que liste
*/
public static <T> Collector<T, ?, List<T>> toList();
// en extension
Stream<T> myStream = Stream.of(/*valeurs de type T séparées par des ,*/ )
174
Stream<String> myLines = Files.lines(Paths.get("monFichier"));
// La classe DossierEntreprise
package streams;
/*constructors*/
public DossierEntreprise(String identification, int anneeCreation,
String email, int nbSalaries) {
this.identification = identification;
this.anneeCreation = anneeCreation;
this.email = email;
this.nbSalaries = nbSalaries;
}
/*methods*/
//Getters & setters
public String getIdentification() {return this.identification;}
public void setIdentification(String identification) {
this.identification = identification;
}
175
// La classe AgenceCoordination
package streams;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;
/*constructors*/
public AgenceCoordination() {}
/*methods*/
public void accueillerEntreprise(DossierEntreprise d) {
if(!entreprises.contains(d))
entreprises.add(d);
}
/*
* calcul du nombre moyen des salariés des entreprises
* à partir d'une annee en utilisant un itérateur
*/
public double nbMoyenSalariesIt(int annee) {
double nb = 0;
int nbEntreprises = 0;
if(nbEntreprises > 0)
return nb / (double) nbEntreprises;
else return 0;
}
/*
* calcul du nombre moyen des salariés des entreprises
* à partir d'une annee en utilisant un stream
* sans parallélisation
176
*/
public double nbMoyenSalariesStream(int annee) {
return entreprises.stream()
.filter(d -> d.getAnneeCreation()>=annee)
.mapToDouble(DossierEntreprise::getNbSalaries)
.average()
.getAsDouble();
}
/*
* calcul du nombre moyen des salariés des entreprises
* à partir d'une annee en utilisant un stream
* avec parallélisation
*/
public double nbMoyenSalariesParallelStream(int annee) {
return entreprises.parallelStream()
.filter(d -> d.getAnneeCreation()>=annee)
.mapToInt(DossierEntreprise::getNbSalaries)
.average()
.getAsDouble();
}
/*
* calcul du nombre moyen des salariés des entreprises
* à partir d'une annee en utilisant un stream
* sans parallélisation et un Collector
*/
public double nbMoyenSalariesCollector(int annee) {
return entreprises.stream()
.filter(d -> d.getAnneeCreation() >= annee)
.collect(Collectors.averagingInt(DossierEntreprise::getNbSalaries))
.doubleValue();
}
/*
* calcul du nombre moyen des salariés des entreprises
* à partir d'une annee en utilisant un stream
* avec parallélisation et un Collector
*/
public double nbMoyenSalariesParallelCollector(int annee) {
return entreprises.parallelStream()
.filter(d -> d.getAnneeCreation() >= annee)
.collect(Collectors.averagingInt(DossierEntreprise::getNbSalaries))
.doubleValue();
}
177
// affiche les emails des entreprises
public void afficheMails() {
entreprises.stream()
.forEach(d -> System.out.println(d.getEmail()));
}
// La classe Test
package streams;
178
DossierEntreprise e10 = new DossierEntreprise("00043", 2019,
"africanSpecials@op.fr", 10);
ag.accueillerEntreprise(e1);
ag.accueillerEntreprise(e2);
ag.accueillerEntreprise(e3);
ag.accueillerEntreprise(e4);
ag.accueillerEntreprise(e5);
ag.accueillerEntreprise(e6);
ag.accueillerEntreprise(e7);
ag.accueillerEntreprise(e8);
ag.accueillerEntreprise(e9);
ag.accueillerEntreprise(e10);
System.out.println(
"Moyen du nombre des salariés pour chaque entreprise créée après 2012");
System.out.println(
"====================================================================");
start = System.currentTimeMillis();
System.out.println(ag.nbMoyenSalariesStream(2012));
System.out.println("Avec un stream sans parallélisation : " +
(System.currentTimeMillis() - start) +
" millisecondes"); // 29 ms
start = System.currentTimeMillis();
System.out.println(ag.nbMoyenSalariesParallelStream(2012));
System.out.println("Avec un stream avec parallélisation : " +
(System.currentTimeMillis() - start) +
" millisecondes"); // 13 ms
start = System.currentTimeMillis();
System.out.println(ag.nbMoyenSalariesCollector(2012));
System.out.println(
"Avec un stream, sans parallélisation et utilisant un collector : " +
(System.currentTimeMillis() - start) +
" millisecondes"); // 4 ms
start = System.currentTimeMillis();
System.out.println(ag.nbMoyenSalariesParallelCollector(2012));
179
System.out.println(
"Avec un stream, avec parallélisation et utilisant un collector : " +
(System.currentTimeMillis() - start) +
" millisecondes"); // 1 ms
System.out.println();
// L'énumération Couleur
package streams;
/*attributes*/
private String name = "";
/*constructors*/
private Couleur(String name) {this.name = name;}
/*methods*/
//toString
@Override
public String toString() {
return this.name;
180
}
}
// La classe Personne
package streams;
/*constructors*/
public Personne() {
nom = prenom = "";
taille = poids = 0.0d;
yeux = Couleur.INCONNU;
}
/*methods*/
//Getters & setters
public String getNom() {
return nom;
}
181
public Double getTaille() {
return taille;
}
//toString
@Override
public String toString() {
return prenom + " " + nom + " :\n" +
"Taille : " + taille + " mètre(s), Poids : " + poids + " kilo(s)\n" +
"Couleur des yeux : " + yeux;
}
}
// La classe Test
package streams;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
182
//créer un stream infini
Stream.iterate(1, x -> x + 1)
.forEach(System.out::println);
System.out.println(
"Filtrer uniquement les personnes pesant plus que 50 kilos");
System.out.println(
"===========================================================");
System.out.println(
"Projetter uniquement les poids des personnes pesant plus que 50 kilos");
System.out.println(
"=====================================================================");
183
stream
.filter(p -> p.getPoids() > 50)
.map(Personne::getPoids)
.forEach(System.out::println);
System.out.println();
System.out.println(
"Calculer la somme des poids des personnes pesant plus que 250 kilos");
System.out.println(
"====================================================================");
//recréer le stream car il est consommé par le forEach précédent
stream = personnes.stream();
if(optionalSum.isPresent())
System.out.println(optionalSum.get() + " kilo(s)");
else
System.out.println("Personne pèse plus que 250 kilos !");
System.out.println();
System.out.println(
"Récupérer le nombre de personnes pesant plus que 50 kilos");
System.out.println(
"=========================================================");
//recréer le stream car il est consommé par le forEach précédent
stream = personnes.stream();
184
.count();
System.out.println(count + " personne(s)");
System.out.println();
System.out.println(
"Récupérer la liste des poids des personnes pesant plus que 50 kilos");
System.out.println(
"===================================================================");
//recréer le stream car il est consommé par le forEach précédent
stream = personnes.stream();
// La classe Paire
package streams;
/*constructors*/
public Paire(T1 first, T2 second) {
setFirst(first);
setSecond(second);
}
/*methods*/
//Getters & setters
185
public T1 getFirst() {return this.first;}
public void setFirst(T1 first) {this.first = first;}
//toString
@Override
public String toString() {
return "("+first+", "+second+")";
}
}
// La classe Test
package streams;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
// output
/*
*{
186
1830=[Paire [first=1830, second=Le rouge et le noir],
Paire [first=1830, second=Le livre des oracles]],
1837=[Paire [first=1837, second=Le rose et le vert]]
}
*/
import java.util.stream.Stream;
2.18.1 Introduction
187
3. intercession (i.e. l’interception d’appels).
3. contextes d’utilisation :
• inspection de méthodes/d’objets ;
• création d’objets selon des types non connu au préalable ;
• invocation de méthodes/constructeurs ;
• accès aux modifiers des entités ;
• inspection des superclasses/super-interfaces, des interfaces,
etc. ;
• création et manipulation de tableaux ;
• création de proxys de classes/d’instances pour intercepter des
appels et ajouter du comportement (e.g. trace automatique)
/*
* description : retourne la superclasse/super-interface de l'entité courante
*/
public Class<? super T> getSuperclass();
/*
* description : retourne le tableau des interfaces implémentées/étendues
par l'entité courante
*/
public Class<?> getInterfaces();
/*
* description : retourne l'attribut publique ayant le nom "name"
ou lève une exception NoSuchFieldException si le nom fournis est inconnu
*/
public Field getField(String name) throws NoSuchFieldException,
SecurityException;
/*
* description : retourne le tableau des attributs publiques de l'entité courante
188
(uniquement ceux directement définis au sein de l'entité courante)
*/
public Field[] getDeclaredFields() throws SecurityException;
/*
* description : retourne le tableau des attributs publiques de l'entité courante
(hérités y inclus)
*/
public Field[] getFields() throws SecurityException;
/*
* description : retourne la méthode publique ayant le nom "name"
éventuellement paramétrée par les paramètres ayant les types "parameterTypes"
ou lève une exception NoSuchMethodException si les spécifications
fournies ne désignent aucune méthode accessible
*/
public Field getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
/*
* description : retourne le tableau des méthodes publiques de l'entité courante
(héritées y inclus)
*/
public Method[] getMethods() throws SecurityException;
/*
* description : retourne le constructeur publique
éventuellement paramétré par les paramètres ayant les types "parameterTypes"
ou lève une exception NoSuchMethodException si les spécifications
fournies ne désignent aucun constructeur accessible
*/
public Field getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
/*
* description : retourne le tableau des constructeurs publiques de
l'entité courante
(héritées y inclus)
*/
public Method[] getConstructors() throws SecurityException;
/*
* description : retourne le type à l'exécution "Class" de la classe
dont le nom est défini par le String "className"
ou lève une exception ClassNotFoundException si le nom fournis est inconnu
*/
189
public static Class<?> forName(String className) throws ClassNotFoundException;
/*
* description : retourne le nom de l'attribut courant
*/
public String getName();
/*
190
* description : retourne le type à l'exécution de l'attribut courant
*/
public Class<?> getType();
/*
* description : retourne le nombre des paramètres de la méthode
*/
public int getParameterCount();
/*
* description : retourne le tableau des types à l'exécution des
paramètres de la méthode par l'ordre de leur déclaration
*/
public Class<?>[] getParameterTypes();
/*
* description : retourne le type à l'exécution du type de retour
de la méthode
*/
public Class<?> getReturnType();
/*
* description : retourne le tableau des types à l'exécution des
exceptions transmises par la méthode par l'ordre de leur déclaration
*/
public Class<?>[] getExceptionTypes();
/*
* description : invoquer la méthode sur l'objet "obj"
éventuellement en fournissant les attributs "args"
*/
public Object invoke(Object obj, Object... args)
191
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException;
/*
* retourne un tableau des annotations de l'élément annoté
(y inclus celles héritées)
*/
Annotation[] getAnnotations()
/*
* retourne un tableau des annotations de l'élément annoté
(uniquement celles directement annotant l'élément annoté)
192
*/
Annotation[] getDeclaredAnnotations()
/*
* retourne true si l'élément est annoté par une annotation ayant
un type à l'exécution spécifié par "annotationClass"
sinon retourne false
*/
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
2.18.9 Exemples
import java.lang.reflect.Method;
import java.util.Scanner;
if (mParamTypes.length > 0) {
for (Class<?> paramType: mParamTypes)
buffer.append(paramType.getName() + ", ");
buffer.delete(buffer.toString().length() - 2, buffer.toString()
.length());
}
buffer.append(")");
if (mExceptions.length > 0) {
buffer.append(" throws ");
193
for (Class<?> exception: mExceptions)
buffer.append(exception.getName() + ", ");
buffer.delete(buffer.toString().length() - 2, buffer.toString()
.length());
}
buffer.append(";");
System.out.println(buffer.toString());
}
}
while(!correct) {
System.out.println("Saisir un nom de classe");
String nomClasse = scanner.nextLine();
try {
Class<?> c = Class.forName(nomClasse);
displayPublicMethods(c);
} catch (ClassNotFoundException e) {
correct = false;
continue;
}
correct = true;
}
}
}
/*constructors*/
public Produit() {}
public Produit(String reference, String designation, double prixHT) {
194
this.reference = reference;
this.designation = designation;
this.prixHT = prixHT;
}
/*methods*/
//abstract methods
public abstract double leprixTTC();
//toString
@Override
public String toString() {
return "Reference: " + reference +
"\nDesignation: " + designation +
"\nPrix HT: " + prixHT +
"\nPrix TTC: " + this.leprixTTC();
}
}
// La classe ProduitTNormal
package reflection;
/*constructors*/
public ProduitTNormal() {}
195
public ProduitTNormal(String reference, String designation, double prixHT) {
super(reference, designation, prixHT);
}
/*methods*/
//implemented abstract methods of Produit
@Override
public double leprixTTC() {
return this.getPrixHT() * 1.196;
}
// La classe Livre
package reflection;
/*constructors*/
public Livre() {}
public Livre(String reference, String designation, double prixHT,
String editeur) {
super(reference, designation, prixHT);
this.editeur = editeur;
}
/*methods*/
//Getters & setters
public String getEditeur() {
return editeur;
}
public void setEditeur(String editeur) {
this.editeur = editeur;
}
//toString
@Override
public String toString() {
return super.toString() +
"\nEditeur: " + editeur;
}
}
// La classe Test
196
package reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
197
System.out.println("Implements: " + interfaces.length + " interfaces: ");
for (Class<?> inter: interfaces)
System.out.println(inter);
System.out.println();
for(Class<?> p: pTypes)
System.out.println(p.getName());
System.out.println("--------------------------------------\n");
}
System.out.println();
for(Class<?> p: pTypes)
System.out.println(p.getName());
System.out.println("--------------------------------------\n");
}
System.out.println();
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
198
import java.util.Scanner;
try {
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
199
public class Test {
try {
Method methode = livreClasse.getMethod(nomMethode);
Object prixTTC = methode.invoke(livre);
System.out.println("Par introspection, Prix TTC: " + prixTTC + "\n");
200
MOYEN,
ELEVE;
}
// L'annotation Risk
package reflection;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Risk {
NiveauRisque value() default NiveauRisque.MOYEN;
}
@Risk
public static void m3() {
throw new RuntimeException("Boom");
}
@Risk
public static void m5() {
System.out.println("m5");
}
201
System.out.println("m6");
}
@Risk(NiveauRisque.ELEVE)
public static void m7() {
throw new RuntimeException("Crash");
}
import java.lang.reflect.Method;
202
2.19 Les dates (Nouvelle API depuis Java 8)
2.19.1 Introduction
203
/*
* description : retourne le temps
selon l'unité désignant l'objet courant
entre les deux objets temporels
"temporal1Inclusive" (inclus) et temporal2Exclusive (exclus)
*/
long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive)
204
• THURSDAY : jeudi ;
• FRIDAY : vendredi ;
• SATURDAY : samedi ;
• SUNDAY : dimanche.
/*
* description : retourne vrai si la date courante est
après la date "other", false sinon
*/
default boolean isAfter(ChronoLocalDate other)
205
2.19.9 L’interface ChronoLocalDateTime<D extends ChronoLocalDate>
/*
* description : retourne vrai si le datetime courant est
après le datetime "other", false sinon
*/
default boolean isAfter(ChronoLocalDateTime<?> other)
/*
* description : retourne vrai si le datetime courant est
après le datetime "other", false sinon
*/
default boolean isAfter(ChronoZonedDateTime<?> other)
/*
* description : retourne l'instant correspondant au datetime courant
selon les règles de conversion associées au fuseau horaire
du datetime
*/
default Instant toInstant();
206
2.19.11 La classe Instant
/*
* description : retourne vrai si l'instant actuel est
après l'instant "otherInstant", false sinon
*/
public boolean isAfter(Instant otherInstant)
/*
* description : retourne l'instant courant de l'horloge du système
*/
public static Instant now();
/*
* description : retourne l'instant correspondant au string "text"
qui doit désigner un instant valide
*/
public static Instant parse(CharSequence text);
207
*/
public DayOfWeek getDayOfWeek();
/*
* description : retourne le jour du mois de la date courante (entre 1 et 31)
*/
public int getDayOfMonth();
/*
* description : retourne le jour de l'année de la date courante (entre 1 et 366)
*/
public int getDayOfYear();
/*
* description : retourne le mois de l'année de la date courante
*/
public Month getMonth();
/*
* description : retourne le mois de l'année de la date courante (entre 1 et 12)
*/
public int getMonthValue();
/*
* description : retourne l'année de la date courante
*/
public int getYear();
/*
* description : retourne true si l'année de la courante est bissextile,
false sinon
*/
public boolean isLeapYear();
/*
* description : retourne une version ajustée de la date courante
par l'ajusteur "adjuster"
*/
public LocalDate with(TemporalAdjuster adjuster);
/*
* description : retourne une copie de la date courante
ayant le jour du mois "dayOfMonth"
*/
public LocalDate withDayOfMonth(int dayOfMonth);
208
/*
* description : retourne une copie de la date courante
ayant le jour de l'année "dayOfYear"
*/
public LocalDate withDayOfYear(int dayOfYear);
/*
* description : retourne une copie de la date courante
ayant le mois "month"
*/
public LocalDate withMonth(int month);
/*
* description : retourne une copie de la date courante
ayant l'année "year"
*/
public LocalDate withYear(int year);
/*
* description : retourne une copie de la date courante
en lui retranchant "amountToSubtract" d'unité temporelle "unit"
*/
public LocalDate minus(long amountToSubtract, TemporalUnit unit);
/*
* description : retourne une copie de la date courante
en lui retranchant "daysToSubtract" jours
*/
public LocalDate minusDays(long daysToSubtract);
/*
* description : retourne une copie de la date courante
en lui retranchant "weeksToSubtract" semaines
*/
public LocalDate minusWeeks(long weeksToSubtract);
/*
* description : retourne une copie de la date courante
en lui retranchant "monthsToSubtract" mois
*/
public LocalDate minusMonths(long monthsToSubtract);
/*
* description : retourne une copie de la date courante
en lui retranchant "yearsToSubtract" années
*/
209
public LocalDate minusYears(long yearsToSubtract);
/*
* description : retourne une copie de la date courante
en lui ajoutant "amountToAdd" d'unité temporelle "unit"
*/
public LocalDate plus(long amountToAdd, TemporalUnit unit);
/*
* description : retourne une copie de la date courante
en lui ajoutant "daysToAdd" jours
*/
public LocalDate plusDays(long daysToAdd);
/*
* description : retourne une copie de la date courante
en lui ajoutant "weeksToAdd" semaines
*/
public LocalDate plusWeeks(long weeksToAdd);
/*
* description : retourne une copie de la date courante
en lui ajoutant "monthsToAdd" mois
*/
public LocalDate plusMonths(long monthsToAdd);
/*
* description : retourne une copie de la date courante
en lui ajoutant "yearsToAdd" années
*/
public LocalDate plusYears(long yearsToAdd);
/*
* description : retourne la date courante de l'horloge du système
dans le fuseau horaire (timezone) par défaut
*/
public static LocalDate now();
/*
* description : retourne la date correspondant au string "text"
qui doit désigner une date valide
*/
public static LocalDate parse(CharSequence text);
/*
* description : retourne une date locale ayant l'année
210
"year", le mois "month" et le jour du mois "dayOfMonth"
avec month entre 1 et 12
*/
public static LocalDate of(int year, int month, int dayOfMonth);
/*
* description : retourne une date locale ayant l'année
"year", le mois "month" et le jour du mois "dayOfMonth"
avec month une valeur de l'énumération "Month"
*/
public static LocalDate of(int year, Month month, int dayOfMonth);
/*
* description : retourne une date locale ayant l'année
"year" et le jour de l'année "dayOfYear"
avec dayOfMonth entre 1 et 366
*/
public static LocalDate ofYearDay(int year, int dayOfYear);
/*
* description : retourne le nombre des minutes du time courant (entre 0 et 59)
*/
public int getMinute();
/*
* description : retourne le nombre des secondes du time courant (entre 0 et 59)
*/
public int getSecond();
/*
* description : retourne le nombre de nanosecondes du time courant
* (entre 0 et 999,999,999)
*/
211
public int getNano();
/*
* description : retourne vrai si le time courant est
avant le time "other", false sinon
*/
public boolean isBefore(LocalTime other)
/*
* description : retourne vrai si le time courant est
après le time "other", false sinon
*/
public boolean isAfter(LocalTime other)
/*
* description : retourne une version ajustée du temps courant
par l'ajusteur "adjuster"
*/
public LocalTime with(TemporalAdjuster adjuster);
/*
* description : retourne une copie du time courant
ayant l'heure "hour"
*/
public LocalTime withHour(int hour);
/*
* description : retourne une copie du time courant
ayant le nombre de minutes "minute"
*/
public LocalTime withMinute(int minute);
/*
* description : retourne une copie du time courant
ayant le nombre de secondes "second"
*/
public LocalTime withSecond(int second);
/*
* description : retourne une copie du time courant
ayant le nombre de nanosecondes "nanoOfSecond"
*/
public LocalTime withNano(int nanoOfSecond);
/*
* description : retourne une copie du time courant
212
en lui retranchant "amountToSubtract" d'unité temporelle "unit"
*/
public LocalTime minus(long amountToSubtract, TemporalUnit unit);
/*
* description : retourne une copie du time courant
en lui retranchant "hoursToSubtract" heures
*/
public LocalTime minusHours(long hoursToSubtract);
/*
* description : retourne une copie du time courant
en lui retranchant "minutesToSubtract" minutes
*/
public LocalTime minusMinutes(long minutesToSubtract);
/*
* description : retourne une copie du time courant
en lui retranchant "secondsToSubtract" secondes
*/
public LocalTime minusSeconds(long secondsToSubtract);
/*
* description : retourne une copie du time courant
en lui retranchant "nanosToSubtract" nanosecondes
*/
public LocalTime minusNanos(long nanosToSubtract);
/*
* description : retourne une copie du time courant
en lui ajoutant "amountToAdd" d'unité temporelle "unit"
*/
public LocalTime plus(long amountToAdd, TemporalUnit unit);
/*
* description : retourne une copie du time courant
en lui ajoutant "hoursToAdd" heures
*/
public LocalTime plusHours(long hoursToAdd);
/*
* description : retourne une copie du time courant
en lui ajoutant "minutesToAdd" minutes
*/
public LocalTime plusMinutes(long minutesToAdd);
213
/*
* description : retourne une copie du time courant
en lui ajoutant "secondsToAdd" secondes
*/
public LocalTime plusSeconds(long secondsToAdd);
/*
* description : retourne une copie du time courant
en lui ajoutant "nanosToAdd" nanosecondes
*/
public LocalTime plusNanos(long nanosToAdd);
/*
* description : retourne le time courant de l'horloge du système
dans le fuseau horaire (timezone) par défaut
*/
public static LocalTime now();
/*
* description : retourne le time correspondant au string "text"
qui doit désigner un time valide
*/
public static LocalTime parse(CharSequence text);
/*
* description : retourne un time local ayant l'heure
"hour" et le nombre de minutes "minute"
*/
public static LocalTime of(int hour, int minute);
/*
* description : retourne un time local ayant l'heure
"hour", le nombre de minutes "minute" et le nombre
de secondes "second"
*/
public static LocalTime of(int hour, int minute, int second);
/*
* description : retourne un time local ayant l'heure
"hour", le nombre de minutes "minute", le nombre
de secondes "second" et le nombre de nanosecondes
"nanoOfSecond"
*/
public static LocalTime of(int hour, int minute, int second, int nanoOfSecond);
214
2.19.14 La classe LocalDateTime
/*
* description : retourne le jour du mois du datetime courant (entre 1 et 31)
*/
public int getDayOfMonth();
/*
* description : retourne le jour de l'année du datetime courant (entre 1 et 366)
*/
public int getDayOfYear();
/*
* description : retourne le mois de l'année du datetime courant
*/
public Month getMonth();
/*
* description : retourne le mois de l'année du datetime courant (entre 1 et 12)
*/
public int getMonthValue();
/*
* description : retourne l'année du datetime courant
*/
public int getYear();
/*
* description : retourne l'heure du datetime courant (entre 0 et 23)
*/
public int getHour();
/*
* description : retourne le nombre des minutes du datetime courant
* (entre 0 et 59)
*/
215
public int getMinute();
/*
* description : retourne le nombre des secondes du datetime courant
* (entre 0 et 59)
*/
public int getSecond();
/*
* description : retourne le nombre de nanosecondes du datetime courant
* (entre 0 et 999,999,999)
*/
public int getNano();
/*
* description : retourne la partie date du datetime courant
*/
public LocalDate toLocalDate();
/*
* description : retourne la partie time du datetime courant
*/
public LocalTime toLocalTime();
/*
* description : le datetime associé au fuseau horaire
ayant l'identifiant "zone"
*/
public ZonedDateTime atZone(ZoneId zone);
/*
* description : retourne une version ajustée du dateime courant
par l'ajusteur "adjuster"
*/
public LocalDateTime with(TemporalAdjuster adjuster);
/*
* description : retourne une copie du datetime courant
ayant le jour du mois "dayOfMonth"
*/
public LocalDateTime withDayOfMonth(int dayOfMonth);
/*
* description : retourne une copie du datetime courant
ayant le jour de l'année "dayOfYear"
*/
216
public LocalDateTime withDayOfYear(int dayOfYear);
/*
* description : retourne une copie du datetime courant
ayant le mois "month"
*/
public LocalDateTime withMonth(int month);
/*
* description : retourne une copie du datetime courant
ayant l'année "year"
*/
public LocalDateTime withYear(int year);
/*
* description : retourne une copie du datetime courant
ayant l'heure "hour"
*/
public LocalDateTime withHour(int hour);
/*
* description : retourne une copie du datetime courant
ayant le nombre de minutes "minute"
*/
public LocalDateTime withMinute(int minute);
/*
* description : retourne une copie du datetime courant
ayant le nombre de secondes "second"
*/
public LocalDateTime withSecond(int second);
/*
* description : retourne une copie du datetime courant
ayant le nombre de nanosecondes "nanoOfSecond"
*/
public LocalDateTime withNano(int nanoOfSecond);
/*
* description : retourne une copie du datetime courant
en lui retranchant "amountToSubtract" d'unité temporelle "unit"
*/
public LocalDateTime minus(long amountToSubtract, TemporalUnit unit);
/*
* description : retourne une copie du datetime courant
217
en lui retranchant "daysToSubtract" jours
*/
public LocalDateTime minusDays(long daysToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "weeksToSubtract" semaines
*/
public LocalDateTime minusWeeks(long weeksToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "monthsToSubtract" mois
*/
public LocalDateTime minusMonths(long monthsToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "yearsToSubtract" années
*/
public LocalDateTime minusYears(long yearsToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "hoursToSubtract" heures
*/
public LocalDateTime minusHours(long hoursToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "minutesToSubtract" minutes
*/
public LocalDateTime minusMinutes(long minutesToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "secondsToSubtract" secondes
*/
public LocalDateTime minusSeconds(long secondsToSubtract);
/*
* description : retourne une copie du datetime courant
en lui retranchant "nanosToSubtract" nanosecondes
*/
public LocalDateTime minusNanos(long nanosToSubtract);
218
/*
* description : retourne une copie du datetime courant
en lui ajoutant "amountToAdd" d'unité temporelle "unit"
*/
public LocalDateTime plus(long amountToAdd, TemporalUnit unit);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "daysToAdd" jours
*/
public LocalDateTime plusDays(long daysToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "weeksToAdd" semaines
*/
public LocalDateTime plusWeeks(long weeksToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "monthsToAdd" mois
*/
public LocalDateTime plusMonths(long monthsToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "yearsToAdd" années
*/
public LocalDateTime plusYears(long yearsToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "hoursToAdd" heures
*/
public LocalDateTime plusHours(long hoursToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "minutesToAdd" minutes
*/
public LocalDateTime plusMinutes(long minutesToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "secondsToAdd" secondes
*/
219
public LocalDateTime plusSeconds(long secondsToAdd);
/*
* description : retourne une copie du datetime courant
en lui ajoutant "nanosToAdd" nanosecondes
*/
public LocalDateTime plusNanos(long nanosToAdd);
/*
* description : retourne le datetime courant de l'horloge du système
dans le fuseau horaire (timezone) par défaut
*/
public static LocalDateTime now();
/*
* description : retourne le datetime correspondant au string "text"
qui doit désigner un datetime valide
*/
public static LocalDateTime parse(CharSequence text);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour" et le nombre de minutes "minute"
avec month entre 1 et 12
*/
public static LocalDateTime of(int year, int month, int dayOfMonth,
int hour, int minute);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour", le nombre de minutes "minute" et
le nombre de secondes "second"
avec month entre 1 et 12
*/
public static LocalDateTime of(int year, int month, int dayOfMonth,
int hour, int minute, int second);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour", le nombre de minutes "minute",
le nombre de secondes "second" et
le nombre de nanosecondes "nanoOfSecond"
avec month entre 1 et 12
220
*/
public static LocalDateTime of(int year, int month, int dayOfMonth,
int hour, int minute, int second, int nanoOfSecond);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour" et le nombre de minutes "minute"
avec month une valeur de l'énumération "Month"
*/
public static LocalDateTime of(int year, Month month, int dayOfMonth,
int hour, int minute);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour", le nombre de minutes "minute" et
le nombre de secondes "second"
avec month une valeur de l'énumération "Month"
*/
public static LocalDateTime of(int year, Month month, int dayOfMonth,
int hour, int minute, int second);
/*
* description : retourne un datetime local ayant l'année
"year", le mois "month", le jour du mois "dayOfMonth",
l'heure "hour", le nombre de minutes "minute",
le nombre de secondes "second" et
le nombre de nanosecondes "nanoOfSecond"
avec month une valeur de l'énumération "Month"
*/
public static LocalDateTime of(int year, Month month, int dayOfMonth,
int hour, int minute, int second, int nanoOfSecond);
/*
* description : retourne un datetime local créé à partir
de la date locale "date" et le temps local "time"
*/
public static LocalDateTime of(LocalDate date, LocalTime time);
221
2.19.16 La classe TemporalAdjusters
/*
* description : retourne le nombre de mois de la période courante
*/
public int getMonths();
/*
* description : retourne le nombre d'années de la période courante
*/
public int getYears();
/*
* description : une période entre les deux dates locales
"startDateInclusive" (incluse) et
"endDateExclusive" (exclus)
*/
public static Period between(LocalDate startDateInclusive,
LocalDate endDateExclusive);
222
2.19.18 La classe Duration
/*
* description : une durée entre les deux temps
"startInclusive" (incluse) et
"endExclusive" (exclus)
*/
public static Duration between(Temporal startInclusive, Temporal endExclusive);
/*
* description : retourne le ZoneId correspondant au string "zoneId"
à condition que "zoneId" soit un identifiant valide d'un fuseau horaire
*/
public static ZoneId of(String zoneId);
223
/*
* description : retourne le fuseau horaire par défaut du système
*/
public static ZoneId systemDefault();
2.19.21 Exemples
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
224
System.out.println("Heure : " + currentTime.getHour());
System.out.println("Minutes : " + currentTime.getMinute());
System.out.println("Secondes : " + currentTime.getSecond());
System.out.println("Nanosecondes : " + currentTime.getNano());
System.out.println();
225
import java.time.LocalDateTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;
226
System.out.println("Avant 7 millisecondes : " +
base.minus(7, ChronoUnit.MILLIS));
System.out.println("Avant 8 microsecondes : " +
base.minus(8, ChronoUnit.MICROS));
System.out.println("Avant 9 nanosecondes : " +
base.minusNanos(9));
System.out.println();
}
}
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
227
}
}
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Period;
import java.time.temporal.ChronoUnit;
System.out.println(
"(Avec ChronoUnit) Nombre d'années de la période entre " + dt1 + " et " +
dt2 + " : " + ChronoUnit.YEARS.between(dt1, dt2) + " années.");
System.out.println("(Avec ChronoUnit) Nombre de mois de la période entre " +
dt1 + " et " + dt2 + " : " + ChronoUnit.MONTHS.between(dt1, dt2) + " mois.");
System.out.println("(Avec ChronoUnit) Nombre de jours de la période entre " +
dt1 + " et " + dt2 + " : " + ChronoUnit.DAYS.between(dt1, dt2) + " jours.");
System.out.println();
System.out.println(("Nombre de secondes de la durée entre " + dt1 + " et " +
dt3 + " : " + d.getSeconds() + " secondes."));
}
}
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
228
import java.util.List;
import java.util.Map;
System.out.println();
System.out.println("Fuseau horaire par défaut : " + ZoneId.systemDefault());
System.out.println("Règles de conversion : " + ZoneId.systemDefault().getRules());
System.out.println();
System.out.println(
"Représentation du moment actuel en fuseaux horaires différents :");
System.out.println(
"=================================================================");
LocalDateTime currentTime = LocalDateTime.now();
//liste des fuseaux horaires dans lesquels nous affichons le moment actuel
List<ZoneId> zones = Arrays.asList(
ZoneId.of("Europe/Paris"),
ZoneId.of("Asia/Tokyo"),
ZoneId.of("America/Anchorage")
);
zones
.stream()
.forEach(zoneId -> {
System.out.println("\tMoment actuel dans le fuseau horaire \"" +
zoneId.toString() + "\" : " + currentTime.atZone(zoneId).toInstant());
});
}
}
229
2.20 JVM et la modularité (Depuis Java 9)
2.20.1 Introduction
230
3. un module peut contenir plusieurs packages, mais un package ne
peut être contenu que dans un seul module ;
// fichier module-info.java
module nomModule.java {
/*dépendances, exportations et interfaces*/
}
/*
* description : tous les éléments publiques de "package" sont accessibles
par les autres packages
*/
// exports <package>;
/*
* description : tous les éléments publiques de "package1" sont accessibles
uniquement depuis les packages "package2"[, ...]
*/
// qualified exports <package1> to <package2>[, ...];
/*
* description : le module dépend du package "package"
*/
// requires <package>;
/*
* description : le module, et toutes les applications
qui en dépenderont, dépendent du package "package"
*/
// requires <package> transitive;
/*
* description : le module fournit l'interface "package.Interface" et
une implémentation de celle-ci "package.Implementation"
*/
// provides <package.Interface> with <package.Implementation>;
2.20.4 CLI ajoutée par JDK pour les modules (Depuis Java 9)
java --list-modules # lister les modules de Java avec leurs numéros de version
231
# décrit le module :
# - ses exportations :
# - ses dépendances :
# - ses interfaces et leurs implémentations
java --describe-module <module>
3 Tests en Java
3.1.1 Introduction
3.1.1.1 Propriétés :
1. faciliter la définition des tests grâce à des assertions, des méthodes
d’initialisation et de finalisation.
2. enchaîner l’exécution des méthodes de test définies par le testeur.
3. savoir en un seul clic quels tests ont réussi/planté/échoué grâce à
une construction et une exécution rapide de tests.
232
4. mettre à disposition du testeur toute l’infrastructure nécessaire
pour :
• définir des tests : JUnit ne définit pas les tests, ni propose des
principes pour structurer leur définition, c’est la responsabilité
du testeur.
• définir leurs oracles.
• se remettre à JUnit pour leur exécution : le testeur n’invoque
pas explicitement les tests dans le programme, c’est la respons-
abilité du framework d’invoquer les tests définis par le testeur.
233
3.1.2.3 Méthodes de test/Cas de test
1. cas de test :
• description : un cas de test s’intéresse à une seule unité de
code/un seul comportement et doit rester court.
• propriété : les cas de test sont indépendants les uns des autres.
2. définition en JUnit :
• un cas de test ≡ une méthode de test ;
• versions < 4 : les noms des méthodes de test commencent
par test.
• versions >= 4 : les méthodes de test sont annotées par @Test.
3. méthodes de test
• définition :
1. sont sans paramètres et sans type de retour ;
2. embarquent l’oracle et donc contiennent des assertions, par
exemple :
– x vaut 3.
– le résultat de l’appel de telle méthode est non nul.
– x est inférieur à y.
– etc.
• exécution : invocation par JUnit dans un ordre quelconque.
3.1.2.4 Verdicts
1. définition : un verdict désigne le résultat de l’invocation de la procé-
dure de comparaison (une assertion) d’un oracle dans un cas de test.
2. résultats :
• Pass (vert) : aucune faute détectée.
• Fail (rouge) : échec; on attendait un résultat et on a eu un
autre.
• Error : le test n’a pas pu s’exécuter correctement (i.e. une
exception inattendue).
3. remarque : depuis JUnit version >= 4, il n’y a plus de différence
entre Fail et Error.
234
3.1.2.6 Préambules et postambules
1. description : des méthodes écrites par le testeur pour mettre en
place l’environnement de test.
2. définition en JUnit 4 :
• méthodes annotées par @Before et @After :
1. publiques et non statiques ;
2. invoquées avant/après chaque méthode de test par le
framework ;
3. possiblement plusieurs à être annotées par ces deux anno-
tations dans une classe de test, avec un ordre d’invocation
quelconque.
• méthodes annotées par @BeforeClass et @AfterClass :
1. publiques et statiques ;
2. invoquées avant/après la première/dernière méthode de
test par le framework ;
3. une seule méthode annotée par chaque annotation dans
une classe de test.
3. définition en JUnit 3 :
• méthodes équivalentes aux méthodes annotées par @Before et
@After : les méthodes setUp() et tearDown().
• pas de méthodes équivalentes aux méthodes annotées par
@BeforeClass et @AfterClasse.
/*constructors*/
public Subscription(int price, int length) {
this.price = price;
this.length = length;
}
/**
* Calculate the monthly subscription price in euro,
* rounded up to the nearest cent
*
* @return the monthly subscription price in euro
*/
235
public double pricePerMonth() {
return (double) price / (double) length;
}
/**
* cancel/ nullify this subscription
*/
public void cancel() {this.length = 0;}
}
import org.junit.Test;
@Test
public void testRoundUp() {
System.out.println("Test if pricePerMonth() rounds up correctly...");
Subscription s = new Subscription(200, 3);
assertTrue(s.pricePerMonth() == 0.67);
}
}
3.1.3 Approfondissements
236
/*
* description : indiquer le maximum timeout permis en ms
* retour : Pass si la méthode termine son exécution avant le timeout
Fail sinon
*/
@Test(timeout=10)
public void testMethod(){/*code*/ }
/*
* description : ignorer la méthode de test avec éventuellement
un message indiquant pourquoi. La méthode de test ne sera pas
ainsi invoquée par JUnit
*/
@Ignore("message")
public void testMethod(){/*code*/ }
// exemples
// Pass si x = 3
assertThat(x, is(3));
// Pass si x != 3
assertThat(x, is(not(3)));
237
// Pass si "color" ou "colour" sont des sous-strings de "responseString"
assertThat(responseString, either(containsString("color"))
.or(containsString("colour")));
// exemples
// Pass si le séparateur du système de fichier est "/"
assumetThat(File.separatorChar, is('/'))
3.1.4.1 Introduction
1. besoin : réutiliser une méthode de test avec des jeux de données
de test différents.
2. approche :
/*importations requises*/
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/*
* indiquer que la classe de test est paramétrée par
des jeux de données différents
*/
@RunWith(Parameterized.class)
visibilite class ClasseTest{
/*
* attributs désignant les composants d'un jeu
de données de test
*/
visibilite type1 jeuPart1;
visibilite type2 jeuPart1;
...
/*
* constructeur publique initialisant une instance de
la classe de test via des paramètres désignant
les composants d'un jeu de données, qui retournera
238
une instance de la classe de test
pour chaque jeu de données de test
*/
public ClasseTest([jeu]){/*code*/ }
3.1.4.2 Exemple
// La classe Sum à tester
package junit;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
239
@RunWith(Parameterized.class)
public class TestSum {
/*attributes*/
private int x;
private int y;
private int result;
/*constructor*/
public TestSum(int x, int y, int result) {
this.x = x;
this.y = y;
this.result = result;
}
/*methods*/
//test methods
@Test
public void testSum() {
assertEquals(result, new Sum().sum(x, y));
}
3.1.5.1 Introduction
1. besoin : rassembler des cas de test pour enchaîner leur exécution
en groupant l’exécution de classes de test.
2. principe :
• création de plusieurs classes de test.
• création d’une classe vide de suite de tests
3. syntaxe :
/*importations requises*/
import org.junit.runner.RunWith;
240
import org.junit.runners.Suite;
/*
* indiquer que la classe de test désigne une suite
de classes de test et indiquer quelles classes de test
constituent la suite
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({ClasseTest1.class, ClasseTest2.class, ...})
visibilite class ClasseSuiteTest{}
3.1.5.2 Exemple
// La classe à tester Calculator
package junit;
/*methods*/
public void add(int n) {result += n;}
public void subtract(int n) {
result -= 1; // Bug: should be result -= n
}
241
public void switchOff() {
/*
* Display "bye bye",
* Beep,
* Switch off the screen
*/
}
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/*methods*/
//environment methods
@Before
public void clearCalculator() {
cal.clear();
}
//test methods
@Test
public void testAdd() {
cal.add(1);
cal.add(2);
assertEquals(cal.getResult(), 3);
}
@Test
public void testSubtract() {
cal.add(10);
cal.subtract(2);
assertEquals(cal.getResult(), 8);
}
242
@Ignore("not ready yet")
@Test
public void testMultiply() {
cal.add(10);
cal.multiply(10);
assertEquals(cal.getResult(), 100);
}
@Test
public void testDivide() {
cal.add(8);
cal.divide(4);
assertEquals(cal.getResult(), 2);
}
@Test(expected=ArithmeticException.class)
public void testDivideByZero() {
cal.add(10);
cal.divide(0);
}
}
/*
* La classe de test abstraite CalculatorAbstractTest
préparant l'environnement de test
*/
package junit;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@BeforeClass
public static void startTestSystem() {
System.out.println("Start test system");
}
@AfterClass
public static void stopTestSystem() {
System.out.println("Stop test system");
}
@Before
public void initTestSystem() {
243
System.out.println("Initialize test system");
}
}
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/*methods*/
//environment methods
@BeforeClass
public static void switchOnCalculator() {
System.out.println("Switch on calculator");
cal = new Calculator();
cal.switchOn();
}
@AfterClass
public static void switchOffCalculator() {
System.out.println("Switch off calculator");
cal.switchOff();
cal = null;
}
@Before
public void clearCalculator() {
System.out.println("Clear calculator");
cal.clear();
}
//test methods
@Test(timeout=10)
public void testSquareRoot() {
cal.squareRoot(2);
}
}
/*
244
* La classe de tests paramétrée CalculatorSquareParameterizedTest
pour tester l'opération square(int)
*/
package junit;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class CalculatorSquareParameterizedTest {
/*attributes*/
private static Calculator cal = new Calculator();
private int param;
private int result;
/*constructors*/
public CalculatorSquareParameterizedTest(int param, int result) {
this.param = param;
this.result = result;
}
/*methods*/
//test methods
@Test
public void testSquare() {
cal.square(param);
assertEquals(result, cal.getResult());
}
245
{5, 25}
});
}
}
/*
* La classe désignant la suite des classes de tests
de la classe à tester Calculator
*/
package junit;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
CalculatorBasicTest.class,
CalculatorAdvancedTest.class,
CalculatorSquareParameterizedTest.class
})
public class CalculatorSuiteTest {}
246
• soit l’exécution d’un programme engendrant plusieurs processus
lourds (via le méchanisme de fork) ou légers (appelés aussi des
threads).
4. programmation multi-processus : faire du parallélisme en créant
plusieurs processus.
5. thread :
• un fil d’exécution, une tâche, une activité ou un processus léger.
• une partie, ou un chemin d’exécution, à l’intérieur d’un processus.
6. programmation multi-threadée : faire du parallélisme en créant
plusieurs threads d’un même processus.
247
• chaque thread possède sa propre pile (et donc ses propres variables
locales).
• tous les threads d’un processus parent partagent ses segments de code,
de données et de tas.
• les threads peuvent communiquer entre eux et partager des données
à travers des variables en mémoire.
• le thread exécutant la fonction main() dans un processus est le
thread principal et tout autre éventuel thread du même procesus
est secondaire.
• sur une machine comportant plusieurs processeurs, chaque thread
peut s’exécuter sur un processeur, indépendamment d’un autre.
• la commutation de contexte entre les threads est gérée par le OS.
4.2.2.1 Introduction
Il existe plusieurs outils de synchronisation de threads :
1. l’attente de la fin d’un thread.
2. la création de verrous binaires (i.e. à deux états : vérouillé ou pas) utilis-
ables par des threads d’un même processus ou de processus différents.
3. la définition de variables conditionnelles permettant d’attendre
l’occurrence d’un événement.
4.2.3.1 Introduction
1. problème : l’accès à une donnée partagée, en lecture par un thread et en
écriture par un autre, pourra engendrer des incohérences au niveau de sa
valeur lors de son lecture/écriture.
2. solution :
• utiliser un mécanisme d’accès exclusif à une donnée partagée par un
seul thread à la fois.
• on parle de “mutual exclusion” ou exclusion mutuelle.
3. définition : un verrou est un sémaphore ayant deux états possibles :
occupé (i.e. vérouillé) ou libre (i.e. déverrouillé).
248
4. opérations : le verrouillage et le déverrouillage sont des opérations atom-
iques (i.e. non interruptibles).
5. utilisation :
• lorsqu’un verrou est libre, un thread peut demander de l’occuper.
• un seul thread peut occuper un verrou à la fois.
• seul le thread occupant le verrou peut le libérer.
• lorsqu’un thread occupe un verrou, les autres threads souhaitant oc-
cuper le même verrou :
1. seront bloqués dans un contexte bloquant et échoueront dans un
contexte non bloquant.
2. ce comportement dépend de l’OS.
6. section critique : une zone d’un programme comportant des instructions
d’accès à une donnée partagée.
//Thread T1
...
249
occuper(verrou);
tant que (x <= seuil){
libérer(verrou);
occuper(verrou);
}
...
// travail sur x;
libérer(verrou);
...
//Thread T2
...
occuper(verrou);
// travail sur x;
libérer(verrou);
...
250
tant que (Predicat non satisfait) faire
relâcher l'accès;
attendre event(Predicat satisfait);
bloquer l'accès;
// Section critique
relâcher l'accès;
//Thread T1=2
...
bloquer l'accès;
// Section critique
signaler event(Predicat satisfait);
relâcher l'accès;
4.2.4.4 Introduction
1. définition : une variable conditionnelle est :
• une donnée commune à plusieurs threads;
• symbolisant un écouteur d’événements ;
• et fonctionnant comme un prédicat (signalant l’occurrence d’un
événement ou pas).
2. implémentation : traiter la valeur de la variable conditionnelle, com-
mune à plusieurs threads, comme section critique devrant être protégée
par une exclusion mutuelle.
3. utilisation :
• un thread occupant un verrou, pourra passer à un état d’attente
atomique, écoutant l’occurrence d’un événement.
• il demandera d’être réveillé une fois l’événement survenu.
• le réveil est réalisé par un autre thread, qui réveillera aussi tous
les autres threads utilisant la variable conditionnelle pour écouter
l’occurrence du même événement.
• parmi les threads réveillés, un seul occupera le verrou, alors que les
autres rentreront dans une attente bloqué atomiquement, écoutant
l’occurrence de l’événement ultérieurement afin d’être réveillés à nou-
veau.
4. remarque : étant donné qu’un seul thread pourra occuper le verrou à la
fois, il est préférable de ne réveiller qu’un seul thread à la fois, parmi ceux
attendant d’être réveillé lors de l’occurrence d’un événement, pour plus
d’efficacité.
251
cond_var;
...
// initialisation
...
// Thread 1
...
occuper(verrou);
tant que (donnee_commune hors bornes) faire
libérer(verrou);
attendre(cond_var); // attente atomique (i.e. bloquante)
// réveil
occuper(verrou);
// travail
libérer(verrou);
// Thread 2
...
occuper(verrou);
// accés et modification de verrou
si (donnee_commune dans bornes) alors
réveillerTaches(cond);
libérer(verrou);
1. package : java.lang
2. description :
• à implémenter par toute classe dont les instances seront exécutées au
sein d’un thread quand celui-ci est activé.
• annotée par @FunctionalInterface et donc désigne une interface
fonctionnelle pouvant être le cible d’une lambda expression ou d’une
référence de méthode.
3. quelques méthodes :
/**
* méthode invoquée par la JVM quand le thread est activé
*/
void run();
1. package : java.lang.
2. description :
• une classe, superclasse de tous les threads en Java.
252
• implémente Runnable.
4.4.1 Propriétés
/**
* crée un nouveau thread ayant un nom automatiquement généré de la forme
* "Thread-n" où n désigne un entier
*/
public Thread();
253
/**
* crée un nouveau thread ayant le nom "name"
*/
public Thread(String name);
/**
* crée un thread exécutant la méthode run() de l'objet Runnable "target"
* et ayant un nom automatiquement généré de la forme
* "Thread-n" où n désigne un entier
*/
public Thread(Runnable target);
/**
* crée un thread exécutant la méthode run() de l'objet Runnable "target"
* et ayant le nom "name"
*/
public Thread(Runnable target, String name);
/**
* retourne une référence sur le thread en cours d'exécution
*/
public static Thread currentThread();
/**
* retourne l'identifiant du thread courant
*/
public long getId();
/**
* retourne le nom du thread courant
*/
public final String getName();
/**
* change le nom du thread courant en "name"
*/
public final void setName(String name);
/**
* retourne la priorité d'exécution du thread courant
*/
public final int getPriority();
/**
* retourne l'état du thread courant
254
*/
public Thread.State getState();
/**
* invoqué par un autre thread T' pour activer le thread courant T et commencer
* son exécution, causant la JVM à invoquer sa méthode run()
* et lancer son exécution en concurrence avec T'
*
* Remarque : on peut invoquer la méthode start() sur un thread au plus une fois
* et on ne peut le re-activer une fois qu'il aura terminé son exécution
*/
public void start();
/**
* interrompt le thread courant (si possible)
* lire la documentation pour voir les cas d'interruption possible d'un thread
*/
public void interrupt();
/**
* suspend l'exécution du thread courant pendant "millis" millisecondes
*/
public static void sleep(long millis);
/**
* suspend l'exécution du thread courant pendant "millis" millisecondes
* et "nanos" nanosecondes
*/
public static void sleep(long millis, int nanos);
/**
* retourne true si le thread courant est "vivant"
* (i.e. sa méthode run() est en cours d'exécution
* et n'a pas encore terminé)
* false sinon
*/
public final boolean isAlive();
/**
* retourne true si le thread courant est un thread "daemon"
*/
public final boolean isDaemon();
/**
* retourne true si le thread courant est interrompu
*/
255
public boolean isInterrupted();
1. package : java.lang.
2. description : une énumération des valeurs de l’état d’un thread.
3. les valeurs :
• NEW : l’état d’un thread quand il vient d’être créé.
• RUNNABLE : l’état d’un thread lors de son activation par l’invocation
de sa méthode start().
• BLOCKED : l’état d’un thread lorsqu’il est mis en sommeil par
l’ordonnanceur pour en utiliser un autre.
• WAITING : l’état d’un thread lorsqu’il attend indéfiniment la fin
d’exécution d’un autre thread.
• TIMED_WAITING : l’état d’un thread lorsqu’il attend pendant un péri-
ode d’attente spécifique la fin d’exécution d’un autre thread.
• TERMINATED : l’état d’un thread lorsqu’il termine l’exécution de sa
méthode run().
4.4.4 Exemple
/* CONSTRUCTORS */
public TestThread(String name) {
super(name);
displayState();
this.start();
displayState();
}
this.start();
displayState();
256
}
/* METHODS */
@Override
public void run() {
for (int i = 0; i < 10; i++) {
displayState();
if (t != null)
displayTState();
}
}
/* classe de test */
package threads;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.displayState();
t2.displayState();
}
}
257
Output
Statut du thread A : NEW
Statut du thread A : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : NEW
Statut du thread A : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread A pendant l'exécution du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread A pendant l'exécution du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread A pendant l'exécution du thread B : RUNNABLE
Statut du thread A : RUNNABLE
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread B : RUNNABLE
Statut du thread A pendant l'exécution du thread B : TERMINATED
Statut du thread A : TERMINATED
Statut du thread B : TERMINATED
1. description :
• un mot-clé décrivant une méthode qui ne peut être accédée par un
autre thread si elle l’est déjà par un thread, même si ce dernier est
mis en sommeil par l’ordonnanceur.
258
• les threads cherchant à utiliser une méthode déjà prise en charge par
un autre thread seront mis dans une liste d’attente.
2. utilité : synchroniser l’accès à des données partagées en lecture et
écriture par deux threads, de manière à ne pas permettre l’émergence
d’incohérences.
1. package : java.lang.
2. description : une classe singleton modélisant une interface entre une
application et son environnement d’exécution.
3. quelques méthodes :
/**
* retourne la seule instance de la classe pour l'application courante
*/
public static Runtime getRuntime();
/**
* retourne le nombre de processeurs disponible à la JVM exécutant l'application
*/
public int availableProcessor();
4.7.1 Pré-requis
4.7.2 Principe
259
Figure 17: Principe du pattern Fork/Join
4.7.3 Processus
260
4.7.4 Implémentation en Java (Depuis Java 7)
/**
* une méthode retournant le résultat de l'exécution de la tâche,
* une fois que l'exécution est terminé,
* et fusionnant le thread de son exécution au sein du pool de threads fournis
* par le service d'exécution associé à cette tâche.
*/
public final V join();
261
• une classe abstraite générique, superclasse de toutes les tâches pou-
vant être découpées en sous-tâches, pouvant être exécutées récursive-
ment en parallèle, et retournant un résultat de type V.
• hérite de ForkJoinTask<Void>.
3. quelques méthodes :
/**
* méthode encapsulant le traitement à effectuer par une sous-tâche,
* et retournant un résultat de type V
*/
protected abstract V compute();
/**
* invoke le pool de threads courant sur la tâche parallélisable "task"
* afin de l'exécuter et retourne son résultat de type "T"
* lors de la complétion de l'exécution de ses sous-tâches.
*/
public <T> T invoke(ForkJoinTask<T> task);
262
package threads.fork_join;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;
/* ATTRIBUTES */
private Path path;
private String filter = "*";
private long result;
/* CONSTRUCTORS */
public FolderScanner() {}
public FolderScanner(Path path, String filter) {
this.path = path;
this.filter = filter;
}
/* METHODS */
public long getResult() {return this.result;}
/**
* Scans folders recursively
* @return the number of files in this scanner's path that math this scanner's filter
* @throws ScanException
*/
public long sequentialScan() throws ScanException {
if (path == null || path.toString().equals(""))
throw new ScanException(
"Invalid path error: the provided path is either empty or null"
);
System.out.println(
"Scanning \"" + path + "\" for files having the extension \""
+ filter + "\""
);
263
if (Files.isDirectory(p.toAbsolutePath())) {
FolderScanner f = new FolderScanner(p.toAbsolutePath(), filter);
result += f.sequentialScan();
}
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
System.out.println(
"Scanning \"" + path + "\" for files having the extension \""
+ filter + "\"");
if(Files.isDirectory(p.toAbsolutePath())) {
FolderScanner task = new FolderScanner(p.toAbsolutePath(), filter);
taskList.add(task);
task.fork();
}
}
} catch (IOException e) {
264
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected Long compute() {
long result = 0;
try {
result = this.parallelScan();
} catch(ScanException e) {
e.printStackTrace();
}
return result;
}
}
/* classe d'exception */
package threads.fork_join;
/* classe de test */
package threads.fork_join;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ForkJoinPool;
265
public class Test {
pool.invoke(fs);
/*
* une classe contenant une méthode exécutant une tâche
* pouvant être parallélisée en utilisant Fork/Join
*/
package threads.fork_join;
import java.util.concurrent.RecursiveTask;
266
public class SuiteComputation extends RecursiveTask<Long> {
/* ATTRIBUTES */
private long debut, fin, result;
private static int SEUIL = 1_000;
/* CONSTRUCTOR */
public SuiteComputation() {
debut = fin = result = 0;
}
/* METHODS */
public long getResult() {
return result;
}
return result;
}
@Override
protected Long compute() {
long nbIterations = getNumberOfIterations();
else {
System.out.println("Fork/Join mode of execution of task");
// Dichotomic computation
267
long middle = nbIterations / 2;
return result;
}
}
/* classe de test */
package threads.fork_join;
import java.util.concurrent.ForkJoinPool;
pool.invoke(suiteComputation);
268
Fork/Join mode of execution of task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Fork/Join mode of execution of task
Fork/Join mode of execution of task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Fork/Join mode of execution of task
Monothread execution of task/sub-task
Fork/Join mode of execution of task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Monothread execution of task/sub-task
Result: 292105640
5.1 Introduction
1. programmation procédurale :
• exécuter une application : exécuter la méthode main() d’une des
classes de l’application.
• terminer une application : fin de l’exécution de la méthode
main().
2. programmation événementielle :
• application = assemblage de composants graphiques.
• l’état de l’application change au fur et à mesure des interactions
des utilisateurs avec l’application.
• événement (event) : toute action utilisateur interagissant avec
l’interface graphique de l’application.
• écouteur d’événements (event listener) : un composant per-
mettant à une vue/fenêtre d’écouter l’occurrence d’un type
d’événements (e.g., clic d’un bouton)
• traitement d’un événement (event handler) : méthode de
traitement invoquée lors de l’occurrence d’un événement.
• exécuter une application : exécuter la méthode main().
• terminer une application :
1. indépendante de la fin de la méthode main().
269
2. arrêter la boucle d’attente d’événements déclenchés par
l’utilisateur.
270
5.2 Les composants graphiques
271
/** la constante pour le style italic */
public static final int ITALIC;
/**
* retourne la coordonnée y du point
*/
public int getY();
/**
* retourne le point courant
*/
public Point getLocation();
/**
* déplace le point courant vers le point ("x", "y")
*/
public void setLocation(int x, int y);
/**
* déplace le point courant vers les coordonées du point "point"
*/
public void setLocation(Point point);
272
*/
public double getWidth();
/**
* retourne la hauteur de la dimension courante en tant qu'un double
*/
public double getHeight();
/**
* retourne la dimension courante
*/
public Dimension getSize();
/**
* change la dimension courante pour avoir une largeur "width"
* et une hauteur "height"
*/
public void setSize(int width, int height);
/**
* change la dimension courante pour avoir une largeur entière
* obtenue à partir de "width" et une hauteur entière
* obtenue à partir de "height"
*/
public void setSize(double width, double height);
/**
* change la dimension courante pour avoir la largeur et hauteur
* de la dimension "d"
*/
public void setSize(Dimension d);
273
/**
* change la couleur de l'arrière-plan du composant courant en "c"
*/
public void setBackground(Color c);
/**
* retourne la couleur de l'arrière-plan du composant courant
*/
public Color getBackground();
/**
* change la couleur du premier plan du composant courant en "c"
*/
public void setForeground(Color c);
/**
* retourne la couleur du premier plan du composant courant
*/
public Color getForeground();
/**
* change la police du composant courant en "font"
*/
public void setFont(Font f);
/**
* retourne la police du composant courant
*/
public Font getFont();
/**
* redimensionne le composant courant pour avoir
* une largeur "width" et une hauteur "height"
* (par défaut, un composant n'a pas de taille)
*/
public void setSize(int width, int height);
/**
* redimensionne le composant courant pour avoir la largeur
* et hauteur de la dimension "d"
*/
public void setSize(Dimension d);
/**
* retourne la dimension (largeur, hauteur) désignant
* la dimension du composant courant.
274
*/
public Dimension getSize();
/**
* retourne la largeur du composant courant
*/
public int getWidth();
/**
* retourne la hauteur du composant courant
*/
public int getHeight();
/**
* redimensionne le composant courant pour avoir une dimension préférée
* définie par "d", qui sera prise en compte par le layout manager
* responsable de la disposition du composant courant dans son parent.
*
* Remarque : le redimensionnement selon une dimension préférée ne fonctionne
* que si le parent du composant utilise un layout manager
*/
public void setPreferredSize(Dimension d);
/**
* retourne la dimension préférée du composant courant
*/
public Dimension getPreferredSize();
/**
* déplace le composant courant vers le point ("x", "y")
* (par défaut, un composant est localisé au point (0, 0)
*/
public void setLocation(int x, int y);
/**
* retourne le point (x, y) désignant la localisation du composant courant.
*/
public Point getLocation();
/**
* retourne la coordonnée x du composant par rapport au point (0, 0)
*/
public int getX();
/**
* retourne la coordonnée y du composant par rapport au point (0, 0)
275
*/
public int getY();
/**
* déplace le composant courant vers le point ("x", "y")
* (le coin gauche supérieur de l'écran est au point (0, 0))
* et le redimensionne pour avoir une largeur de "width"
* et une hauteur de "height"
*/
public void setBounds(int x, int y, int width, int height);
/**
* change la visibilité du composant courant en "b"
* (par défaut le composant est invisible)
*/
public void setVisible(boolean b);
/**
* crée et retourne un contexte graphique pour le composant courant
* afin de pouvoir dessiner dessus.
*
* Remarque : retourne null si le composant courant est invisible
*/
public Graphics getGraphics();
/**
* redessine le composant courant
*
* Remarque : appelée automatiquement lorsqu'un événement écouté par le composant
* est émis
*/
public void repaint();
/**
* rattache l'écouteur d'événéments souris "listener" au composant courant
*/
public void addMouseListener(MouseListener listener);
/**
* définie si ce composant courant est activé/ désactivé selon la valeur de "b"
* (les composants sont activés par défaut)
*/
public void setEnabled(boolean b);
/**
* retourne true si le composant courant est activé, false sinon
276
*/
public boolean isEnabled();
/**
* ajoute le composant "comp" à la fin de ce conteneur et
* notifie le layout manager d'ajouter le composant
* au sein du layout associé au conteneur selon les contraintes définies
* par "constraints"
*/
public void add(Component comp, Object constraints);
/**
* utilise "manager" comme layout manager du conteneur courant
*/
public void setLayout(LayoutManager manager);
277
3. quelques méthodes :
/**
* spécifie si la fenêtre courante est au premier plan.
* S'il existe plusieurs fenêtres au premier plan, leur ordre est non spécifié
* et dépend de la plateforme.
*/
public final void setAlwaysOnTop(boolean c) throws SecurityException;
/**
* ajuste la taille de la fenêtre courante de manière à englober les dimensions
* préférées de ses composants contenus.
*
* Remarque : ne doit être invoquée qu'une fois tous les composants de la
* fenêtre y soient ajoutés, sinon certains composants pourront être invisibles.
*/
public void pack();
/**
* change la position de la fenêtre courante relativement au composant "c",
* selon les scénarios suivants :
* 1. si "c" est "null", alors la fenêtre est placée au centre de l'écran.
* 2. si "c" est non "null", mais invisible, alors la fenêtre est placée au
* centre de la fenêtre contenant "c".
* 3. si "c" est non "null" est visible, alors la fenêtre est placée de
* manière à avoir son centre et celui de "c" coincident.
*/
public void setLocationRelativeTo(Component c);
278
• une classe modélisant tous les frames AWT.
• hérite de Window.
3. quelques méthodes :
/**
* affecte "title" comme titre de la fenêtre courante
*/
public void setTitle(String title);
/**
* retourne le titre de la fenêtre courante
*/
public String getTitle();
/**
* retourne true si la fenêtre courante est redimensionnable.
* (initialement toutes les fenêtres le sont)
*/
public boolean isResizable();
/**
* spécifie si la fenêtre courante est redimensionnable selon la valeur de "c"
*/
public void setResizable(boolean c);
/**
* retourne true si la fenêtre courante est non décorée
* (i.e., n'a ni des contours ni des boutons de contrôle)
* (initialement toutes les fenêtres ne le sont pas)
*/
public boolean isUndecorated();
/**
* spécifie si la fenêtre courante est décorée selon la valeur de "c"
*
* remarque : la fenêtre ne doit pas être visible lors de l'appel de cette méthode
*/
public void setUndecorated(boolean c);
279
3. quelques méthodes :
/**
* appelle la méthode paint() du délégué de l'UI, si celui-ci est non null
* en lui passant une copie du contexte graphique "g" pour dessiner dessus
*
* Remarque : cette méthode est invoquée automatiquement :
- quand le composant courant est instancié
- quand le conteneur du composant ou le composant lui-même alternent en
termes de visibilité
- quand le conteneur du composant ou le composant lui-même sont redimensionnés
*/
protected void paintComponent(Graphics g);
5.2.3.1 Terminologie
1. frame :
• une fenêtre graphique indépendante de toute autre fenêtre, appelée
aussi “fenêtre cadre”.
• contient un titre, et une bordure.
2. panneau (panel) : un composant graphique représentant une surface rect-
angulaire sans bordure, utilisé comme conteneur de composants.
5.2.3.2.1 Structure
Les composants formant la structure d’un JFrame :
1. la fenêtre ;
2. le root pane (en vert), le conteneur principal de la fenêtre.
3. le layered pane (en violet), un panneau composé du conteneur global et
de la barre de menu.
4. la barre de menu (en orange), quand il y en a une.
5. le content pane (en rose), un panneau consitutant un conteneur global
dans lequel on met tous nos composants.
6. le glass pane (en transparence), une couche utilisée pour intercepter les
actions de l’utilisateur avant qu’elles ne parviennent aux composants.
5.2.3.2.2 Métadonnées
1. package : javax.swing.
2. description :
280
Figure 19: Structure d’une JFrame
281
• une classe modélisant tous les frames Swing.
• hérite de Frame.
• par défaut, utilise un BorderLayout comme gestionnaire de disposi-
tion.
3. quelques méthodes :
/**
* spécifier l'action par défaut à effectuer lors de la fermeture de la frame
* courante, où "operation" désigne l'une des constantes de l'interface
* `WindowConstants`.
* Par défaut, l'action à effectuer est associée à "WindowConstants.HIDE_ON_CLOSE".
*/
public void setDefaultCloseOperation(int operation);
/**
* retourne le "content pane" de la fenêtre courante.
*/
public Container getContentPane();
/**
* changer le "content" de la fenêtre courante en "contentPane"
*/
public void setContentPane(Container contentPane);
282
3. quelques méthodes :
/**
* dessine un ovale rempli et délimité par le rectangle
* ayant une largeur "width" et une hauteur "height"
* à partir du point ("x", "y")
*/
public abstract void fillOval(int x, int y, int width, int height);
/**
* dessine le contour d'un rectangle
* ayant une largeur "width" et une hauteur "height"
* à partir du point ("x", "y")
*/
public void drawRect(int x, int y, int width, int height);
/**
* dessine un rectangle rempli
* ayant une largeur "width" et une hauteur "height"
* à partir du point ("x", "y")
*/
public abstract void fillRect(int x, int y, int width, int height);
/**
* dessine le contour d'un rectangle rond
* ayant une largeur "width", une hauteur "height",
* une largeur d'arc du coin "arcWidth" et une longueur d'arc du coin "arcHeight"
* à partir du point ("x", "y")
*/
283
public abstract void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight);
/**
* dessine un rectangle rond rempli
* ayant une largeur "width", une hauteur "height",
* une largeur d'arc du coin "arcWidth" et une longueur d'arc du coin "arcHeight"
* à partir du point ("x", "y")
*/
public abstract void fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight);
/**
* dessine une ligne passant par les points ("x1", "y1") et ("x2", "y2")
*/
public abstract void drawLine(int x1, int y1, int x2, int y2);
/**
* dessine un polygone de "nPoints" points rempli
* tels que chaque point pi = ("xPoints[ i]", "yPoints[ i]").
*
* Remarque : le dernier point est lié au premier point automatiquement
*/
public abstract void fillPolygon(int[] xPoints, int[] yPoints, int nPoints);
/**
* dessine le contour d'un polygone de "nPoints" points,
* tels que chaque point "pi" = ("xPoints[ i]", "yPoints[ i]")
*
* Remarque : le dernier point est lié au premier point automatiquement
*/
public abstract void drawPolygon(int[] xPoints, int[] yPoints, int nPoints);
/**
* dessine le texte "str" tel que la ligne de fond du premier caractère de "str"
* passe par le point ("x", "y")
*/
public abstract void drawString(String str, int x, int y);
/**
* change la couleur de l'objet graphique courant en "c"
*/
public abstract void setColor(Color c);
/**
* retourne la couleur de l'objet graphique courant
284
*/
public abstract Color getColor();
/**
* change la police de l'objet graphique courant en "font"
* (uniquement pour les objets textuels)
*/
public abstract void setFont(Font font);
/**
* retourne la police de l'objet graphique courant
*/
public abstract Font getFont();
/**
* dessine une image "img" en commençant du point ("x", "y") et en lui affectant
* un observateur d'images "observer".
*/
public abstract boolean drawImage(Image img, int x, int y,
ImageObserver observer);
/**
* dessine une image "img" en commençant du point ("x", "y") et en lui affectant
* les dimensions ("width", "height") et un observateur d'images "observer".
*
* Remarque : L'image est mise à l'échelle des dimensions fournies si nécessaire.
*/
public abstract boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer);
285
*/
public abstract void setPaint(Paint paint);
286
5.2.6 Les formes et les paintures
/**
* crée un gradient des couleurs "color1" et "color2" passant par les points
* ("x1", "y1") et ("x2", "y2"), avec répétition si "cyclic" vaut true, et sans
* répétition sinon
*/
public GradientPaint(float x1, float y1, Color color1, float x2, float y2,
Color color2, boolean cyclic);
287
1. package : java.awt.
2. description : une interface offrant l’interface commune à tous les layout
managers.
3. quelques méthodes :
1. package : java.awt.
2. description :
288
• une classe modélisant un layout manager divisant l’espace disponible
dans un conteneur pour l’ajout de composants en 5 zones: nord, sud,
est, ouest, et centre.
• implémente LayoutManager1 et LayoutManager2.
3. propriétés :
• chaque zone est identifée par une constante correspondante :
1. BorderLayout.NORTH : zone du nord occupant ;
2. BorderLayout.SOUTH : zone du sud ;
3. BorderLayout.EAST : zone de l’est ;
4. BorderLayout.WEST : zone de l’ouest ;
5. BorderLayout.CENTER : zone centrale ;
• chaque zone peut contenir au plus un composant.
• si on essaye d’ajouter un composant à une zone déjà occupée, le
composant ajouté se superpose avec le composant déjà ajouté.
• l’ajout d’un élément à un frame utilisant un BorderLayout se fait
par défaut dans la zone centrale.
• un composant ajouté en BorderLayout.CENTER occupe la totalité de
la largeur et de la hauteur de son conteneur.
• un composant ajouté en BorderLayout.NORTH ou BorderLayout.SOUTH
occupe la totalité de la largeur de son conteneur mais une hauteur
proportionnelle à celle de son contenu.
• un composant ajouté en BorderLayout.EAST ou BorderLayout.WEST
occupe la totalité de l’hauteur de son conteneur mais une largeur
proportionnelle à celle de son contenu.
4. quelques méthodes :
289
Figure 21: Exemple d’un applet géré par un FlowLayout
290
1. package : java.awt.
2. description :
• une classe modélisant un layout manager ajoutant les composants
dans une grille rectangulaire dont chaque cellule possède la même
taille, selon leur ordre d’ajout.
• implémente LayoutManager.
3. propriétés :
• la direction du flôt d’ajout des composants est déterminée par
l’orientation du conteneur utilisant le gestionnaire.
• par défaut, le flôt d’ajout des composants est de gauche à droite et
de haut en bas.
4. quelques méthodes :
/**
* crée un GridLayout Swing contenant une grille
* de "rows" lignes et "cols" colonnes
*/
public GridLayout(int rows, int cols);
/**
* définie "cols" comme nombre de colonnes de la grille
* du layout manager courant
*/
public void setColumns(int cols);
/**
* définie "rows" comme nombre de lignes de la grille
* du layout manager courant
*/
public void setRows(int rows);
/**
* définie l'espace horizontal entre les composants dans les cellules de la grille
* du layout manager courant par "hgap" pixels
*/
public void setHgap(int hgap);
/**
* définie l'espace vertical entre les composants dans les cellules de la grille
* du layout manager courant "vgap" pixels
*/
public void setVgap(int vgap);
291
Figure 23: Exemple de BoxLayout
2. description :
• une classe modélisant un layout manager ajoutant des composants
à la suite sur un axe de positionnement qui est soit horizontal (une
ligne), soit vertical (sur une colonne).
• implémente LayoutManager1 et LayoutManager2.
3. quelques constantes :
• BoxLayout.X_AXIS : les composants sont positionnés horizontale-
ment de gauche à droite.
• BoxLayout.Y_AXIS : les composants sont positionnés verticalement
de haut en bas.
• BoxLayout.LINE_AXIS :
1. les composants sont positionnés comme s’ils étaient des mots sur
une ligne
2. leur orientation dépend de la ComponentOrientation de leur con-
teneur :
– si elle est verticale, alors ils sont positionnés verticalement
de haut en bas.
– si elle est horizontale, alors si elle est, de plus, de gauche
à droite, ils sont positionnés horizontalement de gauche à
droite, sinon ils sont positionnés horizontalement de droite à
gauche.
• BoxLayout.PAGE_AXIS :
1. les composants sont positionnés comme s’ils étaient des lignes
sur une page
2. leur orientation dépend de la ComponentOrientation de leur con-
teneur (idem que BoxLayout.LINE_AXIS).
4. quelques méthodes :
/**
* crée un BoxLayout pour le conteneur cible "target", selon l'axe de positionnement
* défini par "axis"
*/
public BoxLayout(Container target, int axis);
292
5.2.7.7 La classe Box
1. package : javax.swing.
2. description :
• une classe modélisant des boîtes désignant des containers utilisant un
BoxLayout par défaut.
• hérite de JComponent
3. quelques méthodes :
/**
* crée une Box qui positionne ses éléments horizontalement de gauche à droite
*/
public static Box createHorizontalBox();
/**
* crée une Box qui positionne ses éléments verticalement de haut en bas
*/
public static Box createVerticalBox();
/**
* affiche la prochaine carte du conteneur "parent".
*
* Remarque : si la carte visible du conteneur avant le changement
est la dernière carte, alors la première carte est envoyée
*/
public void next(Container parent);
/**
* affiche la carte précédente du conteneur "parent".
*
* Remarque : si la carte visible du conteneur avant le changement
est la première carte, alors la dernière carte est envoyée
293
*/
public void previous(Container parent);
/**
* affiche la dernière carte du conteneur "parent"
*/
public void last(Container parent);
/**
* affiche la carte du conteneur "parent" associée au nom "name"
*/
public void show(Container parent, String name);
/**
* spécifie la position en y du composant dans la grille
* valeur spéciale : RELATIVE, quand le composant doit être ajouté immédiatement
* après le dernier composant ajouté sur l'axe des Y.
*/
public int gridy;
/**
294
* spécifie le nombre de colonnes occupées par le composant
* (par défaut vaut 1 et doit être non nul)
*
* valeurs spéciales :
* 1. REMAINDER : le composant est le dernier composant dans la ligne
* 2. RELATIVE : le composant est l'avant dernier composant dans la ligne
*/
public int gridwidth;
/**
* spécifie le nombre de lignes occupées par le composant
* (par défaut vaut 1 et doit être non nul)
*
* valeurs spéciales :
* 1. REMAINDER : le composant est le dernier composant dans la colonne
* 2. RELATIVE : le composant est l'avant dernier composant dans la colonne
*/
public int gridheight;
/**
* 1. quand utilisée avec gridx, gridy: le composant doit être ajouté
* immédiatement après le dernier composant ajouté sur l'axe des X, Y.
* 2. quand utilisé avec gridwidth, gridheight: le composant est l'avant
* dernier composant dans la ligne/ colonne
*/
public static final int RELATIVE;
/**
* quand utilisé avec gridwidth, gridheight : le composant est le dernier dans
* la ligne, colonne.
*/
public static final int REMAINDER;
/**
* à utiliser lorsque la taille de la zone d'affichage du composant est plus
* large que sa taille préférée. il détermine si le composant à besoin d'être
* redimensionné, et si oui alors comment le faire, selon les constantes
* NONE, HORIZONTAL, VERTICAL, BOTH.
*/
public int fill;
/**
* ne pas redimensionner le composant
*/
public static final int NONE;
295
/**
* redimensionner le composant horizontalement seulement
*/
public static final int HORIZONTAL;
/**
* redimensionner le composant verticalement seulement
*/
public static final int VERTICAL;
/**
* redimensionner le composant horizontalement et verticalement
*/
public static final int BOTH;
/**
* ancrage du composant dans la cellule (i.e., son alignement), pouvant avoir les
* valeurs suivantes :
* 1. FIRST_LINE_START : en haut à gauche.
* 1. PAGE_START : en haut au centre.
* 1. FIRST_LINE_END : en haut à droite.
* 1. LINE_START : au milieu à gauche.
* 1. CENTER : au milieu et centré.
* 1. LINE_END : au milieu à droite.
* 1. LAST_LINE_START : en bas à gauche.
* 1. PAGE_END : en bas au centre.
* 1. LAST_LINE_END : en bas à droite.
* 1. ...
*/
public int anchor;
/**
* en haut à gauche de sa zone d'affichage
* (ou en haut à droite selon l'orientation du composant)
*/
public static final int FIRST_LINE_START;
/**
* en haut au centre de sa zone d'affichage
*/
public static final int PAGE_START;
/**
* en haut à droite de sa zone d'affichage
* (ou en haut gauche selon l'orientation du composant)
*/
296
public static final int FIRST_LINE_END;
/**
* au milieu à gauche de sa zone d'affichage
* (ou à droite selon l'orientation du composant)
*/
public static final int LINE_START;
/**
* positionne le composant au milieu et centré dans sa zone d'affichage
*/
public static final int CENTER;
/**
* au milieu à droite de sa zone d'affichage
* (ou à gauche selon l'orientation du composant)
*/
public static final int LINE_END;
/**
* en bas à gauche de sa zone d'affichage
* (ou à droite selon l'orientation du composant)
*/
public static final int LAST_LINE_START;
/**
* en bas au centre de sa zone d'affichages
*/
public static final int PAGE_END;
/**
* en bas à droite de sa zone d'affichage
* (ou à gauche inversement selon l'orientation du composant)
*/
public static final int LAST_LINE_END;
/**
* si la grille est plus large que la zone d'affichage du composant, alors
* l'espace est redistribué proportionnellement aux valeurs de weightx des
* différentes colonnes
*/
public double weightx;
/**
* si la grille est plus haute que la zone d'affichage du composant, alors
* l'espace est redistribué proportionnellement aux valeurs de weighty des
297
* différentes lignes
*/
public double weighty;
/**
* l'espacement à droite et à gauche du composant
*/
public int ipadx;
/**
* l'espacement à au dessus et au dessous du composant
*/
public int ipady;
/**
* l'espacement autour du composant, s'ajoutant à ses propriétés ipadx et ipady
*/
public Insets insets();
/**
* retourne le contenu de l'étiquette textuelle du bouton courant
*/
public String getText();
/**
* rattache l'écouteur d'événéments d'actions "listener" au bouton courant
*/
public void addActionListener(ActionListener listener);
298
5.2.8.2 La classe JButton
1. package : javax.swing.
2. description :
• une classe modélisant tous les boutons cliquables Swing.
• hérite de AbstractButton.
3. quelques méthodes :
/**
* crée un boutton Swing contenant le texte "text"
*/
public JButton(String text);
299
*/
public int getX();
/**
* retourne la position y verticale de l'événement relativement au composant
* cible de l'événement
*/
public int getY();
/**
* méthode invoquée quand le bouton de la souris est lâché (released)
* sur un composant ayant un MouseListener y rattaché
*/
void mouseReleased(MouseEvent e);
/**
* méthode invoquée quand le bouton de la souris est cliquée (pressed and released)
* sur un composant ayant un MouseListener y rattaché
*/
void mouseClicked(MouseEvent e);
/**
* méthode invoquée quand la souris entre et survole une zone non obscure
* d'un composant ayant un MouseListener y rattaché
*/
void mouseEntered(MouseEvent e);
/**
* méthode invoquée quand la souris sort et arrête de survoler une zone
* non obscure d'un composant ayant un MouseListener y rattaché
*/
void mouseExited(MouseEvent e);
300
5.2.9.4 La classe ActionEvent
1. package : java.awt.event
2. description: une classe modélisant tous les événements d’action émis par
un composant et fournissant des informations dessus.
3. quelques méthodes :
/**
* affecte "text" comme valeur de l'étiquette courante
*/
public void setText(String text);
/**
* retourne le contenu de l'étiquette courante
*/
public String getText();
/**
301
* définie l'alignement horizontal de l'étiquette courant selon la constante
* d'alignement "alignment"
*/
public void setHorizontalAlignment(int alignment);
/**
* retourne l'alignement horizontal de l'étiquette courante
*/
public int getHorizontalAlignment();
/**
* définie l'alignement vertical de l'étiquette courant selon la constante
* d'alignement "alignment"
*/
public void setVerticalAlignment(int alignment);
/**
* retourne l'alignement vertical de l'étiquette courante
*/
public int getVerticalAlignment();
302
• une classe modélisant un champ de texte monoligne modifiable par
des actions utilisateurs.
• hérite de JTextComponent.
3. quelques méthodes :
/**
* crée un JTextField de taille "columns"
* et contenant le texte "text"
*/
public JTextField(String text, int columns);
303