Java Zriouile
Java Zriouile
Java Zriouile
SOMMAIRE
Chapitre 1 : Programmation Orientée Objets ............................................................................ 6
1. De la programmation classique vers la programmation orientée objet ............................................. 6
2. Concepts de la Programmation Orientée Objets ............................................................................. 6
2.1 Objet .............................................................................................................................................. 7
2.2 Classe ............................................................................................................................................ 7
2.3 Encapsulation ................................................................................................................................. 7
2.4 Héritage ......................................................................................................................................... 7
2.5 Polymorphisme .............................................................................................................................. 8
3. Comment penser POO.................................................................................................................... 8
Chapitre 2 : Vue d’ensemble de la plate-forme Java .............................................................. 9
1. Introduction ..................................................................................................................................... 9
2. Caractéristiques ................................................................................................................................ 9
3. La plateforme Java ........................................................................................................................... 9
4. Java : de l’édition à l’exécution ....................................................................................................... 10
5. Le Java SE Development Kit ......................................................................................................... 10
6. Java : les éditions ............................................................................................................................ 10
7. Génération de code exécutable dans les langages de programmation ........................................... 10
8. Génération de code en java ............................................................................................................ 11
9. Différents modes de compilation ................................................................................................... 11
10. Avantages de la JVM pour Internet ............................................................................................ 11
11. Exemple: Mon premier programme en Java .............................................................................. 12
12. Exécution d’un programme Java ................................................................................................ 13
Chapitre 3 : Structures de contrôle ............................................................................................ 14
1. Variables ........................................................................................................................................ 14
1.1. Déclaration des variables........................................................................................................ 14
1.2. Initialisation des variables....................................................................................................... 14
2. Style de programmation non standard ........................................................................................... 15
3. L’affectation ................................................................................................................................... 15
4. Types de données en Java .............................................................................................................. 15
4.1. Types primitifs ....................................................................................................................... 15
4.2. Type objet: Constante null ..................................................................................................... 17
5. Transtypage.................................................................................................................................... 17
6. Principaux opérateurs .................................................................................................................... 18
6.1. Opérateurs arithmétiques....................................................................................................... 18
6.2. Opérateurs d’affectation ......................................................................................................... 18
6.3. Opérateurs d’incrémentations et décrémentations ................................................................ 18
Prof : R.ZRIOUILE Page 1
2éme année DSI POO-Java-
4.1. BorderLayout......................................................................................................................... 97
4.2. FlowLayout ............................................................................................................................ 97
4.3. CardLayout ............................................................................................................................ 98
4.4. GridLayout............................................................................................................................. 99
4.5. BoxLayout ............................................................................................................................. 99
4.6. Programme sans gestionnaire de mise en forme ............................................................... 100
4.7. Une classe Insets pour gérer les marges ............................................................................... 100
5. JTextArea..................................................................................................................................... 101
6. JTable .......................................................................................................................................... 101
6.1. Tables simples ..................................................................................................................... 102
6.2. Modèles de table .................................................................................................................. 102
- Héritage
- Polymorphisme
2.1 Objet
Un objet est une structure informatique caractérisée par un état et un ensemble d'opérations
exécutables par cet objet qui caractérise son comportement.
Objet = état + comportement (opérations)
Exemple:
Une Fenêtre :
Etat : position, taille, bordure, titre, couleur,...
Opérations: déplacer, réduire, agrandir...
Un Fichier :
Etat : nom, directory, id, protections, propriétaire, contenu,
Opérations : ouvrir, fermer, détruire,
2.2 Classe
Une classe c’est la description d’un ensemble d’objets ayant une structure de données
commune et disposant des mêmes méthodes. Les objets apparaissent alors comme des
variables d’un tel type classe (en P.O.O., on dit aussi qu’un objet est une instance de sa
classe). Bien entendu, seule la structure est commune, les valeurs des champs étant propres à
chaque objet. En revanche, les méthodes sont effectivement communes à l’ensemble des
objets d’une même classe.
Exemple : Materiel
Personne
-Nom :String -Nom :String
-Prenom :String -Prix :int
-Age :int -Nombre :int
+affiche() :void +affiche() :void
+calculeAge() :int +achete() :void
Classe Instances
-Nom : Meknassi
Personne -Prenom :Ali
-Nom :String -Age :23
-Prenom :String Instanciatio
-Age :int n -Nom : Kadiri
+affiche() :void -Prenom :Hamza
+calculeAge() :int -Age :30
2.3 Encapsulation
L’Encapsulation signifie qu’il n’est pas possible d’agir directement sur les données d’un
objet; il est nécessaire de passer par ses méthodes, qui jouent ainsi le rôle d’interface
obligatoire. On traduit parfois cela en disant que l’appel d’une méthode est en fait l’envoi
d’un message à l’objet.
2.4 Héritage
L’héritage permet de définir une nouvelle classe à partir d’une classe existante (qu’on réutilise
en bloc !), à laquelle on ajoute de nouvelles données et de nouvelles méthodes. La conception
de la nouvelle classe, qui hérite des propriétés et des aptitudes de l’ancienne, peut ainsi
s’appuyer sur des réalisations antérieures parfaitement au point et les spécialiser à volonté.
Comme on peut s’en douter, l’héritage facilite largement la réutilisation de produits existants,
d’autant plus qu’il peut être réitéré autant de fois que nécessaire (la classe C peut hériter de B,
qui elle-même hérite de A).
Exemple :
Personne Materiel
-nom :string -nom :string
-prenom :string -prix :int
-age :int -nombre :int
+affiche() :void +affiche() :void
+calculeAge() :int +achete() :void
La roue :
97% des machines d'entreprises ont une JVM (Java Virtual Machine) installée
Java est téléchargé plus d'un milliard de fois chaque année
Il y a plus de 9 millions de développeurs Java dans le monde
Java est un des langages les plus utilisé dans le monde
Plus de 3 milliards d'appareils mobiles peuvent mettre en oeuvre Java
Plus de 1,4 milliards de cartes à puce utilisant Java sont produites chaque année
2. Caractéristiques
Le langage Java possède de nombreuses caractéristiques :
C’est un langage compilé : avant d’être exécuté, il doit être traduit dans le langage de
la machine sur laquelle il doit fonctionner.
Il emprunte sa syntaxe en grande partie du langage C et C++.
Les programmes Java peuvent être exécutés sous forme d’applications indépendantes
ou distribuées à travers le réseau et exécutées par un navigateur Internet sous forme
d’applets.
Le langage Java a la particularité principale d’être portable sur plusieurs systèmes
d’exploitation tels que Windows, MacOS ou Linux. C’est la plateforme qui garantit la
portabilité des applications développées en Java.
3. La plateforme Java
Une plateforme est un environnement matériel et/ou logiciel dans lequel un programme
tourne. La plupart des plateformes peuvent être décrites comme une combinaison du système
d’exploitation et du matériel sous-jacent. La plateforme Java est une plateforme de
développement purement logiciel qui tourne sur d’autres plateformes basées sur le matériel.
La plateforme Java a deux composants :
La Machine Virtuelle Java (Java Virtual Machine): programme permettant
d'interpréter et d'exécuter le bytecode Java (proche du langage machine).
L’API Java (Java Application Programming Interface): ensemble de bibliothèques
contenant des classes et interfaces organisées en Packages.
Remarque:
La JVM est contenue dans un framework d’exécution appelé JRE (Java Runtime
Environment). Elle est disponible pour plusieurs systèmes d’exploitation (Microsoft
Windows, Solaris OS, Linux ou Mac OS).
5. Le Java SE Development Kit
Pour exécuter une application développée avec Java, il faut télécharger le JRE. Cependant,
pour les développeurs il faut télécharger le kit de développement Java (JDK). Le JDK est le
kit de développement de référence, distribué gratuitement sur Internet par Sun. La version
courante du JDK est JDK SE 11. Le JDK contient aussi le JRE.
Le JDK SE est composé d'un certain nombre d'outils:
Javac : C'est le compilateur Java
Java : Exécute le ou les fichiers compilés par Javac
AppletViewer : Ce programme permet d'exécuter une Applet Java sans nécessité
d'utiliser un navigateur web
Javadoc : Outil permettant de construire, à partir des commentaires insérés dans des
sources Java, une documentation HTML
Il y a plusieurs environnements de développement. Parmi lesquelles on peut citer: eclipse et
netbeans. Ils sont téléchargés depuis les sites suivants
http://www.eclipse.org
http://www.netbeans.org
6. Java : les éditions
Les principales éditions de Java sont:
Java ME : Java Micro Edition
Prévu pour le développement d'applications embarquées (assistants personnels et terminaux
mobiles..)
Java SE : Java Standard Edition
Destiné au développement d'applications pour ordinateurs personnels
Java EE : Java Entreprise Edition
Destiné à un usage professionnel avec la mise en œuvre de serveurs (serveurs d’applications
et serveurs Web)
7. Génération de code exécutable dans les langages de programmation
Le code est généré par un compilateur en plusieurs étapes :
Vérification syntaxique.
Vérification sémantique (typage).
Production de code dans un langage plus proche de la machine.
Important:
1. Ce code doit être sauvegardé obligatoirement dans le Fichier source nommé «
Principale.java »
2. Une classe exécutable doit posséder une méthode ayant la signature public static void
main(String[] args).
Dans le cas de l’environnement JDK.
Pour compiler il suffit d’utiliser la commande javac : javac Principale.java.
Pour exécuter, il suffira d’utiliser la commande: java Principale.
qui interprète le bytecode de la méthode main() de la classe Principale.
public class Principale{…..}:La ligne suivante commence par public class, qui veut
dire que nous allons définir une nouvelle classe Java, suivi du nom de cette
classe, qui est aussi le nom de notre programme.
Sachez simplement pour l'instant les choses suivantes :
Un programme comporte au moins une classe.
Cette classe doit obligatoirement porter le même nom que le fichier dans lequel le
programme est enregistré. Le fichier possède, en plus, l'extension .java
La deuxième ligne se termine par le caractère {, qui marque le début d'un bloc. Nous verrons
plus loin ce que représente exactement un bloc. Sachez seulement pour l'instant que la
déclaration d'une nouvelle classe est suivie de sa définition, et que celle-ci est incluse dans un
bloc, délimité par les caractères { et } ;
public static void main (String [] args){…} : cette ligne permet de définir la méthode
particulière nommé main.
main() { signifie que nous allons définir une méthode, ce qui est indiqué entre autres, par les
parenthèses (). Une méthode est une sorte de procédure appartenant à une classe.
Lorsque la méthode est exécutée, elle prend des paramètres de types précis et renvoie une
valeur de type tout aussi précis.
Le mot void désigne le type de valeur renvoyé par la méthode. Et justement, void signifie
"rien", c'est-à-dire aucune valeur.
public : obligatoire pour que votre programme puisse s’exécuter. Il indique que notre
méthode peut être utilisée par n'importe qui, c'est-à-dire par d'autres classes. Oublier le
mot public n'empêcherait pas le programme d'être compilé normalement, mais cela
empêcherait l'interpréteur de l'utiliser
Static: Le mot static a une signification un peu plus complexe, qui s'éclaircira dans un
prochain chapitre. Certaines méthodes sont de type static et d'autres non. Sachez
simplement pour l'instant que ce qui est static appartient à une classe et ce qui ne l'est
pas à une instance.
String[] args : permet de récupérer des arguments transmis au programme au moment
de son lancement. On peut lancer un programme sans fournir d’arguments, mais
l’indication String args[] est obligatoire.
Dans l'exemple simplifié, la méthode ne prend pas de paramètres. Dans notre programme réel,
elle prend un paramètre, dont le nom est args et qui est de type String[]. Nous verrons plus
loin ce que cela signifie.
Pour résumer, retenez qu'une application Java doit contenir une classe : portant le même nom
que le fichier dans lequel elle est enregistrée, comportant (au moins) une méthode : de type
public et static appelée main, ayant un argument.
System.out.println ("Mon premier programme Java") ; cette ligne sert à définir le
contenu de notre programme qui va afficher le message Mon premier programme Java.
Cette ligne constitue le corps de la méthode main. Elle comporte un appel à une méthode et
un paramètre. La méthode appelée est println. Cette méthode prend un paramètre de type
chaîne de caractères et affiche sa valeur sur la sortie standard. Le paramètre est placé entre
parenthèse.
La méthode println à laquelle nous faisons référence ici appartient à l'objet out. Cet objet
appartient lui-même à la classe System.
12. Exécution d’un programme Java
Pour exécuter un programme Java on va utiliser l’enivrement de développement
Eclipse (plus utiliser).
• Types entiers
Java dispose de quatre types entiers, correspondant chacun à des emplacements mémoire de
taille différente, donc à des limitations différentes. Le tableau suivant en récapitule leurs
caractéristiques. Notez l’existence de constantes prédéfinies de la forme
1.40239846E-45 3.40282347E38
Float 4 7
(Float.MIN_VALUE) (Float.MAX_VALUE)
4.9406564584124654E-324 1.797693134862316E302
Doule 8 15
(Double.MIN_VALUE) (Double.MAX_VALUE)
• Type caractère
Comme la plupart des langages, Java permet de manipuler des caractères. Mais il offre
l’originalité de les représenter en mémoire sur deux octets en utilisant le code universel
Unicode (les 65536 combinaisons qu’offre Unicode, on retrouve les 128 possibilités du code
ASCII restreint (7 bits) et même les 256 possibilités du code ASCII/ANSI (Latin 1) utilisé par
Windows).
• Type booléen
Ce type sert à représenter une valeur logique du type vrai/faux. Il n’existe pas dans tous les
langages car il n’est pas aussi indispensable que les autres. En effet, on peut souvent se
contenter d’expressions booléennes du genre de celles qu’on utilise dans une instruction if :
if (n<p) ..... // n<p est une expression booléenne valant vrai ou faux
En Java, on peut disposer de variables de ce type, ce qui permettra des affectations telles que:
boolean ordonne ; // déclaration d’une variable de type booléen
.....
ordonne = n<p ; // ordonne reçoit la valeur de l’expression booléenne n<p
6. Principaux opérateurs
Les opérateurs Java sont voisins du C.
6.1. Opérateurs arithmétiques
7. Instructions de contrôle
Les structures de contrôle sont presque les mêmes que celles utilisées en C ou en C++. On les
rappelle ci-dessous en précisant les spécificités Java.
Structure de contrôle Syntaxe Commentaire
Les parenthèses sont
if (expression) instruction ; obligatoires en Java autour
instruction conditionnelle de l’expression booléenne.
if De même le point-virgule est
if (expression) {bloc d’instructions} obligatoire en fin de bloc.
if (expression) instruction ;
On ne peut pas donner une
instruction conditionnelle else instruction ;
instruction vide après la
if else if (expression) {bloc d’instructions}
condition if.
else {bloc d’instructions}
La partie initialisation se
compose d’une ou plusieurs
initialisations séparées par
des virgules. La partie test
for(initialisation;test;incrémentation)
la boucle for est une expression
{bloc d’instructions}
booléenne. La partie
incrémentation peut contenir
plusieurs instructions
séparées par des virgules.
Interruption de l’itération en
cours et passage à
break ;
l’instruction suivant la
utilisation de break et boucle.
continue dans les boucles Interruption de l’itération en
cours et retour au début de la
continue ;
boucle avec exécution de la
partie incrémentation.
while (expression booléenne)
l’instruction while
{bloc d’instructions}
Les blocs sont délimités par
deux instructions case !
switch (variable){ Lorsqu’une égalité est
case valeur1 : instructions1 ; trouvée, le bloc d’instruction
case valeur2 : instructions2 ; correspondant est exécuté,
l’instruction switch
… ainsi que tous les blocs
default : instructions ; suivant ! Pour qu’un seul
} bloc ne soit exécuté, il faut
utiliser explicitement
l’instruction break.
Exemple:
Rectangle est une classe utilisée pour créer des objets représentant des rectangles particuliers.
• Elle regroupe 4 données de type réel qui caractérisent le rectangle: longueur, largeur et
origine (x,y) (la position en abscisse et en ordonnée de son origine).
• On suppose qu’on effectue les opérations de déplacement et de calcul de la surface du
rectangle.
• Les symboles + et – sont les spécificateurs d’accès (voir plus loin)
Notation UML (Unified Modeling Language)
- : private
# : protected
+ : public
$ (ou souligné) : static
class Rectangle {
int longueur;
int largeur;
int x;
Attributs
int y;
void deplace(int dx, int dy) {
x = x+ dx;
Méthodes y = y + dy;
}
int surface() {
return longueur * largeur;
}
}
NomDeClasse objetId;
NomDeClasse objetId1, objetId2,….;
Remarque:
La déclaration d’une variable de type primitif réserve un emplacement mémoire pour stocker
la variable. Par contre, la déclaration d’un objet, ne réserve pas une place mémoire pour
l’objet, mais seulement un emplacement pour une référence à cet objet (les objets sont
manipulés avec des références).
Exemple:
Considérons la classe ClasseTest
class ClasseTest {
// corps de la classe ClasseTest
}
l’instruction: ClasseTest objA;
déclare objA comme objet (variable) de type ClasseTest
Définit le nom et le type de l’objet.
Déclare que la variable objA est une référence à un objet de la classe ClasseTest. Cela
veut dire qu’on va utiliser une variable objA qui référencera un objet de la classe
ClasseTest.
Aucun objet n’est créé: un objet seulement déclaré vaut « null ».
objA Null
2.3. Création d’un objet
Après la déclaration d’une variable, on doit faire la création (et allocation) de la mémoire de
l’objet qui sera référencé par cette variable. La création doit être demandée explicitement dans
le programme en faisant appel à l’opérateur new. La création réserve de la mémoire pour
stocker l’objet et initialise les attributs. L’expression new NomDeClasse() crée un
emplacement pour stocker un objet de type NomDeClasse.
Exemple
class ClasseTest {
/* Corps de la classe ClasseTest */
}
ClassTest objA ; /* déclare une référence sur l’objet objA */
objA= new ClasseTest(); /* crée un emplacement pour stocker l’objet
objA */
Les deux expressions précédentes peuvent être remplacées par :
ClassTest objA = new ClasseTest();
En générale:
Chaque objet met ses données membres dans sa propre zone mémoire.
Les données membres ne sont pas partagées entre les objets de la même classe.
Exemple : Considérons la classe Rectangle
Cette garantie d’initialisation par défaut ne s’applique pas aux variables locales (variables
déclarées dans un bloc, par exemple variables locales d’une méthode)
3. Définition des méthodes
En Java, chaque fonction est définie dans une classe. Elle est définie par:
– un type de retour
– un nom
– une liste (éventuellement vide) de paramètres.
– une suite d’instructions (un bloc d’instructions) qui constitue le corps de la méthode
Syntaxe :
typeRetour nomMethode ( «Liste des paramètres » ) {
}
nomMethode : c’est le nom de la méthode (sa 1ère lettre doit être écrite en minuscule)
« Liste des paramètres » : liste des arguments de la méthode. Elle définit les types et
les noms des informations qu’on souhaite passer à la méthode lors de son appel.
typeRetour : c’est le type de la valeur qui sera retournée par la méthode après son
appel. Si la méthode ne fournit aucun résultat, alors typeRetour est remplacé par le
mot clé void.
Remarques importantes :
1) La portée d’une variable locale est limitée au bloc constituant la méthode où elle est
déclarée. De plus, une variable locale ne doit pas posséder le même nom qu’un argument
muet de la méthode :
void f(int n)
{ float x ; // variable locale a f
float n ; // interdit en Java
.....
}
void g ()
{ double x ;//variable locale à g, indépendante de x locale à f
.....
}
2) Les variables locales ne sont pas initialisées de façon implicite (contrairement aux
champs des objets). Toute variable locale, y compris une référence à un objet, doit être
initialisée avant d’être utilisée, faute de quoi on obtient une erreur de compilation.
4. Accès aux membres d’un objet
4.1. Accès aux attributs (données membres)
Considérons la classe ClassTest suivante:
class ClasseTest {
double x; boolean b;
}
ClasseTest objA = new ClasseTest();
// créer un objet de référence objA
// on peut dire aussi objA est une instance de la classe
ClassTest
// ou tous simplement créer un objet objA
ClasseTest objB = new ClasseTest();
Maintenant l’objet dont la référence objA existe. Pour accéder à une donnée membre on
indique le nom de la référence à l’objet suivi par un point suivi par le nom du membre dans
l’objet de la manière suivante:
nomObjet.nomAttibut
nomObjet = nom de la référence à l’objet
nomAttribut =nom de la donnée membre (attribut).
Exemple :
Pour les objets objA et objB de la classe ClassTest qui sont déjà créés:
objA.b=true; // affecte true à l’attribut b de l’objet objA.
objA.x=2.3; // affecte le réel 2.3 au membre x de l’objet objA.
objB.b=false; // affecte false à l’attribut b de l’objet objB.
objB.x=0.35; // affecte le réel 0.35 au membre x de l’objet objB.
4.2. Accès aux méthodes: appels des méthodes
• Les méthodes ne peuvent être définies que comme des composantes d’une classe.
• Une méthode ne peut être appelée que pour un objet.
• L’appel d’une méthode pour un objet se réalise en nommant l’objet suivi d’un point
suivi du nom de la méthode et de sa liste d’arguments:
nomObjet.nomMethode(arg1, ….)
où :
nomObjet : nom de la référence à l’objet
nomMethode : nom de la méthode.
Exemple 1:
soit f() une méthode qui prend un paramètre de type double et qui retourne une valeur de
type int.
class ClasseTest {
float x; int i; boolean b;
int f(double x) {
int n;
// corps de la fonction f()
return n;
}
}
ClasseTest objA = new ClasseTest(); // créer un objet objA
int j = objA.f(5.3); // affecte à j la valeur retournée par f()
Exemple 2 :
Considérons la classe Rectangle dotée de la méthode
initialise qui permet d’affecter des valeurs à l’origine (aux attributs x et y).
public class Rectangle{
int longueur, largeur; int x,y;
void initialiseOrigine(int x0, int y0) {
x=x0; y=y0;
}
public static void main (String args[]) { Rectangle r1;
r1.longueur=4; r1.largeur=2;
r1. initialiseOrigine(0,0); // affecte 0 aux attributs x et y
// Erreur car l’objet n’est pas encore créé. Il faut tout d’abord le
créer (r1=new Rectangle ();)
}}
Exemple 3:
Crée à l’origine un rectangle r1 de longueur 4 et de largeur 2
public class Rectangle{
int longueur, largeur; int x, y;
void initialiseOrigine(int x0, int y0) {
x=x0; y=y0;}
public static void main (String args[]) {
Rectangle r1=new Rectangle (); r1.longueur=4; r1.largeur=2;
r1.initialiseOrigine(0,0);
}
}
5. Encapsulation (accessibilité)
• Une classe permet d’envelopper les objets : un objet est vu par le reste du programme
comme une entité opaque.
• L'enveloppement [wrapping] des attributs et méthodes à l'intérieur des classes plus
(+) le contrôle d'accès aux membre de l’objet est appelé encapsulation.
• Le contrôle d'accès aux membre de l’objet est appelé cacher l'implémentation: les
membres publiques sont vus de l'extérieur mais les membres privés sont cachés.
• L'encapsulation est un mécanisme consistant à rassembler les données et les méthodes
au sein d'une structure en cachant l'implémentation de l'objet, c'est-à-dire en empêchant
l'accès aux données.
• Possibilité d’accéder aux attributs d’une classe Java mais ceci n’est pas recommandé
car contraire au principe d’encapsulation: les données (attributs) doivent être protégés.
• Accessibles pour l’extérieur par des méthodes particulières (sélecteurs)
Plusieurs niveaux de visibilité peuvent être définis en précédant, la déclaration d’un attribut,
d’une méthode ou d’un constructeur, par un modificateur : private, public ou protected.
Spécificateurs d’accès:
L'encapsulation permet de définir 3 niveaux de visibilité des éléments de la classe.
Ces 3 niveaux de visibilité (public, private et protected) définissent les droits d'accès aux
données suivant le type d’accès:
• public: accès depuis l’extérieure (par une classe quelconque)
• private : accès depuis l’intérieure (accès par une méthode de la classe elle-même)
• protected: se comporte comme private avec moins de restriction. Une classe dérivée a
un accès aux membres protected mais pas aux membres private.
Encapsulation "usuelle": les attributs sont privés, et les méthodes sont publiques
Constitution d’un programme Java
• Un programme Java utilise un ensemble de classes
• Les classes sont regroupées par package
• Une classe regroupe un ensemble d’attributs et de méthodes
Visibilité – Encapsulation
Pour une bonne encapsulation, il est préférable de définir les attributs comme « private ». On
définit alors des méthodes «publiques » (accesseurs) permettant de lire et/ou de modifier les
attributs.
class ClasseTest {
public int x; private int y;
public void initialise (int i, int j){
x=i;
y=j; // accès à l’attribut private y depuis l’intérieure OK
}
}
public class TestA{ // fichier source de nom TestA.java public
static void main (String args[]) {
ClasseTest objA;
objA=new ClasseTest(); // On peut aussi déclarer ClasseTest
objA=new ClasseTest();objA.initialise(1,3);// x vaut 1 et y vaut 3
System.out.println(" x= "+objA.x);
// affiche x = 1 puisque x public, on peut y accéder
System.out.println(" y= "+objA.y);
// ne compile pas car accès à un attribut y privé de ClasseTest
} // depuis l’extérieur (classe TestA)
}
Exemple 2: affichage depuis l’extérieur d’un champs private
Comme les identificateurs st1 et st2 sont des arguments muets pour la méthode initialise(),
alors on peut les noter nom et prenom qui n’ont aucune relation avec les champs private nom
et prenom. Dans ce cas la classe Etudiant peut s’écrire comme suit:
class Etudiant {
private String nom, prenom;
public initialise(String nom, String prenom){
this.nom=nom; this.prenom=prenom;
}
}
L’autoréférence (this) est utilisée principalement :
pour lever une ambiguïté,
dans un constructeur, pour appeler un autre constructeur de la même classe,
lorsqu'une référence à l'instance courante doit être passée en paramètre à une méthode.
Exemple:
class ClasseA{
private ClasseA() { … } // constructeur privé sans arguments
…
}
…
ClasseA a=new ClasseA();
// erreur, car constructeur ClasseA() est privé
Exemple:
Considérons la classe suivante:
class ClasseTest{
public ClasseTest (…) {… } // Constructeur ClasseTest
…
private int n=10; private int p;
}
L’instruction suivante: ClasseTest objA=new ClasseTest(…); Entraîne successivement:
1. initialisation implicite (par défaut) des champs n et p de l’objet objA à 0
2. initialisation explicite: On affecte au champ n la valeur 10 (la valeur figurant dans sa
déclaration).
3. exécution des instructions du constructeur: Le corps du constructeur n’est exécuté
qu’après l’initialisation par défaut et l’initialisation explicite.
9.3. Surcharge des constructeurs (Plusieurs constructeurs)
Les constructeurs peuvent être surchargés comme n’importe quelle autre méthode. Une classe
peut avoir plusieurs constructeurs. Comme le nom du constructeur est identique au nom de
la classe: Java permet la surcharge des constructeurs.
Exemple :
public class Etudiant {
private String nom, prenom;
private int codeNatEtudiant;
public Etudiant(String n, String p) { // Constructeur 1 (2arguments)
nom = n;
prenom = p;
}
public Etudiant(String n, String p, int cne) {
// Constructeur 2 (3 arguments)
nom = n; prenom = p; codeNatEtudiant = cne;
}
}
public class TestEtudiant {
public static void main(String[] args) {
Etudiant e1, e2;
e1 = new Etudiant("Mohd", "Ali");
e2 = new Etudiant("Ouardi", " fatima", 22564321);
}
}
Exemple:
int [] t1 = new int[3] ;
for (int i=0 ; i<3 ; i++) t1[i] = i ;
int [] t2 = new int[2] ;
for (int i=0 ; i<2 ; i++) t2[i] = 10 + i ;
Une méthode d’une classe dérivée a accès aux membres publics de sa classe de base.
Exemple : pour écrire la méthode afficheCouleur, nous pouvons nous appuyer sur la
méthode affiche de Point en procédant ainsi :
public void afficheCouleur ()
{ affiche() ;//équivalent de this.affiche() ;
System.out.println (" et ma couleur est : " + couleur) ;
}
1.4. Redéfinition
On appelle redéfinition (en anglais « overriding ») d’une méthode, la possibilité de définir le
comportement d’une méthode selon le type d’objet l’invoquant, i.e., de donner une nouvelle
implémentation à une méthode héritée sans changer sa signature.
Exemple : Redéfinition de la méthode affiche de la classe Point dans la classe PointCol
public void affiche ( )
{ affiche() ;//équivalent de this.affiche() ;
System.out.println (" et ma couleur est : " + couleur) ;
}
Attention : Il ne faut pas confondre la redéfinition (en anglais « overriding ») et la surcharge
(en anglais «overloading ») qui a été étudiée dans la partie 14 de ce cours et qui correspond à
la possibilité de définir des comportements différents pour la même méthode selon les
arguments passés en paramètres.
2. Polymorphisme
Le polymorphisme est un concept extrêmement puissant en POO, il permet de manipuler des
objets sans connaître tout à fait leur type tout en se basant sur la relation d’héritage.
Le polymorphisme en Java, se traduit par :
La compatibilité entre un type dérivée et un type de base.
La liaison dynamique(ou ligature dynamique) des méthodes : dans le sens où il permet
d’obtenir le comportement adapté à chaque type d’objet, sans avoir besoin de tester sa
nature.
Le polymorphisme se base sur cette affirmation : un objet a comme type non seulement sa
classe mais aussi n’importe quelle classe dérivée.
Exemple1 :
public class graphique {
private int x, y; public class Cercle extends graphique {
public graphique ( int x, int y) { private double rayon =1 ;
this.x = x ; this.y = y ;}
public void identifie () { public Cercle ( int x, int y, double r){
System.out.println (‘’ Je suis une forme super(x,y) ; rayon = r ;}
géometrique ‘’) ;
} public void identifie () {
public void affiche () { System.out.println (‘’ Je suis un cercle ‘’) ;}
this.identifie() ;
System.out.println (‘’ Le centre de l’objet se public double surface (){
trouve dans :’’ + x+ ‘’ et ‘’ + y) ;} return ( rayon * 2* 3.14) ;}
public double surface () {
return (0) ;} }
}
public class Rectangle extends graphique { public class test_poly {
private int larg, long ; public static void main (String [] args) {
public Rectangle ( int x, int y, int larg, int long){ graphique g = new graphique (3,7);
Méthode Fonctionnalité
String toString() Retourne une chaîne de caractères représentant l'objet.
boolean equals(Object obj) Indique si l'objet est égal à un autre.
Retourne la classe d'exécution d'un objet. Par exemple :
Point C = new Point(2, 3);
Class getClass() Class type_objet = C.getClass();
Exemples :
Class getClass():
Exemple d’exécution :
Classe de marin : class Marin
Surcouf
this.l = l;
this.b = b;
}
public boolean equals(RectEquals obj) {
if(this.surface()==obj.surface()) {
return true }
else {
return false;
}
}
public static void main(String []args) {
RectEquals r1= new RectEquals(3,9);
RectEquals r2=new RectEquals(6,4);
System.out.println(r2.equals(r1));
}
Exemple d’exécution
false
protected void finalize()
public class Garbage {
public void demo() {
System.out.println("hello");
}
public void finalize() {
System.out.println("object is garbage collected");
}
public static void main(String [ ]args) {
Garbage s1=new Garbage();
s1.demo();
s1=null;
//s1.demo();
System.gc();// garbage collector methode
}
}
Exemple d’exécution
hello
object is garbage collected.
4. Les classes abstraites
4.1. Concept des classes abstraites
Une classe abstraite est une classe qui ne permet pas d’instancier des objets, elle ne
peut servir que de classe de base pour une dérivation.
Dans une classe abstraite, on peut trouver classiquement des méthodes et des attributs,
dont héritera toute classe dérivée et on peut trouver des méthodes dites « abstraites »
qui fournissent uniquement la signature et le type de retour.
Syntaxe :
abstract class A
{public void f() {……} //f est définie dans A
public abstract void g (int n) ;
//g est une méthode abstraite elle n’est pas définie dans A
}
Utilisation
A a ; //on peut déclarer une référence sur un objet de type A ou dérivé
a = new A (….) ; //Erreur pas d’instanciation d’objets d’une classe abstraite
4.2. . Règles des classes abstraites
Dès qu’une classe abstraite comporte une ou plusieurs méthodes abstraites, elle est
abstraite, et ce même si l’on n’indique pas le mot clé « abstract » devant sa
déclaration.
Une méthode abstraite doit être obligatoirement déclarée « public », ce qui est logique
puisque sa vacation est d’être redéfinie dans une classe dérivée.
Les noms d’arguments muets doivent figurer dans la définition d’une méthode
abstraite
public abstract void g(int) ; //Erreur : nom argument fictif est obligatoire
Une classe dérivée d’une classe abstraite n’est pas obligée de redéfinir toutes les
méthodes abstraites, elle peut ne redéfinir aucune, mais elle reste abstraite tant qu’il y
a encore des méthodes abstraites non implémentées.
Une classe dérivée d’une classe non abstraite peut être déclarée abstraite.
4.3. Intérêt des classes abstraites
Le recours aux classes abstraites facilite largement la conception orientée objet. On peut
placer dans une classe abstraite toutes les fonctionnalités dont on souhaite disposer pour les
classes descendantes :
Soit sous la forme d’une implémentation complète de méthodes (non abstraites) et de
champs (privés ou non) lorsqu’ils sont communs à tous les descendants,
Soit sous forme d’interface de méthodes abstraites dont on est alors sûr qu’elles
existeront dans toute classe dérivée instanciable.
Exemple
abstract class graphique { public class Cercle extends graphique {
private int x, y; private double rayon =1 ;
public graphique ( int x, int y) {
this.x = x ; this.y = y ;} public Cercle ( int x, int y, double r){
public void affiche () { super(x,y) ; rayon = r ;}
System.out.println (‘’ Le centre de l’objet se
trouve dans :’’ + x+ ‘’ et ‘’ + y) ;} public double surface (){
public abstract double surface ();//méthode return ( rayon * 2* 3.14) ;}
abstraite
} }
public class Rectangle extends graphique { public class test_poly2 {
public static void main (String [] args) {
private int larg, long ;
graphique [] tab = new graphique [6];
public Rectangle ( int x, int y, int larg, int long){ //tab[0] = new graphique (3,2); Erreur car une
classe abstraite ne peut pas être instanciée
super (x,y) ; this.long = long ; this.larg = larg ;}
tab[0] = new Cercle (3,2,7);
Remarque : Une classe abstraite peut ne comporter que des méthodes abstraites et aucun
champ. Dans ce cas, on peut utiliser le concept de l’interface.
5. Les interfaces
5.1. Concept d’interface
Si on considère une classe abstraite n’implantant aucune méthode et aucun champ
(sauf les constantes), on aboutit à la notion d’interface.
Une interface définit les entêtes d’un certain nombre de méthodes, ainsi que des
constantes.
L’interface est plus riche qu’un simple cas particulier des classes abstraites :
Une classe peut implémenter plusieurs interfaces (alors qu’une classe ne pouvait
dériver que d’une seule classe abstraite).
La notion d’interface va se superposer à celle de dérivation, et non s’y substitue.
Les interfaces peuvent se dériver.
Une classe dérivée peut implémenter 1 ou plusieurs interfaces, elle peut même
réimplémenter une interface déjà implémentée par la superclasse.
On pourra utiliser des variables de type interface.
5.2. Syntaxe
o Définition d’une interface
public interface I
{void f (int n) ; //public abstract facultatifs
void g () ; //public abstract facultatifs
}
Toutes les méthodes d’une interface sont abstraites. On peut ne pas mentionner le
modificateur de visibilité (par défaut public) et le mot clé « abstract ».
o Implémentation d’une interface
Lorsqu’on définit une classe, on peut préciser qu’elle implémente une interface donnée en
utilisant le mot clé « implements ».
Syntaxe:
public interface I1
{….}
public interface I2
{…}
public class A implements I1, I2
{…..A doit définir les méthodes de I1 et I2}
Exemple
public interface Affichable{
public class Flottant implements Affichable {
void affiche() ;
private float val ;
}
public Flottant (float n)
public class Entier implements Affichable {
{val = n ;}
private int val ;
public void affiche() {
public Entier (int n) {val = n ;}
System.out.println (« Je suis un flottant de
public void affiche() {
valeur » + val) ; }
System.out.println (« Je suis un entier de valeur
}
» + val) ;}}
public class TestInterface {
public static void main (String [] args) {
Affichable [] tab = new Affichable [2]; Résultat de l’exécution
tab[0] = new Entier (25); - Je suis un entier de valeur 25
tab [1] = new Flottant (1.25);
tab [0].affiche(); - Je suis un flottant de valeur 1.25
tab [1].affiche; } }
Interface et constantes
Une interface peut renfermer aussi des constantes symboliques qui seront accessibles à toutes
les classes implémentant l’interface :
public interface I
{void f (int n) ; //public abstract facultatifs
void g () ; //public abstract facultatifs
static final int max = 100 ;
}
Les constantes déclarées sont toujours considérées comme « static » et « final »
5.3. Interface et dérivations
L’interface est totalement indépendante de l’héritage : Une classe dérivée peut implémenter
une ou plusieurs interfaces.
interface I1 {…..}
interface I1 {…..}
class A implements I1 {……}
class B extends A implements I1, I2 {…..}
Exemple
interface I1
{void f(int n) ;
static final int max = 100;
}
interface I2 extends I1
{void g (int n);
static final int min = 10;
}
Error : décrit les erreurs internes ou le manque de ressources dans le système d’exécution de
Java.
Exception : se sépare également en deux branches : les exceptions dérivant de
RuntimeException et les autres.
}
}
Exemples d’exécution:
Exception :java.lang.ArrayIndexOutOfBounds : 4
Fin du main
Exemple 4 : Division par zéro (dans main RuntimeException)
1 Une classe d’exception se définit en héritant de la classe Exception déjà définie dans l’API java.
On indique le type d’exceptions qui peuvent être rencontrées dans les méthodes de la classe Point
2 par le mot clé throws.
4 Ensuite pour récupérer une exception lancée par une méthode, on utilise les instructions try et
catch :
Exemple d’exécution :
interface Comparable {
public int compareTo(Object o);
}
La méthode compareTo permet de comparer l’objet courant (this) à l’objet o reçu en argument
et renvoyer un entier (dont la valeur exacte est sans importance) :
négatif (la valeur -1)si l’on considère que l’objet courant est "inférieur" à l’objet o (au
sens de l’ordre qu’on veut définir),
nul (la valeur 0)si l’on considère que l’objet courant est égal à l’objet o (il n’est ni
inférieur, ni supérieur),
positif (la valeur 1)si l’on considère que l’objet courant est "supérieur" à l’objet o,
2. Interfaces Cloneables
L’interface Comparable, nécessite l’implémentation de la méthode clone :
interface Cloneable {
public Object clone();
}
Une classe qui veut que ses instances puissent être clonés superficiellement devra
implémenter l’interface Cloneable et redéfinir la méthode clone() :
Une classe qui veut que ses instances puissent être clonés en profondeur devra
implémenter l’interface Cloneable et redéfinir la méthode clone() :
this.nom = nom;
this.prenom = prenom;
}
public Object clone() // Permet de cloner l'objet
{
Object o=null;
Try {
o = super.clone();// Appele la methode clone() de la classe
// parente ( la classe Object)
}
catch (CloneNotSupportedException e) //Intercepte une erreur
//lors de la copie
{
System.out.println(e);
}
return o; // ATTENTION : Renvoie un objet de la Classe Object
}
public void affiche() {
System.out.println("personne: "+prenom+"; "+nom);
}
public void setPrenom(String n) {
this.prenom=n;
}
}
public class Test {
public static void main(String []args) {
Personne p=new Personne("youssef","dahani") ;
Personne p1=(Personne) p.clone();
System.out.println( p1);
System.out.println(p);
p.affiche();
p1.affiche();
p1.setPrenom("Ahmadi");
p.affiche();
p1.affiche();
}
}
Exemple2 : Clonage superficielle : Classe personne
//***********************************************************
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void affiche() {
System.out.println("personne: "+prenom+"; "+nom);
}
public void setPrenom(String n) {
this.prenom=n;
}
}
public class Test {
public static void main(String []args) {
try{
Personne p=new Personne("youssef","dahani");
Personne p1=(Personne)p.clone();
System.out.println(p);
System.out.println(p1);
p.affiche();
p1.affiche();
p.setPrenom("Ahmadi");
p.affiche();
p1.affiche();
}
catch (CloneNotSupportedException e){
throw new InternalError();
}
}
}
Exemple3 : Clonage profondeur: Classe Cellule
return tmp;
}
public void afficher(){
System.out.println(t[0]+" "+t[1]);
}
public void changeMe(){
t[0] = 11;
t[1] = 12;
}
}
public class TestCellule {
public static void main(String args[]){
Cellule x = new Cellule(); // x Objet Cellule
x.afficher();
Cellule y = (Cellule) x.clone(); // y clone de x
y.afficher();
x.changeMe();
y.afficher();
x.afficher();
System.out.println(x);
System.out.println(y);
}
}
3. Classes enveloppes
Les classes enveloppes (wrappers en anglais) vont permettre de manipuler les types primitifs
comme des objets. Chacun des 8 types primitifs (boolean, byte, char, short, int, long, float et
double) possède une classe correspondante, appelée classe enveloppe, qui généralise le type.
Les 8 classes enveloppes sont:
Boolean,
Byte,
Character,
Short,
Integer,
Long,
Float
Double.
Ces classes enveloppes sont définies dans java.lang et peuvent donc être utilisées sans
importation.
Toutes les classes enveloppes disposent d’un constructeur recevant un argument d’un type
primitif :
Integer nObj = new Integer (12) ; // nObj contient la référence à un objet
// de type Integer encapsulant la valeur 12
Double xObj= new Double (5.25) ; // xObj contient la référence à un objet
// de type Double encapsulant la valeur 5.25
Elles disposent toutes d’une méthode de la forme xxxValue (xxx représentant le nom du type
primitif) qui permet de retrouver la valeur dans le type primitif correspondant :
Prof : R.ZRIOUILE Page 59
2éme année DSI POO-Java-
Pour exporter une information vers une destination externe, le programme peut ouvrir un flux
vers cette destination et y écrire l’information séquentiellement.
Un flux(ou flot ou stream en anglais) est une suite de données (octets, caractères, objets
quelconques) successivement lues ou écrites.
Lecture Écriture
Ouvre un flux en lecture Ouvre un flux en écriture
Lit tant qu’il ya quelque chose à lire Écrire tant qu’il y a quelque chose à écrire
Ferme le flux Ferme le flux
En Java, le nombre de classes intervenant dans la manipulation des flux est important (plus de
50). Dans ce chapitre, on va réaliser les opérations classiques suivantes :
création séquentielle d’un fichier binaire ;
lecture séquentielle d’un fichier binaire ;
accès direct à un fichier binaire ;
création d’un fichier texte ;
lecture d’un fichier texte ;
while (n != 0) ;
sortie.close () ;
System.out.println ("*** fin creation fichier ***");
}
}
Exemple d’exécution :
donnez le nom du fichier a creer : entiers
donnez un entier : 12
donnez un entier : 85
donnez un entier : 55
donnez un entier : 128
donnez un entier : 47
donnez un entier : 0
*** fin creation fichier ***
Remarques:
On peut fournir en argument du constructeur de FileOutputStream un objet de type File à
la place d’un objet de type String car Java dispose d’une classe File permettant de
manipuler des noms de fichiers ou de répertoires.
Il est possible de doter un flux d’un tampon. Il s’agit d’un emplacement mémoire qui sert
à optimiser les échanges avec le flux.
Les informations sont d’abord enregistrées dans le tampon, et ce n’est que lorsque ce
dernier est plein qu’il est "vidé" dans le flux.
Pour doter un flux de type FileOutputStream d’un tampon, on crée un objet de type
BufferedOutputStream en passant le premier en argument de son constructeur.
DataOutputStream sortie = new DataOutputStream ( new BufferedOutputStream
( new FileOutputStream (nomfich))) ;
on crée un objet entree qui, par l’intermédiaire de l’objet f, se trouve associé au fichier
entiers.dat. Ici encore, les deux instructions (création FileInputStream et création
DataInputStream) peuvent être condensées en :
DataInputStream entree = new DataInputStream ( new FileInputStream ("entiers.dat")) ;
Enfin, la classe DataInputStream dispose de méthodes permettant de lire sur un flux (donc ici
dans un fichier) une valeur d’un type primitif quelconque. Elles se nomment readInt (pour
int), readFloat (pour float)... Ici, readInt nous conviendra.
Exemple :
Voici un programme complet qui relit un fichier binaire d’entiers du type de ceux créés.
import java.io.* ; // pour les classes flux
import java.util.Scanner;
public class LecFichierBinaire
{ public static void main (String args[]) throws IOException
{ String nomfich ;
int n = 0 ;
System.out.print ("donnez le nom du fichier a lister : ") ;
Scanner Clavier=new Scanner(System.in);
nomfich = Clavier.nextLine() ;
DataInputStream entree = new DataInputStream
( new FileInputStream (nomfich))
System.out.println ("valeurs lues dans le fichier " + nomfich + " :") ;
boolean eof = false ; // sera mis a true par exception EOFile
while (!eof)
{ try
{ n = entree.readInt () ;}
catch (EOFException e)
{ eof = true ;}
if (!eof) System.out.println (n) ;}
entree.close () ;
System.out.println ("*** fin liste fichier ***");
}
}
Exemple d’exécution :
donnez le nom du fichier a lister : entiers
12
85
55
128
47
0
*** fin fin liste fichier ***
Remarques:
On peut fournir en argument du constructeur de FileInputStream un objet de type File à la
place d’un objet de type String car Java dispose d’une classe File permettant de
manipuler des noms de fichiers ou de répertoires.
Pour doter un flux de type FileInputStream d’un tampon, on crée un objet de type
BufferedInputStream en passant le premier en argument de son constructeur.
DataInputStream sortie = new DataInputStream ( new BufferedInputStream
( new FileInputStream (nomfich))) ;
4. Accès directe à un fichier binaire
Pour réaliser l’accès direct à un fichier binaire java dispose une classe spécifique
RandomAccessFile. Cette classe dispose des fonctionnalités des deux classes
DataInputStream et DataOutputStream, en particulier des méthodes readInt, readFloat,
writeInt, writeFloat... Les constructeurs de la classe RandomAccesFile besoin de deux
paramètres:
Nom de fichier à accéder.
Mode d’accès : deux valeurs "r" (lecture seule) ou "rw" (lecture et écriture).
RandomAccesFile entree = new RandomAccesFile(“entiers ’’, ‘’r’’);
RandomAccessFile dispose d’une méthode spécifique seek permettant d’agir sur le "pointeur
de fichier".
Remarques:
Le pointeur de fichier correspond au rang du prochain octet à lire ou à écrire (le premier octet
portant le numéro 0).
Exemple :
import java.io.* ;
import java.util.Scanner;
public class AccesDirect
{ public static void main (String args[]) throws IOException
{ String nomfich ;
int n, num ;
RandomAccessFile entree ;
System.out.print ("donnez le nom du fichier a consulter : ") ;
Scanner Clavier=new Scanner(System.in);
nomfich = Clavier.nextLine() ;
entree = new RandomAccessFile (nomfich, "r") ;
do
{ System.out.print ("Numero de l’entier recherche : ") ;
num = Clavier.nextInt() ;
if (num == 0) break ;
entree.seek (4*(num-1)) ;
n = entree.readInt() ;
System.out.println (" valeur = " + n) ;
}
while (num != 0) ;
entree.close () ;
System.out.println ("*** fin consultation fichier ***");
}}
Exemple d’exécution
donnez le nom du fichier a consulter : entiers.
Numero de l’entier recherche : 3
valeur = 55
Numero de l’entier recherche : 5
valeur = 47
Numero de l’entier recherche : 0
*** fin consultation fichier ***
5. Création d’un fichier texte
Nous vous proposons d’écrire un programme qui lit des nombres entiers au clavier et qui,
pour chacun d’entre eux, écrit une ligne d’un fichier texte contenant le nombre fourni
accompagné de son carré, sous la forme suivante : 12 a pour carre 144
On convient que l’utilisateur fournira la valeur 0 pour signaler qu’il n’a plus de valeurs à
entrer. La classe abstraite Writer sert de base à toutes les classes relatives à un flux texte de
sortie. La classe FileWriter, dérivée de Writer, permet de manipuler un flux texte associé à un
fichier. L’un de ses constructeurs s’utilise ainsi: FileWriter f = new FileWriter ("carres.txt") ;
Cette opération associe l’objet f à un fichier de nom carres.txt. S’il n’existe pas, il est créé
(vide). S’il existe, son ancien contenu est détruit. On a donc affaire à un classique ouverture
en écriture.
Les méthodes de la classe FileWriter permettent d’écrire des caractères, des tableaux de
caractères ou des chaînes. Dans certains cas, elles se révéleront suffisantes. Mais, si l’on
souhaite disposer de possibilités de formatage, on peut recourir à la classe PrintWriter qui
dispose d’un constructeur recevant en argument un objet de type FileWriter.
Ainsi, avec : PrintWriter sortie = new PrintWriter (f); on crée un objet sortie qui, par
l’intermédiaire de l’objet f, se trouve associé au fichier carres.txt.
Bien entendu, les deux instructions peuvent être fusionnées en :
PrintWriter sortie = new PrintWriter (new FileWriter ("carres.txt")) ;
Comme nous l’avons vu dans l’introduction, la classe PrintWriter dispose des méthodes print
et println que nous allons pouvoir utiliser exactement comme nous l’aurions fait pour afficher
l’information voulue à l’écran.
Exemple :
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class CreFichierText
{ public static void main (String args[]) throws IOException
{ String nomfich ;
int n ; Scanner Clavier=new Scanner(System.in);
System.out.print ("Donnez le nom du fichier a creer : ") ;
nomfich = Clavier.nextLine() ;
PrintWriter sortie = new PrintWriter (new FileWriter (nomfich)) ;
do
{ System.out.print ("donnez un entier : ") ;
n = Clavier.nextInt() ;
if (n != 0)
{ sortie.println (n + " a pour carre " + n*n) ;
}}
while (n != 0) ; sortie.close () ;
System.out.println ("*** fin creation fichier ***");
}
}
Exemple d’exécution :
Donnez le nom du fichier a creer : carres.txt
donnez un entier : 5
donnez un entier : 12
donnez un entier : 45
donnez un entier : 2
donnez un entier : 0
*** fin creation fichier ***
Voici la liste du fichier ainsi créé :
5 a pour carre 25
12 a pour carre 144
45 a pour carre 2025
2 a pour carre 4
6. Lecture d’un fichier texte
Pour lire un fichier texte on distingue deux situations :
On se contente d’accéder aux lignes du fichier (sans chercher à un interpréter le
contenu).
On souhaite pouvoir accéder aux différentes informations présentes dans une ligne.
6.1. Accès aux lignes d’un fichier texte
Dans la hiérarchie de la superclasse Reader n’existe pas une classe jouant le rôle symétrique
de PrintWriter. Il faut se contenter de la classe FileReader, symétrique de FileWriter. Les
méthodes de cette classe donnent la possibilité d’accéder des caractères, ce qu’il faut prendre
en considération la gestion de la fin de la ligne. En couplant la classe FileReader avec la
classe BufferedReader qui dispose d’une méthode readLine, nous allons pouvoir lire chacune
des lignes de notre fichier.
BufferedReader entree = new BufferedReader (new FileReader ("carres.txt")) ;
La méthode readLine de la classe BufferedReader fournit une référence à une chaîne
correspondant à une ligne du fichier. Si aucun caractère n’est disponible (pas même une
simple fin de ligne), readLine fournit la valeur null.
Exemple:
import java.io.* ;
import java.util.Scanner;
public class LecFichierText
{ public static void main (String args[]) throws IOException
{
String nomfich ;
String ligne ;
Scanner Clavier=new Scanner(System.in);
System.out.print ("Donnez le nom du fichier a lister : ") ;
nomfich = Clavier.nextLine() ;
BufferedReader entree = new BufferedReader (new FileReader
(nomfich)) ;
do
{ ligne = entree.readLine() ;
if (ligne != null) System.out.println (ligne) ;
}
while (ligne != null) ;
entree.close () ;
System.out.println ("*** fin liste fichier ***");
}
}
Exemple d’exécution :
Donnez le nom du fichier a lister : carres.txt
5 a pour carre 25
12 a pour carre 144
45 a pour carre 2025
2 a pour carre 4
*** fin liste fichier ***
6.2. La classe StringTokenizer
Dans l’exemple précédent, nous nous sommes contentés d’accéder aux différentes lignes du
fichier. Dans certains cas, vous pourrez avoir besoin d’accéder à chacune des informations
d’une même ligne. JAVA dispose d’une classe nommée StringTokenizer, qui permet de
découper une chaîne en différents tokens (sous-chaînes), en se fondant sur la présence de
caractères séparateurs qu’on choisit librement. Par ailleurs, on pourra appliquer à ces
différents tokens, les possibilités de conversion d’une chaîne en un type primitif, ce qui
permettra d’obtenir les valeurs voulues.
Nous lisons chaque ligne du fichier comme précédemment. Puis nous construisons, à partir de
la ligne lue (ici, ligneLue), un objet de type StringTokenizer :
StringTokenizer tok = new StringTokenizer (ligneLue, " ") ;
Méthodes de la classe String Tokenizer :
countToken, qui compte le nombre de tokens d’un objet du type StringTokenizer ;
nextToken, qui fournit le token suivant s’il existe
Exemple :
import java.io.* ;
import java.util.* ; // pour StringTokenizer
import java.util.Scanner;
public class Tokenizer {
public static void main (String args[]) throws IOException {
String nomfich ; int nombre, carre ;
System.out.print ("donnez le nom du fichier a lister : ") ;
Prof : R.ZRIOUILE Page 69
2éme année DSI POO-Java-
String getName ()
Fournit une chaîne contenant le nom correspondant (sans nom de chemin).
boolean isHidden()
Fournit true si l’objet correspond à un fichier caché.
boolean canRead()
Fournit true si l’objet correspond à un fichier autorisé en lecture.
boolean canWrite()
Fournit true si l’objet correspond à un fichier autorisé en écriture.
boolean canExecute()
Fournit true si l’objet correspond à un fichier programme exécutable.
setReadOnly ()
Marque l’objet comme étant en lecture seule.
d. Accès aux membres d’un répertoire
String [] liste()
Fournit un tableau de chaînes correspondant.
File [] listeFiles()
Fournit les mêmes informations que la méthode précédente, mais sous la forme plus pratique
d’un tableau d’objets de type File.
Exemple :
import java.io.*;
import java.util.Scanner;
public class TestFichier {
public static void main (String args[])throws IOException{
int n;
File monFichier = new File ("ent.dat");
DataOutputStream sortie = new DataOutputStream(new FileOutputStream
(monFichier));
do { System.out.print ("donnez un entier : ") ;
Scanner Clavier=new Scanner(System.in);
n = Clavier.nextInt() ;
if (n != 0)
Exemple d’exécution
donnez un entier : 3
donnez un entier : 4
donnez un entier : 0
Nom du fichier : ent.dat
Chemin du fichier : ent.dat
Chemin absolu : C:\Users\dell\Desktop\java programme\Exception\Classe File\ent
Droit de lecture : true
Droite d'ecriture : false
Taille de ce fichier en octet: 8
8. sérialisation et désérialisation
La sérialisation est la technique qui permet de transformer une structure de données
complexe en mémoire vers une représentation linéaire, sous la forme d’une chaîne de
caractères, qui peut être transmise via le réseau ou de le sauvegarder dans un fichier binaire.
La désérialisation est le procédé inverse, qui prend une donnée linéaire selon un certain
format et reconstruit une structure de données complexe en mémoire isomorphe à celle qui a
été sérialisée.
8.1. Interface Serializable
L’interface Serializable ne définit aucune méthode mais permet simplement de marquer une
classe comme pouvant être sérialisée. Tout objet qui doit être sérialisé doit implémenter cette
interface ou une de ses classes mères doit l'implémenter. Si l'on tente de sérialiser un objet qui
n'implémente pas l'interface Serializable, une exception java.io.NotSerializableException est
levée.
Exemple
this.taille = taille;
this.prenom = prenom;
}
public String getNom() {
return this.nom;
}
public void setNom( String nom) {
this.nom = nom;
}
public int getTaille() {
return this.taille;
}
public void setTaille( int taille) {
this.taille = taille;
}
public String getPrenom() {
return this.prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
}
8.2. Etapes de sérialisation: Ecrire un objet sérialisé dans un fichier
1- Créer un objet FileOutputStream.
FileOutputStream sortie= new FileOutputStream(‘Personne.txt’);
2- Créer un objet ObjectOutputStream. Cet objet permet d’écrire des objets, mais il ne
peut pas se connecter directement à un fichier. Il a besoin pour ce la d’un
« intermidiaire », ici un FileOutputStream. on va alors chainer les deux flots,
ObjectOutputStream et FileOutputStream
ObjectOutputStream sor= new ObjectOutputStream(‘sortie’);
3- Ecrire les objets a sauvegarder dans ‘Personne.txt’
sor.writeObject(personne1);
sor.writeObject(personne2);
…….
sor.writeObject(personnen);
4- Fermer ObjectOutputStream. La fermeture du premier flot entraine automatiquement
celle des autres.
sor.close();
Chapitre 10 : Collections
1. Définition
Une collection gère un groupe d'un ensemble d'objets d'un type donné ; ou bien c'est un objet
qui sert à stocker d'autres objets.
2. Interfaces
Les interfaces sont organisées on deux catégories : Collection && Map.
hasNext permet de vérifier s'il y a un élément qui suitnext permet de pointer l'élément
suivant.
remove permet de retirer l'élément courant.
Les collections vues comme des ensembles réalisent les 3 opérations mathématiques sur des
ensembles:
union: add et addAll
intersection: retainAll
différence: remove et removeAll
3.2. List
Liste est une collection ordonnée. Elle permet la duplication des éléments. L'interface est
renforcée par des méthodes permettant d'ajouter ou de retirer des éléments se trouvant à une
position donnée. Elle permet aussi de travailler sur des sous listes. On utilise le plus souvent
des ArrayList sauf s'il y a insertion d'élément(s) au milieu de la liste. Dans ce cas il est
préférable d'utiliser une LinkedList pour éviter ainsi les décalages.
public Interface List extends Collection{
// Positional Access
Object get(int index);
Object set(int index, Object element); // Optional
void add(int index, Object element); // Optional
Object remove(int index); // Optional
boolean addAll(int index, Collection c); // Optional
// Search
int indexOf(Object o);
int lastIndexOf(Object o);
// Iteration
ListIterator listIterator();
ListIterator listIterator(int index);
// Range-view
List subList(int fromIndex, int toIndex);
}
Les méthodes de l'interface List permettent d'agir sur un élément se trouvant à un index donné
ou bien un ensemble d'éléments à partir d'un index donné dans la liste.
get (remove) retourne (resp. retirer) l'élément se trouvant à la position index.
set (add & addAll) modifie (resp. ajouter) l'élément (resp. un seul ou une collection)
se trouvant à la position index.
indexOf (lastIndexOf) recherche si un objet se trouve dans la liste et retourner son
(resp. son dernier) index.
subList permet de créer un sous liste d'une liste.
Pour parcourir une liste, il a été défini un itérateur spécialement pour la liste.
public Interface ListIterator extends Iterator{
boolean hasNext();
Object next();
boolean hasPrevious();
Object previous();
int nextIndex();
int previousIndex();
void remove(); //Optional
void set(Object o); // Optional
void add(Object o); // Optional }
hasNext permet de vérifier s'il y a un élément qui suit.
next permet de pointer l'élément courant.
nextIndex retourne l'index de l'élément courant.
Pour les sous listes, elles sont extraites des listes de fromIndex (inclus) à toIndex (non
inclus). Tout changement sur les sous listes affecte la liste de base, et l'inverse provoque un
état indéfini s'il y a accès à la sous liste.
Les classes implémentées l’interface List sont : ArrayList (tableau à taille variable),
LinkedList (liste chaînée) et Vector.
Exemple1: Voici un programme créant un vecteur contenant dix objets de type Integer,
illustrant les principales fonctionnalités de la classe ArrayList ;
import java.util.* ;
public class Array1{
public static void main (String args[]){
ArrayList <Integer> v = new ArrayList <Integer> () ;
System.out.println ("En A : taille de v = " + v.size() ) ;
/* on ajoute 10 objets de type Integer */
for (int i=0 ; i<10 ; i++)
v.add (Integer.valueOf(i)) ;
System.out.println ("En B : taille de v = " + v.size() );
/* affichage du contenu, par acces direct (get) a chaque element */
System.out.println ("En B : contenu de v = ");
for (Integer e : v)
System.out.print (e + " ");
System.out.println ();
/* suppression des elements de position donnee */
v.remove (3);
v.remove (5);
System.out.println ("En C : contenu de v = " + v);
/* ajout d’elements a une position donnee */
v.add (2, Integer.valueOf (100));
v.add (2, Integer.valueOf (200));
v.add (5, Integer.valueOf (200));
System.out.println ("En D : contenu de v = " + v);
/* modification d’elements de position donnee */
v.set (1, Integer.valueOf (1000)) ;
v.set (5, Integer.valueOf (2000)) ;
System.out.println ("En E : contenu de v = " + v);
}
}
Exemple d’exécution :
Exemple2:
import java.util.*;
public class ListExemple {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bernadine");
list.add("Elizabeth");
list.add("Gene");
list.add("Elizabeth");
list.add("Clara");
System.out.println(list);
System.out.println("2: " + list.get(2));
System.out.println("0: " + list.get(0));
LinkedList<String> queue = new LinkedList<String>();
queue.addFirst("Bernadine");
queue.addFirst("Elizabeth");
queue.addFirst("Gene");
queue.addFirst("Elizabeth");
queue.addFirst("Clara");
System.out.println(queue);
queue.removeLast();
queue.removeLast();
System.out.println(queue);
}
}
Exemple d’exécution :
La classe Vector
Les vecteurs sont des objets de type Vector. La gestion des vecteurs est assez similaire à la
gestion des ArrayList.
Vector liste = new Vector() ;
Méthode Description
add(objet) Ajoute un élément objet en fin de liste.
Insère un élément objet dans la liste, à l’indice spécifié
add(indice, objet)
en paramètre.
Ajoute un élément objet en fin de liste et augmente sa
addElement(objet) taille de un.
Retourne l’élément stocké à l’indice spécifié en
elementAt(indice) paramètre.
clear() Supprime tous les éléments de la liste.
Retourne l’indice dans la liste du premier objet donné en
indexOf(objet)
paramètre, ou –1 si objet n’existe pas dans la liste.
Retourne l’indice dans la liste du dernier objet donné en
lastIndexOf(objet)
paramètre, ou –1 si objet n’existe pas dans la liste.
remove(indice) Supprime l’objet dont l’indice est spécifié en paramètre
Supprime tous les éléments compris entre les indices i
removeRange(i, j)
(valeur comprise) et j (valeur non comprise).
Remplace l’élément situé en position i par l’objet
setElementAt(objet, i)
spécifié en paramètre.
size() Retourne le nombre d’éléments placés dans la liste.
Exemple :
import java.util.*;
public class SetExemple {
public static void main(String args[]) {
Set<String> set = new HashSet<String>(); // Une table de Hachage
set.add("Clara");
set.add("Maria");
set.add("Gene");
set.add("Elizabeth");
set.add("Clara");
System.out.println(set);
SortedSet<String> sortedset = new
TreeSet<String>(set); // Un Set trié
System.out.println(sortedset);
}
}
Exemple d’exécution
3.4. Map
C'est un ensemble de paires, contenant une clé et une valeur (en réalité, nous pouvons associer
plusieurs valeurs. Dans ce cas-là, nous sommes en présence d'une multimap.
Deux clés ne peuvent être égales au sens de equals.
L'interface interne Entry permet de manipuler les éléments d'une paire comme suit:
public interface Entry {
Object getKey();
Object getValue();
Object setValue(Object value);
}
getKey & getValue retournent respectivement la clé et la valeur associée à cette clé.
setValue permet de modifier une valeur d'une paire. Remarque : faire attention de ne pas
modifier directement la valeur associée à une clé. Pour le faire, retirer l'ancienne clé (et donc
sa valeur aussi) et ajouter une nouvelle clé (avec cette nouvelle valeur).
public interface Map {
// Basic Operations
Object put(Object key, Object value);
Object get(Object key);
Object remove(Object key);
boolean containsKey(Object key);
boolean containsValue(Object value);
int size();
boolean isEmpty();
// Bulk Operations
void putAll(Map t);
void clear();
// Collection Views
public Set keySet();
public Collection values();
public Set entrySet();
// Interface for entrySet elements
public interface Entry {
Object getKey();
Object getValue();
Object setValue(Object value);
}
}
import java.util.*;
public class MapExample {
public static void main(String args[]) {
Map map = new HashMap();
Integer ONE = new Integer(1);
for (int i=0, n=args.length; i<n; i++) {
String key = args[i];
Integer frequency = (Integer)map.get(key);
if (frequency == null) {
frequency = ONE;
} else {
int value = frequency.intValue();
frequency = new Integer(value + 1);
}
map.put(key, frequency);
}
System.out.println(map);
Map sortedMap = new TreeMap(map);
System.out.println(sortedMap);
}
}
Mélanger:
shuffle(List liste) ; mélange les éléments de manière aléatoire.
Manipuler:
reverse(List liste) ; inverse les éléments de la liste.
fill (List liste, Object element) ; initialise les éléments de la liste avec element.
copy(List dest, List src) ; copy une liste src dans une liste dest.
Rechercher:
binarySearch(List list, Object element) ; une recherche binaire d'un élément.
binarySearch(List list, Object element, Comparator comp) ; une recherche binaire d'un
élément en utilisant un comparateur.
Des algorithmes qui s'appliquent sur toutes les collections:
Ces alogorithmes effectuent des recherches extrêmes: min, max etc.
min (Collection) et max (Collection).
Exercice
1. Définir une classe Stagiaire avec les attributs suivants : nom et prénom.
2. Définir un constructeur permettant d’initialiser les attributs d'un objet stagiaire par des
valeurs saisies par l’utilisateur.
3. Définir la méthode toString ( ) permettant d’afficher les informations d'un stagiaire.
4. Écrire un programme testant la classe Stagiaire.
Déclarer une collection d'objet stagiaire.
Ajouter des stagiaires dans la collection.
Afficher la liste des stagiaires.
5. Modifier la classe de teste pour afficher la liste des stagiaires triée dans un ordre
alphabétique des noms, si des stagiaires ont le même nom, ils seront triés en ordre
alphabétique des prénoms.
Exemple :
o ALAMI Ali
o SAFI Amal
o SAFI Karim
o SAFI Widad
Note: Pour définir un ordre de tri, la classe stagiaire doit implémenter l'interface
Comparable, ensuite redéfinir la méthode compareTo ().
Correction
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class TestStagiaire {
public static void main(String[] args) {
List<Stagiaire> stagiaires = new ArrayList<Stagiaire>();
stagiaires.add(new Stagiaire("yves", "amine"));
stagiaires.add(new Stagiaire("alaoui", "samir"));
stagiaires.add(new Stagiaire("yves", "zineb"));
stagiaires.add(new Stagiaire("safi", "amal"));
Collections.sort(stagiaires);
Chapitre 11 : Threads
1. Notion de threads
La machine virtuelle java (JVM) permet d'exécuter plusieurs traitements en parallèle (en
pratique, ils s'exécutent par “tranche” et en alternance sur le processeur). Ces traitements sont
gérés par des threads of control (fil de contrôle), ou plus simplement threads.
Les threads Java sont des processus légers : ils partagent un ensemble de codes, données et
ressources au sein d'un processus lourd qui les héberge (ce processus est la JVM).
Avantages des processus légers par rapport aux processus système :
- rapidité de lancement et d'exécution
- partage desressources système du processus englobant
- simplicité d'utilisation
Intérêts d'une application multi-threads :
gérer l'exécution de traitements longs sans bloquer les autres
Exemples:
- calculs, affichage et gestion des interactions dans une interface graphique
- lancer des programmes démons qui tournent en tâche de fond
lancer plusieurs exécutions du même code simultanément sur différentes données
Exemples :
- répondre à plusieurs requêtes en même temps dans un serveur
- traiter deux flux sonores en parallèle
- simuler le parallèlisme nécessaire à certaines classes d'applications
Inconvénients d'une application multi-threads :
- il faut gérer les problèmes de synchonisation entre threads
- une telle application est difficile à écrire et à débogger
2. Thread et interface runnable
En Java, un thread est une instance de la classe Thread qui implémente l'interface Runnable
dont la méthode run() décrit le traitement à lancer.
public interface Runnable{
public void run();
}
Un thread est crée en sous classant la classe Thread et en redéfinissant sa méthode run(), ou
en instanciant le thread avec un objet Runnable.
new Thread(new Runnable(){
public void run(){
});
Un Thread qui n'est plus référencé n'est pas détruit par le garbage collector car il est
enregistré par un contrôleur d'exécution. Le thread principal est celui de la méthode main.
Exemple 1
public class TstThr1
{ public static void main (String args[])
{ Ecrit e1 = new Ecrit ("bonjour ", 10, 5) ;
Ecrit e2 = new Ecrit ("bonsoir ", 12, 10) ;
Ecrit e3 = new Ecrit ("\n", 5, 15) ;
e1.start() ;
e2.start() ;
e3.start() ;
}}
Prof : R.ZRIOUILE Page 85
2éme année DSI POO-Java-
Exemple 2
public class TstThr3
{ public static void main (String args[])
{ Ecrit e1 = new Ecrit ("bonjour ", 10, 5) ;
Ecrit e2 = new Ecrit ("bonsoir ", 12, 10) ;
Ecrit e3 = new Ecrit ("\n", 5, 15) ;
Thread t1 = new Thread (e1) ; t1.start() ;
Thread t2 = new Thread (e2) ; t2.start() ;
Thread t3 = new Thread (e3) ; t3.start() ;
}
}
class Ecrit implements Runnable
{ public Ecrit (String texte, int nb, long attente)
{ this.texte = texte ;
this.nb = nb ;
this.attente = attente ;
}
public void run ()
{ try
{ for (int i=0 ; i<nb ; i++)
{ System.out.print (texte) ;
Thread.sleep (attente) ; // attention Thread.sleep
}
}
catch (InterruptedException e) {} // impose par sleep
}
Prof : R.ZRIOUILE Page 86
2éme année DSI POO-Java-
Exemple d’exécution
bonjour bonsoir
bonjour bonsoir
bonjour bonjour bonsoir bonjour
bonjour bonsoir bonjour bonjour bonsoir
bonjour bonjour bonsoir
bonsoir bonsoir bonsoir bonsoir bonsoir bonsoir
3. Durée de vie d’un thread
destroy, resume, suspend et stop sont des méthodes agissant sur l'état d'un thread, mais qui
peuvent poser des problèmes de blocage ou de mauvaise terminaison et sont donc
désapprouvées.
Activation : la méthode start() appelle la méthode run() (start() n'est pas bloquante dans le
thread appelant).
Destruction : elle intervient quand la méthode run() se termine.
Il est possible d'interrompre le thread en utilisant la méthode interrupt() qui crée une
InterruptedException si le thread est en attente.
public class MonThread extends Thread{
public void run(){
try{
... // traitement, avec des périodes de sommeil et/ou d'attente
}
catch(InterruptedException e){
... // libération propre des ressources
}
// autre traitement
}
}
catch(InterruptedExceptione){
System.out.println(this.getName()+" a ete interrompu");
}
}
Une valeur de priorité est affectée à chaque thread et détermine sa priorité d'accès au
temps CPU. Mais la JVM n'assure pas le time slicing : le temps CPU n'est pas forcément
partagé équitablement entre threads de même priorité.
La priorité est modifiée par setPriority(int i) et accédée par int getPriority().
La méthode de classe Thread.yield() suspend l'exécution du thread qui est en train de
s'exécuter pour donner la main à un autre. L'appel de cette méthode peut redonner la main
au thread courant!
La méthode setDaemon(boolean on) appelée avant start() permet de faire du thread un
démon, processus de basse priorité qui tourne en tâche de fond.
Exemple : le garbage collector
6. Synchronisation
Les threads s'exécutant en parallèle sur des données qui peuvent être communes, il faut
gérer des conflits d'accès et des problèmes de synchronisation entre threads.
La synchronisation peut consister à entremêler les exécutions des threads de manière à ce
qu'ils n'accèdent à certaines données ou à certains morceaux de code que chacun à leur tour
alternativement.Une méthode plus simple est la synchronisation sur terminaison : on veut
qu'un morceau de code ne s'exécute qu'après qu'un thread donné ait terminé. La méthode
join () permet une telle synchronisation.
Exemple : on veut que jacko attende que jacki ait fini de parler pour prendre la
parole
La classe Executor
La méthode Executors.newFixedThreadPool(int nbThreads) permet de lancer plusieurs
threads en même temps mais en nombre limité.
Moniteur
Une ressource critique est une ressource qui ne doit être accédée que par un seul thread à la
fois.
Exemples : variable globale, périphérique de l'ordinateur.
En Java, il n'est pas possible de contrôler directement l'accès simultané à une variable, il faut
l'encapsuler et contrôler l'exécution de l'accesseur correspondant.
Un moniteur est un verrou qui ne laisse qu'un seul thread à la fois accéder à la ressource.
En Java, tout objet peut jouer le rôle de moniteur. On pose un moniteur sur un bloc de code à
l'aide du mot clé synchronized
Synchronisation sur moniteur
wait() et notify() synchronisent des threads sur un moniteur :
– l'objet o sur lequel les méthodes sont appelées joue le rôle de moniteur
– le thread qui appelle la méthode o.wait() est placé dans le wait-set de o, perd le
moniteur et attend
– il redeviendra actif dans un des cas suivants :
si la méthode o.notify() est appelée et qu'il est choisi parmi les threads du wait-set
(activation d'un des threads du wait-set, sélection plus ou moins aléatoire)
Si la méthode o.notifyAll() est appelée (activation de tous les threads du wait-set)
Si la durée spécifiée pour le wait est écoulée (cas où wait(int timeout) est
utilisée).
synchronized(obj){ synchronized(obj){
try{ try{
... ...
obj.wait(); obj.notify();
... ...
}
} catch(InterruptedException e){}
catch(InterruptedException e){} }
}
• Synchronisation et POO
La synchronisation est indépendante de l'héritage :
- une méthode synchronisée peut être redéfinie dans une sous-classe sans être synchronisée.
- une méthode non synchronisée peut être redéfinie et synchronisée dans une sousclasse.
La synchronisation d'une méthode de classe se fait sur l'instance de Class représentant la
classe.
public class Machin{
public static synchronized m(){
...
}
}
import java.awt.*;
import javax.swing.* ;
public class Premfen
{ public static void main (String args[])
{ JFrame fen = new JFrame() ;
fen.setSize (300, 150) ;
//hauteur 150pixels et largeur 300 pixels
fen.setTitle ("Ma premiere fenetre") ;
//titre de la fenêtre
fen.setVisible (true) ;
//rendre la fenêtre visible
}
}
L’utilisateur peut manipuler cette fenêtre comme n’importe quelle fenêtre graphique, il peut :
la retailler,
la déplacer (ici, elle s’est affichée dans le coin haut gauche de l’écran),
la réduire à une icône.
2.2. Action sur les caractéristiques d’une fenêtre
void setBounds(int x, int y, int largeur, int hauteur) : Modifier la position et la taille
d'un composant
void setVisible(boolean b) : Montrer et cacher un composant
void setEnabled(boolean b) : Activer et désactiver un composant
boolean isEnabled() : Connaître l’état (activé ou non) d’un composant
void setBackground(Color c) : Modifier la couleur de fond d'un composant
void setForeground(Color c) : Modifier la couleur du premier plan d'un composant
void setSize(int largeur, int hauteur) : Modifier la taille d'un composant
3. Composants atomiques
La classe JComponent est une classe abstraite dérivée de la classe Container qui
encapsule les composants atomiques d'une interface graphique. Les principaux
composants atomiques offerts par Java sont: les boutons, les cases à cocher, les boutons radio,
les étiquettes, les champs de texte, les boîtes de liste, les boîtes de liste combinée.
3.1. Création d’un bouton et ajout dans la fenêtre
Pour créer un objet bouton on utilise le constructeur de la classe JButton :
JButton monBouton = new JButtton ("ESSAI");
Pour introduire ce bouton dans la fenêtre on utilise la méthode getContentPane de la classe
JFrame qui permet de fournir une référence à ce contenu, de type Container :
Container c = getContentPane() ;
On ajoute ce bouton au contenu de référence c par la méthode add de la classe Container :
c.add (monBouton) ;
Exemple :
public class FenBouton
import javax.swing.*; { public static void main (String
import java.awt.Container; args[]){
public class MaFenetre extends JFrame fen = new MaFenetre() ;
JFrame{ fen.setVisible (true) ;
public MaFenetre () // constructeur }
{ setTitle ("Ma premiere fenetre") ; }
setSize (300, 150) ;
JButton monBouton = new JButton
("ESSAI");
Container c = getContentPane() ;
c.add(monBouton) ;
}
getContentPane().add(maCase) ;
La méthode setSelected de la classe AbstractButton permet de modifier l’état d’une case à
cocher.
maCase.setSelected(true) ; //coche la case de référence maCase
Par défaut, un bouton radio est construit dans l’état non sélectionné (false). Pour le
rendre séléctionné, on peut :
utiliser la méthode setSelected de la classe AbstractButton:
bRouge.setSelected(true) ;
Ou le 2 constructeur, de la classe JRadioButton :
ème
Initialement, aucune valeur n’est sélectionnée dans la liste. Le cas échéant, on peut forcer la
sélection d’un élément de rang donné par la méthode setSelectedIndex :
maListe.setSelectedIndex(2) ;
Il existe trois sortes de boîtes de liste, caractérisées par un paramètre de type :
BorderLayout,
FlowLayout
CardLayout
GridLayout,
GridBagLayout
BoxLayout
La méthode setLayout de la classe Container permet d'associer un gestionnaire de mise en
forme à un conteneur.
4.1. BorderLayout
Le gestionnaire de mise en forme BorderLayout permet de placer chaque composant
dans une zone géographique. L'emplacement d'un composant est choisi en fournissant en
argument de la méthode add de la classe Container l'une des constantes entières suivantes
(on peut utiliser indifféremment le nom de la constante ou sa valeur) :
- FlowLayout.LEFT
- FlowLayout.CENTER
- FlowLayout.RIGHT
public FlowLayout(int align, int hgap, int vgap)
Exemple:
4.5. BoxLayout
Le gestionnaire BoxLayout permet de disposer des composants suivant une seule ligne ou une
seule colonne.
Le composant Box est un conteneur:
- dont le gestionnaire est BoxLayout
- qui est enfant de Container, donc n’est pas dans Swing.
On crée un "box horizontal" avec la méthode statique createHorizontalBox :
Box ligne = Box.createHorizontalBox () ; // box horizontal
De la même manière, on crée un "box vertical" avec la méthode statique createVerticalBox :
Box colonne = Box.createVerticalBox () ; // box vertical
"South") ;
contenu.add(new JButton("QUATRE"),
"West") ;
contenu.add(new JButton("CINQ"),"East") ;
}
//redéfinition de la méthode getInsets
afin de définir de nouvelles marges
pour la fenêtre
public Insets getInsets() {
Insets normal = super.getInsets() ;
//récupération des marges par défaut de
la fenêtre
return new Insets(normal.top+10,
normal.left+10, normal.bottom+10,
normal.right+10) ;
//création d'un nouvel objet de type
Insets pour modifier les marges de la
fenêtre
} }
5. JTextArea
Un text area affiche plusieurs lignes de texte et autorise l'édition de ce texte par l'utilisateur à
l'aide du clavier et de la souris.
Constructeurs
JTextArea() : Construit une nouvelle instance de JTextArea.
JTextArea(int l, int c) : Construit une nouvelle instance de JTextArea, avec l lignes
et c colonnes.
JTextArea(Sting text) : Construit un JTextArea avec un texte initial.
JTextArea(String text, int l, int c).
JTextArea(Document doc) : Contruit un JTextArea à partir du Document doc.
Méthodes
String getText() : Retourne le texte du JTextArea.
String getText(int d, int l) : Retourne le texte JTextArea, qui a pour longuer l à partir de
d.
String getSelectedText(Sting text) : Retourne le texte sélectionné.
void setTextArea(String text) le texte de JTextArea est remplacé par text
void append(String text) : Ajoute le texte text à la fin de JTextArea.
void insert(String text, int pos) : Insère le texte text à la position pos, dans le
JTextArea.
void replaceRange(String text, int d, int f) : Remplace le texte du JTextArea qui va de d
à f par text .
void replaceSelection(String text) : Remplace le texte selectionné du JTextArea par text
6. JTable
La JTable est un composant affichant/éditant des données sous forme de feuille de calcul. Les
lignes et les colonnes sont identifiées par un nombre entier (en commençant à 0).
En plus des trois méthodes obligées, la fonction getColumClass a été redéfinie, pour obtenir
le type des valeurs pour une colonne.