Upload
vanthuy
View
223
Download
2
Embed Size (px)
Citation preview
ELLEHCOR
AL
UN
IVE
RS
ITÉ
Licence IMAE
U. E. PARI54 / PARP521
« Programmation objet »
Introduction au langage Javaet à la programmation objet
F. Bertrand
Octobre 2007
1 – Typage
Typage
Java possède deux sortes de type de données :
☞ les types primitifs gérés par valeur (selon la terminologie C)
☞ les types référencés réprésentés par les classes et les
tableaux ; ces types sont gérés par référence (pointeur)
Types primitifs
Java possède huit types de données fondamentaux :
boolean (true,false) int (entier signé, 32 bits)
char (Unicode, 16 bits) long (entier signé, 64 bits)
byte (entier signé, 8 bits) float (flottant, 32 bits)
short (entier signé, 16 bits) double (flottant, 64 bits)
Octobre 2007 Introduction au langage Java Page 2
1 – Typage
Les conversions de type
Java permet toutes les conversions entre des
valeurs entières et des valeurs réelles. Seul le
type « boolean » ne peut être converti en un
autre type.
Il existe deux types de conversion :
☞ une conversion « élargissante » (widening
conversion) transformant une valeur d’un
type vers un type plus « large » ; Java
l’effectue automatiquement
☞ une conversion « rétrécissante » (narrowing
conversion) transformant une valeur d’un
type vers un type plus « étroit » ; Java ne
peut l’effectuer que par l’intermédiaire d’un
transtypage (cast).
Ex. : récupération de la partie entière d’un
réel dans un entier.
Octobre 2007 Introduction au langage Java Page 3
1 – Typage
Exemple de conversions
short x = 5;
int y = 10;
y = x; // conversion implicite, OK
x = y; // erreur à la compilation
x = (short) y; // conversion explicite, OK
short s = (short) 0xffff; // valeur représentant 1
char c = ’\uffff’; // valeur d’un caractère Unicode
int i1 = s; // conversion short > int, donne 1
int i2 = c; // conversion char > int, donne 65535
Octobre 2007 Introduction au langage Java Page 4
1 – Typage
Type énuméré
À partir de la version 1.5, Java permet la
définition de types énumérés. Leur utilisation
permet de rendre l’écriture d’un code plus sûr
et plus lisible (cf. exemple TD). Le contrôle de
type est assuré lors de la compilation.
Premier exemple sans enum :
public static final int ROUGE = 0;
public static final int ORANGE = 1;
public static final int VERT = 2;
public static final int BLEU = 10;
unFeuTricolore.change(BLEU); // OK !...
Deuxième exemple avec enum :
public enum CouleurFeu
{ ROUGE, ORANGE, VERT };
// Erreur détectée, valeur non autorisée.
unFeuTricolore.change(CouleurFeu.BLEU);
Octobre 2007 Introduction au langage Java Page 5
1 – Typage
Déclarations de variables locales
Java est un langage fortement typé, cela
signifie qu’une déclaration de variable doit
spécifier un type.
Seules les valeurs de ce type pourront être
stockées (sans conversion) dans la variable.
int i;
String chaine;
Une déclaration de variable peut inclure une
initialisation.
int i = 0;
String chaine = readLine();
int[] donnees = {0, 1, 2};
Concernant l’initialisation, un compilateur Java
interdit l’utilisation :
➠ d’une variable non initialisée
➠ d’expressions dont la valeur ne peut être
déterminée statiquement à la compilation
Octobre 2007 Introduction au langage Java Page 6
1 – Typage
Une déclaration de constante s’effectue en
utilisant le qualificateur « final ».
final int i = 5; // i n’est plus modifiable
Une déclaration de variable peut s’effectuer à
n’importe quel endroit dans un bloc ({ }) de
code.
Mais l’utilisation d’une variable dépend de sa
portée, définie selon l’endroit où intervient la
déclaration.
void uneMethode()
{
int i = 0; // déclaration de i
while (i < 10) // utilisation de i
{
int j = 10; // déclaration de j
} // j n’est plus utilisable
System.out.println(i);
} // i n’est plus utilisable
Octobre 2007 Introduction au langage Java Page 7
1 – Typage
Transtypage des types primitifs
Dans la bibliothèque Java, beaucoup de
méthodes, notamment avec les classes
conteneurs, acceptent uniquement des objets
en paramètres.
☞ Comment leur passer des types primitifs ?
Pour cela il existe dans la bibliothèque
l’équivalent sous forme de classes pour les
types primitifs :
Boolean (pour boolean) Integer (pour int)
Character (pour char) Long (long)
Byte (pour byte) Float (pour float)
Short (pour short) Double (pour double)
Ce sont des classes encapsulantes (wrapper).
Ces classes ne sont plus vraiment nécessaires à
partir de la version 1.5 de Java (autoboxing).
Octobre 2007 Introduction au langage Java Page 8
1 – Typage
Le passage type primitif -→ type référencé
s’effectue avec un constructeur :
Integer i = new Integer(4);
Le passage type référencé -→ type primitif
s’effectue avec une méthode ayant un nom de
la forme typeValue :
int j = i.intValue();
La création d’un type primitif à partir d’une
chaîne de caractères (String) s’effectue avec
une méthode ayant un nom de la forme
parseType, l’inverse avec toString(valeur) :
int j = Integer.parseInt("123");
String s = Integer.toString(j);
La création d’un type référencé (encapsulant) à
partir d’une chaîne de caractères (String)
s’effectue avec la méthode valueOf :
Integer i = Integer.valueOf("123");
Octobre 2007 Introduction au langage Java Page 9
2 – Classes et objets
Classes et objets
Création d’objets
En Java, la déclaration d’une variable (handle)
d’un type référencé ne crée pas d’objet
(instance) :
Point p ; // déclaration d’un pointeur
// de type Point
☞ La création d’instance passe par l’emploi du
motclé new qui déclenche l’appel au
constructeur correspondant
Point p = new Point(2.0,3.5);
Autres mécanismes de création d’instances :
☞ méthode newInstance() appartenant aux
classes java.lang.Class et
java.lang.Constructor
☞ par désérialisation en utilisant la classe
java.io.ObjectInputStream
Octobre 2007 Introduction au langage Java Page 10
2 – Classes et objets
Création d’objets : cas particuliers
Java définit une syntaxe particulière pour créer
des instances de deux classes importantes :
☞ la classe String :
String name = "ULR";
// equivalent à...
String name1 = new String("ULR");
☞ la classe Class :
Class typeInt = int.type;
Class typePoint = Point.class;
Octobre 2007 Introduction au langage Java Page 11
2 – Classes et objets
Référencement d’objets
En Java, les références représentent les
adresses mémoire des objets auxquels elles
sont liées (pointeur en terminologie C/C++).
Donc Java dispose du concept de pointeur mais
pas de celui d’arithmétique sur pointeurs
(déréférencement, incrémentation... )
Noter que l’absence d’objet est représenté par
le motclé null :
String s = null;
Point p = null;
D’autre part, il est possible de tester le type
d’une référence via l’opérateur « instanceof ».
Octobre 2007 Introduction au langage Java Page 12
2 – Classes et objets
Utilisation d’objets
L’utilisation d’objets s’effectue via l’opérateur
« . » pour accèder aux méthodes et aux
champs :
Point p = new Point(4, 5);
double x = p.x;
p.y = p.x * p.x;
double d = p.distanceDeOrigine();
Octobre 2007 Introduction au langage Java Page 13
2 – Classes et objets
Copie d’objets
L’affectation entre deux handles ne copie que la
référence, et pas l’objet référencé (phénomène
d’alias).
Point p = new Point(2.0,3.5);
Point q = p; // p et q référencent
// le même objet
Le passage d’argument pour une méthode suit
le même comportement.
Pour créer une copie d’objet il est nécessaire
d’utiliser la méthode clone() (héritée de
java.lang.Object).
Point p = new Point(2.0,3.5);
Point q = (Point) p.clone();
Pour être clonable une classe doit mettre en
œuvre l’interface Cloneable.
Octobre 2007 Introduction au langage Java Page 14
2 – Classes et objets
Attention ! : par défaut la méthode clone() est
conçue pour réaliser une copie « superficielle »
(shallow copy) qui contient une copie des types
primitifs et des références.
Une copie « profonde » (deep copy) est à la
charge du programmeur en redéfinissant la
méthode clone() (méthode récursive).
Octobre 2007 Introduction au langage Java Page 15
2 – Classes et objets
Le motclé this
Ce motclé est utilisé pour désigner l’instance
sur laquelle s’applique la méthode.
Le compilateur l’ajoute automatiquement à
chaque attribut de l’instance.
La méthode distanceDeOrigine donnée en
exemple précédemment devrait s’écrire :
public double distanceDeOrigine() {
return Math.sqrt(this.x*this.x
+ this.y*this.y);
}
Un autre exemple sera donné lors de la
comparaison d’objets.
Octobre 2007 Introduction au langage Java Page 16
2 – Classes et objets
Comparaison d’objets
Avec les types primitifs, l’opérateur de
comparaison (==) teste si deux valeurs sont
identiques.
Ce même opérateur, lorsqu’il est utilisé avec
des objets, teste simplement si deux références
pointent sur le même objet (identité).
String lettre = "r";
String s = "bonjour";
String t = "bonjou" + lettre;
if (s == t) // chaînes différentes !...
System.out.println("égalité");
Il existe donc deux tests pour les objets :
☞ l’identité réalisé avec l’opérateur ==
☞ l’égalité réalisé avec la méthode equals()
if (s.equals(t)) // OK !...
System.out.println("égalité");
Octobre 2007 Introduction au langage Java Page 17
2 – Classes et objets
Cette méthode equals() est à écrire par le
concepteur d’une classe car, par défaut, cette
méthode est héritée de Object et elle se
contente uniquement de comparer les
références (même comportement que
l’opérateur ==).
public class Point {
private double x,y;
public boolean equals(Object o) {
if (o == this) // si c’est le meme objet
return true;
if (!(o instanceof Point))
return false;
Point p = (Point) o;
return (this.x == p.x
&& this.y == p.y);
}
}
Octobre 2007 Introduction au langage Java Page 18
2 – Classes et objets
Surcharge de méthode
Avec Java il est possible de définir plusieurs
méthodes avec le même nom
☞ surcharge (overloading) de méthode
public class Ecran {
void affiche(char c) { }
void affiche(int i) { }
}
Le compilateur détermine la méthode appelée
en comparant les types des arguments réels
avec ceux des arguments formels des fonctions
du même nom.
La surcharge sert généralement à conserver la
sémantique (le sens) d’une méthode définie
pour un type mais à l’appliquer à d’autres
types.
Octobre 2007 Introduction au langage Java Page 19
2 – Classes et objets
Les constructeurs étant des méthodes
particulières, ils peuvent également être
surchargés.
public class Point {
...
public Point() {
this.x = 0; this.y = 0;
}
public Point(double abs, double ord) {
this.x = abs; this.y = ord;
}
public Point(Point p) {
this.x = p.x;
this.y = p.y;
}
}
Attention : quand une classe ne possède aucun
constructeur, le compilateur en fournit un par
défaut qui ne prend aucun argument. Si un
autre constructeur existe, le compilateur ne
fournit pas de constructeur par défaut.
Octobre 2007 Introduction au langage Java Page 20
2 – Classes et objets
Allocation mémoire et ramassemiettes
Java est conçu pour récupérer
automatiquement la mémoire allouée à des
objets inutilisés.
Point p = new Point(1,2);
// utilisation de l’objet p...
p = new Point(2,3);
L’objet référencé précédemment par p n’est
plus utilisé, la mémoire utilisée par cet objet
sera récupérée par le ramassemiettes (garbage
collector) lors de son activation.
Avantage : Libère le programmeur de la
gestion explicite de la mémoire et évite
certaines erreurs à l’exécution.
Inconvénient : Ralentissement de l’exécution
lors de l’activation du ramassemiettes.
Octobre 2007 Introduction au langage Java Page 21
3 – Les exceptions
Les exceptions
Gestion des erreurs
Problème :
☞ l’auteur d’une bibliothèque peut détecter
les erreurs à l’exécution mais n’a, en
général, aucune idée de ce qu’il faut faire
ensuite...
☞ l’utilisateur peut savoir comment traiter
ces erreurs mais ne peut les détecter...
La notion d’exception est là pour aider au
traitement de ces problèmes.
Idée fondamentale : une méthode qui
rencontre un problème qu’elle ne peut traiter
lance une exception en espérant que son
appelant pourra gérer le problème.
Octobre 2007 Introduction au langage Java Page 22
3 – Les exceptions
La syntaxe
– L’instruction throw permet de « lancer » une
exception qui doit être une instance de la
classe Throwable ou de ses dérivées (Error,
Exception, RuntimeException)
– Les instructions try et catch définissent un
bloc d’exception selon la syntaxe suivante :
try
BlocInstructionsTry
catch (ClasseException exceptionInterceptee)
BlocInstructions
À noter qu’il peut exister plusieurs blocs
catch.
Octobre 2007 Introduction au langage Java Page 23
3 – Les exceptions
Exemple
class MaClasse
{
// ...
void uneMethode ()
{
try
{
// ...
throw new Exception ();
}
catch (Exception uneException)
{
// Que faire en cas d’exception ?
}
}
}
Octobre 2007 Introduction au langage Java Page 24
3 – Les exceptions
Exemple (suite)
Une méthode susceptible de déclencher une
exception doit s’écrire ainsi :
class MaClasse
{
// ...
void uneMethode () throws ClasseException
{
// ...
// En cas d’erreur,
// déclenchement d’une exception
throw new ClasseException ();
// ...
}
}
Octobre 2007 Introduction au langage Java Page 25
3 – Les exceptions
Discrimination des exceptions
class PbEcriture extends Exception { }
class PbLecture extends Exception { }
class Fichier {
char[] lire(int nbCar) throws PbLecture {
...
throw new PbLecture();
}
void ecrire(char[] elts) throws PbEcriture {
...
throw new PbEcriture();
}
//...
}
Octobre 2007 Introduction au langage Java Page 26
3 – Les exceptions
Discrimination des exceptions (suite)
Un utilisateur de la classe Fichier pourra
différencier les deux exceptions en utilisant
deux gestionnaires :
public void uneMethode(Fichier f) {
try
{
char[] t;
t = f.lire(5);
f.ecrire(t);
}
catch (PbLecture e1)
{
...
}
catch (PbEcriture e2)
{
...
}
}
Octobre 2007 Introduction au langage Java Page 27
3 – Les exceptions
La clause finally
De manière formelle, un gestionnaire
d’exception contient :
☞ toujours un bloc try
☞ zéro ou n bloc(s) catch
☞ zéro ou un bloc finally
Ce bloc finally est exécuté à la sortie du bloc
try.
Cette exécution a lieu si cette sortie est due :
☞ à l’arrivée en fin de bloc try
☞ à une sortie provoquée par une instruction
break, continue ou return
☞ à une exception captée un bloc catch
précédant finally
☞ à une exception non captée
Octobre 2007 Introduction au langage Java Page 28
3 – Les exceptions
La clause finally (suite)
▲ Le bloc finally n’est pas exécuté si la
méthode System.exit() est appelée dans le
bloc try.
Un bloc finally est généralement utilisé pour
terminer « proprement » un programme :
fermeture de fichiers, clôture de connexions
réseau, etc...
try { // ouvrir un fichier, appeler des
// methodes susceptibles
// de lever des exceptions
}
catch (CertaineException e1) {
// traitement de l’exception
}
catch (AutreException e2) {
// traitement de l’exception
}
finally {
// fermer le fichier
}
Octobre 2007 Introduction au langage Java Page 29
3 – Les exceptions
Deux types d’exception
À côté des exceptions définies par les
utilsateurs de Java (dérivées de
java.lang.Exception), il existe des
exceptions propres à la machine virtuelle
(dérivées de java.lang.RuntimeException).
Ces exceptions ont les propriétés suivantes :
☞ elles correspondent à des problèmes
détectés à l’exécution par la machine
virtuelle (division par zéro, utilisation d’un
pointeur nul, etc.)
☞ le compilateur ne force par leur capture car
le coût de cette détection serait trop
important par rapport au bénéfice de leur
traitement
Octobre 2007 Introduction au langage Java Page 30
3 – Les exceptions
Les exceptions d’exécution
Les principales exceptions d’exécutions et leur
signification :
Exception Description
IllegalArgumentException Valeur du paramètre
inappropriée
IllegalStateException L’état de l’objet
ne permet pas
l’exécution de la
méthode
NullPointerException Pointeur nul
IndexOutOfBoundException Valeur hors
intervalle
Octobre 2007 Introduction au langage Java Page 31
3 – Les exceptions
Pour résumer...
L’utilisation d’exceptions :
☞ permet une distinction nette entre la
détection des erreurs et leur traitement
☞ permet de conserver un code plus facile à
maintenir
☞ constitue un mécanisme efficace
Octobre 2007 Introduction au langage Java Page 32
4 – Les « packages »
Les « packages »
Un package (paquetage) représente un
ensemble nommé de classes.
La plateforme Java contient des packages dont
les noms débutent par java, javax et org.omg.
Chaque classe possède deux noms :
☞ un nom simple, nom donné dans la
définition de la classe
☞ un nom qualifié constitué du nom du
package auquel elle appartient suivi de son
nom simple.
Exemple :
La classe String appartient au package
java.lang donc son nom qualifié est
java.lang.String.
Octobre 2007 Introduction au langage Java Page 33
4 – Les « packages »
Définition d’un « package »
Pour indiquer que les classes contenues par un
fichier Java appartiennent à un package
particulier, il est nécessaire d’utiliser le motclé
« package » suivi du nom de celuici et ceci au
début du fichier.
package fr.univ_lr.iupgi;
// à partir d’ici, toutes les classes
// définies dans ce fichier
// appartiennent au
// package fr.univ_lr.iupgi
Par défaut, les classes appartiennent à un
package sans nom.
Octobre 2007 Introduction au langage Java Page 34
4 – Les « packages »
Importation de classes
Par défaut, toutes les classes appartenant au
package java.lang peuvent être utilisées avec
leur nom simple.
Toutes les classes en dehors de ce package
doivent être référencées par leur nom qualifié
(ex. java.io.File au lieu de File) .
Pour alléger la syntaxe des noms de classe, il
existe la (ou les) déclaration(s) « import » (qui
doit suivre « package ») .
import java.io.File;
// à partir d’ici, on peut utiliser
// le nom File au lieu de java.io.File
Il est possible d’importer toutes les classes
d’un package (déconseillé !...)
import java.io.*;
À noter que import ne s’applique pas aux
souspaquetages (subpackages).
Octobre 2007 Introduction au langage Java Page 35
4 – Les « packages »
Unicité des noms de packages
Une des fonctions importantes des packages
est de partitionner le domaine de noms Java et
d’éviter d’éventuelles collisions entre les noms
de classes.
Par exemple, seul le nom de package rend
distinctes les classes java.util.List et
java.awt.List.
-→ d’où le besoin d’unicité des noms de
packages.
La proposition de Sun est d’utiliser les noms de
domaines Internet avec leurs éléments inversés
(à l’exception des packages java, javax et
sun).
Exemple pour un projet à l’IUP :
package fr.univ_lr.iupgi.monProjet;
Octobre 2007 Introduction au langage Java Page 36
4 – Les « packages »
Structure de fichiers associée
Il existe une correspondance entre un nom de
package et le nom du répertoire où seront
stockées les classes associées à ce package.
La règle est que à chaque élément du nom du
package correspond un nom de répertoire.
Exemple : Une classe appartenant à
fr.univ_lr.iupgi.monProjet sera stockée
dans le répertoire
fr/univ_lr/iupgi/monProjet.
Par défaut, ce répertoire est recherché à partir
du répertoire courant (chemin relatif).
D’autres points d’entrée à cette recherche
peuvent être donnés :
☞ soit par l’option classpath de
l’interpréteur
☞ soit par la variable d’environnement
CLASSPATH
Octobre 2007 Introduction au langage Java Page 37
5 – Différences entre C et Java
Différences entre C et Java
☞ pas de préprocesseur
– définition de constantes
-→ champs static final
– pas de #include
-→ pas de besoin
– pas de compilation conditionnelle
-→ pas de besoin
☞ pas de variables globales
☞ taille standardisée des types primitifs
☞ pas d’arithmétique sur les pointeurs (*, &)
☞ pas de goto
☞ pas de struct ni de union
☞ pas de enum (jusqu’à la version 1.5)
☞ pas de typedef
Octobre 2007 Introduction au langage Java Page 38
6 – L’héritage
L’héritage
L’héritage offre deux avantages principaux :
☞ la réutilisation par extension de classes
(parentes)
☞ la substitution d’objets (instances) par
conformité à un protocole (= ensemble de
messages auquel un objet peut répondre)
En Java, l’héritage entre deux classes est
marqué par le motclé « extends ».
Octobre 2007 Introduction au langage Java Page 39
6 – L’héritage
Un exemple simple
Soit une bibliothèque multimédia contenant
des CD et des K7 Video :
CD K7Video
BiblioMultimédia
affiche()
emprunt : booleancommentaires : stringmetteurEnScene : string
fixeCommentaires()donneCommentaires()fixeEtatEmprunt()donneEtatEmprunt()
titre : stringdurée : integer
titre : stringartiste : stringnbTitres : stringdurée : integeremprunt : booleancommentaires : stringfixeCommentaires()donneCommentaires()fixeEtatEmprunt()donneEtatEmprunt() affiche()
Bibliothèque multimédia
Octobre 2007 Introduction au langage Java Page 40
6 – L’héritage
Un exemple simple (suite)
Une analyse rapide montre que les classes CD
et K7Video sont très semblables (certaines
parties sont mêmes identiques).
Cette duplication de code entraîne :
☞ une maintenance laborieuse et plus difficile
☞ augmente les risques d’erreurs dues à cette
maintenance
Octobre 2007 Introduction au langage Java Page 41
6 – L’héritage
Utilisation de l’héritage
En utilisant la relation d’héritage on
« factorise » le code ce qui évite sa duplication
et facilite sa mise à jour...
BiblioMultimédia
CDK7Video
ElementMultimédia
artiste : stringnbTitres : integer
titre : stringdurée : integeremprunt : booleancommentaires : stringfixeCommentaires()donneCommentaires()fixeEtatEmprunt()donneEtatEmprunt()affiche()
metteurEnScene : string
Bibliothèque multimédia
Octobre 2007 Introduction au langage Java Page 42
6 – L’héritage
Utilisation de extends
Un extrait du code Java illustrant les classes
précédentes :
public class ElementMultimédia
{
private String titre;
private int durée;
private boolean emprunt;
private String commentaires;
// constructeur et méthodes...
}
public class K7Video extends ElementMultimédia
{
private String metteurEnScene;
// constructeur et méthodes...
}
public class CD extends ElementMultimédia
{
private String artiste;
private String nbTitres;
// constructeur et méthodes...
}
Octobre 2007 Introduction au langage Java Page 43
6 – L’héritage
Héritage et termes associés
☞ Définition d’une superclasse :
ElementMultimédia
☞ Définition de sousclasses K7Video et CD
☞ La superclasse définit les attributs
communs
☞ Les sousclasses héritent des attributs de la
superclasse
☞ Les sousclasses ajoutent leurs propres
attributs
Octobre 2007 Introduction au langage Java Page 44
6 – L’héritage
Héritage et constructeurs (1)
La classe ElementMultimédia possède un
constructeur qui devra être appelé par ceux
des sousclasses :
public class ElementMultimédia
{
private String titre;
private int durée;
private boolean emprunt;
private String commentaires;
public ElementMultimédia(String unTitre,
int uneDurée)
{
this.titre = unTitre;
this.durée = uneDurée;
this.emprunt = false;
this.commentaires = "";
}
//méthodes...
}
Octobre 2007 Introduction au langage Java Page 45
6 – L’héritage
Héritage et constructeurs (2)
public class K7Video extends ElementMultimédia
{
private String metteurEnScene;
public K7Video(String unMetteurEnScene,
String unTitre,
int uneDurée)
{
super(unTitre, uneDurée);
this.metteurEnScene = unMetteurEnScene;
}
// méthodes...
}
public class CD extends ElementMultimédia
{
private String artiste;
private String nbTitres;
public CD(String unArtiste,
int unNbTitres,
String unTitre,
int uneDurée)
{
super(unTitre, uneDurée);
this.artiste = unArtiste;
this.nbTitres = unNbTitres;
}
// méthodes...
}
Octobre 2007 Introduction au langage Java Page 46
6 – L’héritage
Héritage et constructeurs (3)
☞ le constructeur de la sousclasse doit
comporter un appel au constructeur de la
superclasse (super).
☞ S’il n’existe pas, le compilateur ajoute
l’appel au constructeur par défaut de la
superclasse (super(), sans paramètre).
Cet appel est correct seulement si la
superclasse en possède un.
☞ cet appel doit être la première instruction
du constructeur de la sousclasse.
Octobre 2007 Introduction au langage Java Page 47
6 – L’héritage
Soustypage
Dans la classe BilbioMultimédia, avant la
création des classes K7Video et CD, nous
avions les méthodes suivantes :
public class BilbioMultimédia {
public void ajoutCD(CD unCD) { ... }
public void ajoutK7Video(K7Video uneK7Video) {
...
}
}
Avec la création des deux sousclasses, ces
deux méthodes disparaissent au profit d’une
méthode unique :
public void ajoutEltMultimédia(
ElementMultimédia unEltMultimédia
)
Cette méthode est appelée de la manière
suivante :
BilbioMultimédia biblio = new BilbioMultimédia();
K7Video uneK7 = new K7Video(...);
biblio.ajoutEltMultimédia(uneK7);
Octobre 2007 Introduction au langage Java Page 48
6 – L’héritage
Sousclasses et soustypage
☞ Les classes définissent des types.
☞ Les sousclasses définissent des soustypes.
☞ Des objets des sousclasses peuvent être
utilisés à place des objets du supertype :
☞ C’est le principe de substitution
Octobre 2007 Introduction au langage Java Page 49
6 – L’héritage
Sousclasses et affectation
Des instances d’une sousclasse peuvent être
affectés à des variables des superclasses :
ElementMultimédia unElt = new K7Video(...);
ElementMultimédia unElt = new CD(...);
Sousclasses et passage de paramètres
Des instances d’une sousclasse peuvent être
passés comme paramètres des superclasses :
K7Video uneK7 = new K7Video(...);
biblio.ajoutEltMultimédia(uneK7);
Octobre 2007 Introduction au langage Java Page 50
6 – L’héritage
Héritage : classe vs. objet
Il est nécessaire de bien faire la distinction
entre le diagramme de classes décrivant la
hiérarchie et la factorisation du code...
BiblioMultimédia ElementMultimédia
CD K7Video
eltPossedé1 1..*
Diagramme de classes
... de la représentation mémoire des objets
créés au cours de l’exécution
laBase: BiblioMultimédia
uneK7Video:K7Video uneAutreK7Video:K7VideounCD:CD
Diagramme d’objets
Octobre 2007 Introduction au langage Java Page 51
6 – L’héritage
Héritage & transtypage (1)
On peut affecter un objet d’un soustype à une
variable d’un supertype mais on ne peut pas
faire directement l’inverse.
Soit la classe BilbioMultimédia avec une
méthode d’emprunt :
public ElementMultimédia empruntEltMultimédia(
String titre
)
et le fragment de code suivant :
CD unCD = base.empruntEltMultimédia("7e symph.");
☞ Même si la référence à l’objet retourné est
bien une instance de CD, cela provoquera une
erreur !...
Octobre 2007 Introduction au langage Java Page 52
6 – L’héritage
Héritage & transtypage (2)
Ce n’est pas autorisé par le compilateur. Ce
comportement peut s’expliquer avec les règles
suivantes :
– tout élément de la bibliothèque est de type
ElementMultimédia
– mais tout ElementMultimédia n’est pas un
CD
En autorisant l’affectation précédente, le
compilateur permettrait l’utilisation d’une
K7Video à la place d’un CD et donc d’appeler
des méthodes qui n’existent pas pour ce type
d’objet.
☞ Solution : préciser un transtypage...
CD unCD = (CD)
base.empruntEltMultimédia("7e symph.");
Si la référence retournée n’est pas celle d’un CD
alors une exception sera levée à l’exécution...
Octobre 2007 Introduction au langage Java Page 53
6 – L’héritage
Polymorphisme (1)
Soit la hiérarchie suivante
BiblioMultimédiaElementMultimédia
CD K7Video
eltPossedé1 1..*
affiche()
La méthode affiche va permettre de visualiser
les champs communs à une instance de CD ou
de K7Video.
Cependant elle ne peut afficher les champs
spécifiques à chaque instance...
L’héritage est « à sens unique » :
– une sousclasse hérite des champs de la
superclasse
– la superclasse ne sait rien des champs de la
sousclasse
Octobre 2007 Introduction au langage Java Page 54
6 – L’héritage
Polymorphisme (2)
Une solution envisageable...
BiblioMultimédia ElementMultimédia
CD K7Video
eltPossedé1 1..*
affiche() affiche()
Mais :
– pour afficher les champs communs, il ne faut
pas que ceuxci aient été déclarés private
– d’autre part, la méthode affiche n’est plus
connue pour le type ElementMultimédia
Octobre 2007 Introduction au langage Java Page 55
6 – L’héritage
Polymorphisme (3)
Voici la méthode afficheElements de la
classe BilbioMultimédia :
public void afficheElements()
{
ElementMultimédia elt;
for(Iterator iter = elements.iterator();
iter.hasNext();
)
{
elt = (ElementMultimédia) iter.next();
elt.affiche(); // OK ?...
}
}
Pour que cette méthode se compile, il est
nécessaire qu’une version de affiche soit
présente dans ElementMultimédia.
Néanmoins, à l’exécution, on pourra constater
que la méthode affiche appelée sera soit celle
de CD, soit celle de K7Video.
☞ Pourquoi ?...
Octobre 2007 Introduction au langage Java Page 56
6 – L’héritage
Type statique vs. type dynamique
Pour mieux comprendre le comportement
précédent, il convient de définir les notions de
type statique et type dynamique.
Le type déclaré d’une variable est son type
statique.
Le type de l’objet que référence une variable
est son type dynamique.
Exemple :
ElementMultimédia elt = new CD();
Type statique de elt → ElementMultimédia
Type dynamique de elt → CD
En Java, le compilateur contrôle les violations
de type statique.
La machine virtuelle, à l’exécution, contrôle les
violations de type dynamique.
Octobre 2007 Introduction au langage Java Page 57
6 – L’héritage
Redéfinition de méthode
Pour que la méthode afficheElements puisse
se compiler correctement nous devons avoir la
structure suivante :
BiblioMultimédia ElementMultimédia
CD K7Video
eltPossedé
1 1..*
affiche() affiche()
affiche()afficheElement()
La méthode affiche présente dans
ElementMultimédia est redéfinie dans les
deux sousclasses CD et K7Video.
Une méthode qui redéfinit celle héritée de sa
superclasse doit posséder la même signature.
☞ Comment une méthode redéfinie estelle
sélectionnée à l’exécution ?
Octobre 2007 Introduction au langage Java Page 58
6 – L’héritage
Recherche et sélection de méthodes
Premier cas : héritage sans redéfinition
:K7Video
K7Video uneK7;
ElementMultimédia+affiche()
K7Video
{instance-de}
uneK7.affiche();
☞ La hiérarchie d’héritage est parcourue de bas
en haut à la recherche de la méthode...
Octobre 2007 Introduction au langage Java Page 59
6 – L’héritage
Recherche et sélection de méthodes
Deuxième cas : héritage et redéfinition
:K7Video
ElementMultimédia unElt;
ElementMultimédia+affiche()
K7Video+affiche()
{instance-de}
unElt.affiche();
☞ La première version trouvée est utilisée...
Octobre 2007 Introduction au langage Java Page 60
6 – L’héritage
Recherche de méthode à l’exécution
Comment le compilateur détermine la méthode
affiche() à appeler ?...
➠ en fait le compilateur ne le sait pas car il ne
peut pas le savoir !... (il ne vérifie que les types
statiques)
Dans ce cas, le compilateur produit un code
permettant une recherche dynamique de
méthode (liaison dynamique) à l’exécution
exécutant les actions suivantes :
1. accès à l’instance référencée par la variable
2. détermination de la classe de l’instance
3. recherche de la méthode dans cette classe
4. si la méthode est absente, on la recherche
dans la superclasse jusqu’à remonter à la
classe racine...
Octobre 2007 Introduction au langage Java Page 61
6 – L’héritage
Exemple de la classe Object
L’architecture retenue pour la hiérarchie de
classes Java a été d’avoir une classe racine
unique (Object) dont toutes les autres classes
héritent.
Cela permet de s’assurer que les classes
possèdent toutes un ensemble minimal de
méthodes communes.
Exemple :
La méthode toString dont la comportement
par défaut est d’afficher la classe de l’instance
suivie de son adresse mémoire, par ex.
K7Video@3ef5600.
Ce comportement peut être modifié en
redéfinissant cette méthode dans une classe
spécifique.
Octobre 2007 Introduction au langage Java Page 62
6 – L’héritage
Masquage des données et
encapsulation
Une des principales techniques employée en
programmation objet est celle de
l’encapsulation :
« Séparer les choses qui peuvent changer
de celles qui ne doivent pas... »
données
méthodes
Les données (attributs) sont encapsulées par
les seules entités autorisées à les manipuler
➠ les méthodes.
Octobre 2007 Introduction au langage Java Page 63
6 – L’héritage
Masquage des données et
encapsulation (suite)
Pourquoi encapsuler les données ?...
Plusieurs raisons :
1. la plus importante est de masquer les
détails de la mise en œuvre
2. protéger la cohérence des données
(dépendance)
3. faciliter la mise au point des programmes
(le code modifant les données se situe
uniquement dans les méthodes)
4. simplifie la compréhension du
fonctionnement de l’objet (moins de
membres visibles)
Java mixe dans un même fichier l’interface et la
mise en œuvre (inconvénient en partie
compensé par un système de documentation
(pages HTML) du code)
Octobre 2007 Introduction au langage Java Page 64
6 – L’héritage
Contrôle des accès
Au sein d’une même classe, tous les membres
peuvent être utilisés sans restriction d’accès.
Pour les autres classes (externes), Java définit
des règles d’accès pouvant être spécifiées via
des motsclé contrôlant l’accès : public,
protected et private.
Ce contrôle des accès s’exerce
hiérarchiquement sur :
1. les paquetages
2. les classes
3. les membres d’une classe
Ce contrôle s’exerce également sur la relation
d’héritage.
Octobre 2007 Introduction au langage Java Page 65
6 – L’héritage
Contrôle des accès (suite)
Accès aux paquetages
Un paquetage est toujours accessible au code
définit dans le paquetage.
L’accessibilité d’autres paquetages dépend de
la manière dont est mise en œuvre la notion de
paquetage sur le système d’exploitation
sousjacent (droits d’accès sur les répertoires
par ex.).
Accès aux classes
Par défaut, les classes sont accessibles dans le
paquetage où elles sont définies. Cependant
une classe qualifiée « public » est accessible
par n’importe quelle classe.
▲ Une classe ne peut pas être déclarée
private ou protected.
Octobre 2007 Introduction au langage Java Page 66
6 – L’héritage
Contrôle des accès (suite)
Accès aux membres
Par défaut, les classes appartenant au même
paquetage peuvent accèder réciproquement à
tous leurs membres (accès « friendly »)
Cet accès par défaut peut être modifié par les
trois spécificateurs d’accès selon les règles
suivantes :
– un membre public est accessible par toute
classe accédant à la classe du membre
– un membre private n’est accessible que par
les méthodes de la classe où il est défini
– un membre protected est accessible à toute
classe appartenant au même paquetage et
aux sousclasses (quelque soit leur paquetage
d’appartenance)
Octobre 2007 Introduction au langage Java Page 67
6 – L’héritage
Contrôle des accès (suite)
Exemple
package P1;
class Cercle {
protected double r;
...
}
package P2;
class CercleCentre extends Cercle {
...
public boolean estPlusGrand(Cercle c) {
return (this.r > c.r); ☞ Erreur !}
}
L’accès à c.r est illégal car ce champ n’étant
pas hérité la règle d’accès par défaut
s’applique...
☞ La solution consiste à mettre Cercle et
CercleCentre dans le même paquetage...
Octobre 2007 Introduction au langage Java Page 68
6 – L’héritage
Contrôle des accès et héritage
Une sousclasse accède toujours aux membres
protected de sa superclasse... (sauf des
constructeurs)
Les membres private sont hérités mais la
sousclasse n’y a jamais accès.
Octobre 2007 Introduction au langage Java Page 69
6 – L’héritage
Exemples avec différents
qualificateurs d’accès
package A package B
A.C1
A.C2
A.C4
A.C3
B.C5
B.C6
Accès privatepackage A package B
A.C1
A.C2
A.C4
A.C3
B.C5
B.C6
Accès protected
Octobre 2007 Introduction au langage Java Page 70
6 – L’héritage
Exemples avec différents
qualificateurs d’accès
package A package B
A.C1
A.C2A.C4
A.C3
B.C5
B.C6
Accès par défaultpackage A package B
A.C1
A.C2A.C4
A.C3
B.C5
B.C6
Accès public
Octobre 2007 Introduction au langage Java Page 71
6 – L’héritage
Contrôle des accès
Pour résumer...
Visibilité
Accessible à : public protected défaut private
La classe le définissant ✔ ✔ ✔ ✔
Une classe ✔ ✔ ✔
dans le même paquetage
Une sousclasse ✔ ✔
dans un autre paquetage
Une non sousclasse ✔
dans un autre paquetage
Octobre 2007 Introduction au langage Java Page 72
6 – L’héritage
Contrôle des accès
... et quelques règles d’utilisation
☞ Ne jamais mettre public les attributs (sauf
à la rigueur des constantes)
☞ Un fichier Java ne peut contenir qu’une
seule classe qualifiée « public »
☞ Mettre protected les attributs lorsque la
classe présente un intérêt à être
sousclassée mais attention ces attributs ne
devront plus être modifiés...
☞ Dans le doute, créer un membre avec une
protection forte quitte à lever cette
protection dans une version ultérieure de la
classe (l’inverse n’étant pas possible)
☞ Fournir des méthodes accesseurs (get/set)
pour chaque attribut private
Octobre 2007 Introduction au langage Java Page 73
6 – L’héritage
Accès aux champs dans les
superclasses
Supposons trois classes A, B et C définissant
chacune un attribut x et la relation d’héritage :
C -→ B -→ A.
Dans les méthodes de la classe C, on peut se
référer à ces différents attributs de la manière
suivante :
x // attribut x dans C
this.x // attribut x dans C
super.x // attribut x dans B
((B) this).x // attribut x dans B
((A) this).x // attribut x dans A
super.super.x // illegal...
Octobre 2007 Introduction au langage Java Page 74
6 – L’héritage
Différences entre redéfinition et
masquage
Java ne traite pas de manière identique les
méthodes redéfinies et les attributs masqués.
La partie de code suivante illustre cette
différence :
class A {
int i = 1;
int f() { return i; }
static char g() { return ’A’; }
}
class B extends A {
int i = 2;
int f() { return i; }
static char g() { return ’B’; }
}
Octobre 2007 Introduction au langage Java Page 75
6 – L’héritage
Différences entre redéfinition et masquage (suite)
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.i); //fait reference a B.i
System.out.println(b.f()); //fait reference a B.f()
System.out.println(b.g()); //fait reference a B.g()
System.out.println(B.g()); //B.g() (mieux que b.g())
A a = b; // le type dynamique de a est B
System.out.println(a.i); //fait reference a A.i
System.out.println(a.f()); //refere toujours a B.f()
System.out.println(a.g()); //fait reference a A.g()
System.out.println(A.g()); //A.g() (mieux que a.g())
} }
Octobre 2007 Introduction au langage Java Page 76
6 – L’héritage
Conformité à un protocole
Le fait qu’une sousclasse hérite des méthodes
de sa superclasse permet de substituer à toute
instance de la superclasse une instance de la
sousclasse.
Exemple :
class Dessin {
void ajouterCercle(Cercle c) { ... }
}
Dessin d = new Dessin();
CercleGraphique c = new CercleGraphique();
d.ajouterCercle(c);
// OK car CercleGraphique hérite de Cercle
Octobre 2007 Introduction au langage Java Page 77
6 – L’héritage
Méthodes qualifiées final
Quand une méthode est qualifiée final il est
cependant possible de faire l’économie d’une
recherche de la méthode lors de l’exécution. En
effet, la méthode étant déclarée final, elle ne
peut être redéfinie dans une sousclasse donc
le compilateur sait où se situe la seule version
de la méthode...
➠ la recherche à l’exécution n’est plus
nécessaire. L’appel des méthodes :
☞ appartenant à une classe final
☞ qualifiées final, private ou static
ne nécessite pas de recherche à l’exécution.
Octobre 2007 Introduction au langage Java Page 78
6 – L’héritage
Appeler une méthode redéfinie
☞ utilisation du motclé super
class A {
int i = 1;
int f() { return i; }
}
class B extends A {
int i;
int f() {
i = super.i + 1;
return super.f() + i;
}
}
▲ super.i ≡ ((A)this).i
mais super.f() ≠ ((A)this).f()
☞ Penser également au chaînage des méthodes
redéfinies...
Octobre 2007 Introduction au langage Java Page 79
6 – L’héritage
Retour sur la surcharge...
Contrairement à la redéfinition, le choix d’une
méthode surchargée est toujours réalisé à la
compilation .
public class TestSurcharge {
public static String type(Integer i) {
return "Integer";
}
public static String type(Object o) {
return "Ce n’est pas un Integer";
}
public static void main (String[] args) {
Object[] test = new Object[]
{ new Integer(4), new Double(2.3) };
for(int i=0; i < test.length; i++)
System.out.println(type(test[i]));
}
}
L’exécution du main déclenchera, pour les 2
objets du tableau, l’appel à
donneType(Object) car, lors de la
compilation, le type de test[i] est Object.
Octobre 2007 Introduction au langage Java Page 80
6 – L’héritage
Classes abstraites
Pour faciliter l’élaboration d’une hiérarchie de
classes, il peut parfois être intéressant de
définir des classes non directement
instanciables.
Ces classes ont pour but de regrouper
certaines caractéristiques communes et de
diminuer ainsi le niveau de détails dans la
description des sousclasses.
Octobre 2007 Introduction au langage Java Page 81
6 – L’héritage
Héritage d’une classe abstraite
public abstract class Forme {
public abstract double aire();
public abstract double circonference();
protected Color couleur;
}
class Cercle extends Forme {
public static final double PI = 3.141592;
protected double r;
public Cercle(double r,Color c)
{ this.r = r; couleur = c; }
public double rayon() { return r; }
public double aire() { return PI*r*r; }
public double circonference()
{ return 2*PI*r; }
}
class Rectangle extends Forme {
protected double l, h;
public Rectangle(double l, double h, Color c) {
this.l = l; this.h = h; couleur = c;
}
public double largeur() { return l; }
public double hauteur() { return h; }
public double aire() { return l*h; }
public double circonference()
{ return 2*(l + h); }
}
Octobre 2007 Introduction au langage Java Page 82
6 – L’héritage
Héritage d’une classe abstraite (suite)
Spécificités d’une classe abstraite :
☞ tout classe possèdant une méthode
abstraite est de fait abstraite
☞ une classe abstraite ne peut être instanciée
☞ une sousclasse d’une classe abstraite ne
devient concrète (instanciable) que si elle
définit toutes les méthodes abstraites
héritées
☞ des méthodes static, private ou final
ne peuvent être abstraites
☞ similairement, une classe final ne peut
être abstraite
☞ une classe peut être déclarée abstraite
même si elle ne contient aucune méthode
abstraite
Octobre 2007 Introduction au langage Java Page 83
6 – L’héritage
Héritage d’une classe abstraite (suite)
Forme[] formes = new Forme[3];
formes[0] = new Cercle(2.0);
formes[1] = new Rectangle(2.0, 3.0);
formes[2] = new Rectangle(4.0, 1.0);
double surfaceTotale = 0;
for(int i=0; i < formes.length; i++)
surfaceTotale += formes[i].aire();
Deux points à noter ici :
☞ conversion implicite des objets provenant
de sousclasses de Forme en objets Forme
☞ recherche dynamique de la méthode aire
Octobre 2007 Introduction au langage Java Page 84
6 – L’héritage
Les interfaces
Contrainte = Java permet à une classe de
posséder uniquement une superclasse.
La solution proposée par Java consiste à définir
des entités appelées interfaces, concept très
proche de la notion de classe.
Une interface est utilisée pour définir un
protocole de comportement qui peut être mis
en œuvre par n’importe quelle classe.
Les interfaces sont utiles pour :
– capturer des similarités entre des classes
n’ayant pas de lien direct et cela sans créer
de relation artificielle entre les classes ;
– déclarer des méthodes qu’une ou plusieurs
classes doivent implémenter ;
– présenter certaines méthodes d’un objet sans
révéler sa classe ;
– permettre une « sorte » d’héritage multiple.
Octobre 2007 Introduction au langage Java Page 85
6 – L’héritage
Les interfaces (suite)
Un exemple d’interface :
public interface Comparable
{
public void compareTo(Object o);
}
Cette interface doit être implémentée par
toutes les classes utilisées dans des structures
de données maintenues triées.
Octobre 2007 Introduction au langage Java Page 86
6 – L’héritage
Les interfaces (suite)
Une interface se distingue d’une classe par
certaines restrictions :
☞ toutes les méthodes d’une interface sont
implicitement abstraites
☞ toutes les méthodes d’une interface sont
implicitement publiques
☞ les seuls attributs que peut contenir une
interface sont des constantes déclarées
static et final
☞ une interface n’est pas instanciable
Octobre 2007 Introduction au langage Java Page 87
6 – L’héritage
Les interfaces (suite)
public class Point extends Object
implements Comparable {
private int x, y;
public Point(int cx, int cy) {
this.x = cx; this.y = cy;
}
// ...
public int compareTo(Object o) {
Point p = (Point) o;
int distanceThis = (int) Math.sqrt(x*x + y*y);
int distanceAutre = (int) Math.sqrt(p.x*p.x + p.y*p.y);
return (distanceThis distanceAutre);
}
}
Octobre 2007 Introduction au langage Java Page 88
6 – L’héritage
Comparaison
classe abstraite ↔ interface
☞ une interface peut être implémentée par
n’importe quelle classe
☞ mais implémenter une interface possédant
de nombreuses méthodes peut être
fastidieux
☞ une classe ne peut hériter que d’une seule
classe abstraite
☞ une classe abstraite peut contenir des
méthodes déjà implémentées et donc en
faire bénéficier ses sousclasses
☞ modifier une interface conduit à modifier
toutes les classes qui l’implementent
Octobre 2007 Introduction au langage Java Page 89
6 – L’héritage
Utilisation d’interfaces multiples
L’utilisation de plusieurs interfaces est intéressante quand une
classe doit posséder différentes propriétés.
Une classe Point pourrait ainsi se définir :
class Point extends Object
implements Comparable, Clonable, Serializable
{ ... }
Octobre 2007 Introduction au langage Java Page 90
6 – L’héritage
Dériver des interfaces
Une interface peut posséder des
sousinterfaces.
Une sousinterface hérite de toutes les
méthodes abstraites et des constantes.
Une différence importante : une interface peut
dériver de plusieurs interfaces.
Exemple :
interface Modifiable extends Redimensionnable,
Translatable
{ .. }
Une interface peut également « implémenter »
d’autres interfaces en fournissant une mise en
œuvre des méthodes abstraites héritées.
Octobre 2007 Introduction au langage Java Page 91
6 – L’héritage
Utiliser des interfaces pour
« marquer » des classes
Une interface (vide) peut être utilisée pour
indiquer que les instances d’une classe
possèdent une propriété particulière
(Cloneable, Serializable... ).
La classe déclare posséder cette propriété en
implémentant cette interface.
➠ la possession de cette propriété peut alors
être testée par l’opérateur instanceof.
Exemple :
MonObjet o = new MonObjet();
MonObjet copy;
if (o instanceof Cloneable)
copy = o.clone();
else
copy = null;
Cette technique permet de vérifier ici qu’une
instance peut être dupliquée.
Octobre 2007 Introduction au langage Java Page 92
6 – L’héritage
Utiliser des interfaces pour
« masquer » des classes
Une interface peut être utilisée pour
restreindre l’utilisation des méthodes d’un
objet uniquement à celles indiquées dans
l’interface.
➠ utilisation importante dans certains
packages de la bibliothèque Java (notamment
dans la partie XML).
Exemple :
Octobre 2007 Introduction au langage Java Page 93
6 – L’héritage
interface Lire {
public int lire();
}
interface Ecrire {
public void ecrire(int i);
}
class LireEcrire implements Lire, Ecrire {
public int lire() { ... }
public void ecrire(int i) { ... }
}
// méthode utilisant l’interface Lire :
public void traitement(Lire l) {
// sur l, seule la méthode lire
// est utilisable
}
// dans le main :
LireEcrire le = new LireEcrire();
obj.traitement(le);
Octobre 2007 Introduction au langage Java Page 94
6 – L’héritage
Utiliser des interfaces pour
« masquer » des classes (suite)
Autre utilisation masquant le type réel de
l’objet manipulé.
Exemple :
class LireEcrire implements Lire, Ecrire {
public int lire() { ... }
public void ecrire(int i) { ... }
}
class AutreClasse {
public static Lire donneLire() {
return new LireEcrire();
}
}
// dans le main :
Lire l = AutreClasse.donneLire();
obj.traitement(l);
Octobre 2007 Introduction au langage Java Page 95
6 – L’héritage
L’héritage multiple ou comment
contourner les limitations de Java
Exemple :
En Java, pour qu’une classe soit réellement
utilisable pour instancier des objets
graphiques, il est nécessaire qu’elle dérive de
java.awt.Component. Si on reprend notre
classe CercleGraphique elle doit donc hériter
de Component
=⇒ elle ne peut plus hériter de Cercle.
Comment procéder ?...
Octobre 2007 Introduction au langage Java Page 96
6 – L’héritage
Réutiliser une classe parent sans
héritage
Cette réutilisation consiste en une délégation et
nécessite que la sousclasse réimplémente les
méthodes de la classe parent.
Pratiquement, les méthodes réimplémentées ne
font qu’appeler les méthodes de la classe
parent, elles délèguent leurs appels.
Les limites de cette approche :
☞ le code à écrire pour la réutilisation peut
être aussi important que le code réutilisé !...
☞ plus grave, une instance de
CercleGraphique ne peut plus être
réutilisée à la place d’une instance de
Cercle...
☞ enfin, les champs protected ne sont plus
directement utilisables.
Octobre 2007 Introduction au langage Java Page 97
6 – L’héritage
public class CercleGraphique extends Component {
//réutilisation par délégation de Cercle
private Cercle _cercle;
public double circonference()
{ return _cercle.circonference(); }
public double aire()
{ return _cercle.aire();}
//partie spécifique à CercleGraphique
private java.awt.Color couleur;
public CercleGraphique(double r, Point o,
java.awt.Color c) {
this._cercle = new Cercle(r,o);
this.couleur = c;
}
public void paint(java.awt.Graphics g) {
g.setColor(couleur);
g.drawCircle(_cercle); // n’existe pas !...
}
}
Octobre 2007 Introduction au langage Java Page 98
6 – L’héritage
Hériter d’une classe et implémenter
une interface
Revenons au problème du composant
graphique...
Une solution est que la classe
CercleGraphique hérite de Component et
réutilise Cercle par délégation.
Cela donnerait le schéma UML suivant :
Cercle
− origine : Point
− rayon : float
+ circonference(): float+ aire() : float
CercleGraphique
− couleur : Color
- cercle : Cercle
+ paint(Graphics)+ circonference(): float+ aire() : float
Component(from java.awt)
+ paint(Graphics)
Héritage et délégation
Octobre 2007 Introduction au langage Java Page 99
6 – L’héritage
Hériter d’une classe et implémenter
une interfaceIl subsiste cependant la perte de conformité au
protocole de Cercle (pas de substitution
possible entre CercleGraphique et Cercle).
Pour conserver cette conformité au protocole
de Cercle on peut décomposer Cercle en une
interface et une classe d’implémentation.
Schéma UML final :
Component(from java.awt)
+ paint(Graphics)
<<interface>>Cercle
+ circonference(): float+ aire() : float
CercleImpl
− origine : Point
− rayon : float
+ circonference(): float+ aire() : float
CercleGraphique
− couleur : Color
- cercle : CercleImpl
+ paint(Graphics)+ circonference(): float+ aire() : float
Octobre 2007 Introduction au langage Java Page 100
6 – L’héritage
Les limites de la technique
interfacedélégation
Les limites de cette approche :
☞ nécessité de posséder le code source de la
classe à réutiliser par délégation si celleci
ne possède pas d’interface...
☞ impossible à utiliser dans le cas où on doit
réellement hériter de deux classes (classes
java.awt.Component et
java.util.Observable par exemple).
Octobre 2007 Introduction au langage Java Page 101
7 – Les classes internes
Les classes internes
Le concept de classe interne est assez
particulier (introduit à la version 1.1 du JDK). Il
existe quatre intérêts principaux dans
l’utilisation de classes internes :
– une instance d’une classe interne peut
accèder à l’implémentation de l’instance qui
l’a créé (même aux données privées).
– les classes internes peuvent être masquées
aux autres classes du même package (conflit
de noms).
– les classes internes anonymes sont pratiques
pour définir des callbacks à la volée
– les classes internes sont bien appropriées à
la programmation événementielle.
Octobre 2007 Introduction au langage Java Page 102
7 – Les classes internes
Les classes internesIl existe dans Java quatre types de classes
internes (inner classes) :
– classe interne (non statique) : une instance de
cette classe est toujours associée à une
instance de la classe englobante et a accès à
tous ses champs.
– classe membre statique : même
comportement qu’une classe normale mais
ne peut accèder qu’aux membres statiques
de la classe englobante.
– classe locale (à une méthode) : c’est une
classe définie dans une méthode. Elle
possède les mêmes droits d’accès que la
classe membre mais peut, en plus, accèder
aux variables locales qualifiées final de la
méthode englobante.
– classe anonyme : comme indiqué, ce type de
classe ne possède pas de nom et sa définition
intervient seulement lors de l’instanciation.
Octobre 2007 Introduction au langage Java Page 103
7 – Les classes internes
Classe interne
Ce type de classe est toujours associée à une
instance de la classe englobante. Une classe
membre a accès à tous les champs de la classe
englobante.
Exemple :
public class MaFenetre extends Frame {
private boolean ferme = false;
// déclaration de la classe interne
class WinListner extends WindowAdapter {
private boolean attLocal;
public void windowClosing(WindowEvent e) {
ferme = true;
System.exit(0);
}
}
public static void main(String args[]) {
// utilisation de la classe interne
MaFenetre f = new MaFenetre();
f.addWindowListener( f.new WinListner());
f.attLocal = true; // Erreur !... interdit
}
}
Octobre 2007 Introduction au langage Java Page 104
7 – Les classes internes
Classe interne (suite)
Chaque instance de la classe interne possède
une référence invisible sur une instance de la
classe englobante qu’il l’a créée.
:WinListner
référence à laclasseenglobante
attLocal
f: MaFenetre
ferme
En fait le compilateur modifie le constructeur
de la classe interne en ajoutant l’instance
externe en paramètre (init. de la référence) :
WinListner(MaFenetre fenetre) {
refInstanceExterne = fenetre;
}
Octobre 2007 Introduction au langage Java Page 105
7 – Les classes internes
Classe interne statique
Ce type de classe n’est pas associée à une
instance de la classe englobante et n’a accès
qu’aux champs static de cette classe.
Exemple :
public class MaFenetre extends Frame
{
// déclaration de la classe interne
static class WinListner extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
public static void main(String args[])
{
// utilisation de la classe interne
MaFenetre f = new MaFenetre();
f.addWindowListener(new WinListner());
}
}
Octobre 2007 Introduction au langage Java Page 106
7 – Les classes internes
Classe interne localeComme les classes internes, ce type de classe
est toujours associée à une instance de la
classe englobante. Elle accède à tous les
champs de la classe englobante et aux variables
locales « final » de la méthode.
Exemple :
public class MaFenetre extends Frame
{
void addWL( final int valExit) {
// déclaration locale de la classe interne
class WinListner extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(valExit);
}
}
this.addWindowListener(new WinListner());
}
public static void main(String args[]) {
// utilisation de la classe interne
MaFenetre f = new MaFenetre();
f. addWL(0);}
}
Octobre 2007 Introduction au langage Java Page 107
7 – Les classes internes
Classe anonymeC’est une forme particulière de classe interne.
Son choix est plus une affaire de style de
programmation.
Les caractéristiques suivantes orientent vers
l’utilisation d’une classe anonyme :
☞ déclaration très courte de la classe.
☞ une seule instance de la classe est utilisée.
☞ la classe est utilisée immédiatement après
sa définition.
public class MaFenetre extends Frame {
public static void main(String args[]) {
MaFenetre f = new MaFenetre();
f.addWindowListener(new WindowAdapter() {
// déclaration de la classe anonyme
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
}
Octobre 2007 Introduction au langage Java Page 108
8 – Différences entre C++ et Java
Différences entre C++ et Java
☞ C++ offre l’héritage multiple
☞ C++ offre la généricité (template) (existe
dans Java depuis la version 1.5)
☞ C++ permet la surcharge d’opérateurs (une
seule exception « + » en Java)
☞ C++ offre des fonctions de conversion
appelant automatiquement les
constructeurs appropriés
☞ C++ manipule, par défaut, les objets par
valeur
☞ C++ détermine, par défaut, l’appel de
méthode lors de la compilation (liaison
statique)
Octobre 2007 Introduction au langage Java Page 109
9 – Conception d’IHM avec Java
Conception d’IHM avec Java
La conception d’IHM repose principalement sur
un ensemble de composants graphiques appelé
Swing faisant partie d’un ensemble plus
général appelé Java Foundation Classes (Java
2D, Drag and drop, Accessibility).
– les composants Swing sont dit légers
c’estàdire qu’ils n’utilisent pas
d’implémentation spécifique liée à une
plateforme (contrairement à AWT)
– l’aspect de ces composants est adaptable
(notion de « Pluggable Look and Feel ») (ex.
Java, X11/Motif, Win32, Mac).
Octobre 2007 Introduction au langage Java Page 110
9 – Conception d’IHM avec Java
Les composants graphiques
Tous les composants graphiques sont dérivés
de la classe JComponent (pour Swing) ou de la
classe Component (pour AWT).
Certains types de composants (héritant de
java.awt.Container) sont capables d’en
contenir d’autres, ils sont appelés conteneurs.
Le fait d’hériter d’une classe unique,
JComponent (abstraite), permet de factoriser
un certain nombre de propriétés et de
comportements communs à tous les
composants.
À cette URL est présenté l’ensemble de
composants Swing disponibles.
Octobre 2007 Introduction au langage Java Page 111
9 – Conception d’IHM avec Java
Les conteneurs
Avec Swing une IHM est constituée de
composants résidant dans un conteneur
(container). Celui peut être :
– une fenêtre (ex. JFrame)
– une applet (ex. JApplet) qui utilise comme
fenêtre celle du navigateur Internet.
Octobre 2007 Introduction au langage Java Page 112
9 – Conception d’IHM avec Java
Les gestionnaires de présentation
Sans indication supplémentaire, les conteneurs
placent leurs composants selon une
configuration prédéfinie.
Cette configuration est gérée par un
gestionnaire de placement (Layout Manager).
Il existe plusieurs types de gestionnaire de
placement. Leur rôle est de disposer
« correctement » les composants c’estàdire de
déterminer la position et la taille des
composants les uns par rapport aux autres
quelle que soit la taille de la fenêtre dans
laquelle ils s’affichent.
Octobre 2007 Introduction au langage Java Page 113
9 – Conception d’IHM avec Java
Les événements
Chaque fois qu’un utilisateur tape un caractère
au clavier ou clique sur un bouton de la souris,
un événement apparaît.
N’importe quel type d’objet peut être prévenu
(notifié) par l’apparition d’un événement. Pour
cela, l’objet doit implémenter une interface
spécifique et s’enregistrer comme auditeur
(listener) de la source de l’événement.
public class AppSwing
implements ActionListener {
...
JButton bt = new JButton("Un bouton !");
bt.addActionListener(this);
....
public void actionPerformed(ActionEvent e)
{
nbClics++;
label.setText(nbClics);
}
}
Octobre 2007 Introduction au langage Java Page 114
9 – Conception d’IHM avec Java
Les événements (suite)
Les composants Swing peuvent générer beaucoup de types
d’événements. La table suivante montre quelques exemples.
Quelques événements et leurs auditeurs
Action générant l’événement Type d’auditeur
Clic sur un bouton,
Enter dans un champ de saisie
ou choix d’un elt dans un menu ActionListener
Fermeture d’une fenêtre (principale) WindowListener
Clic avec souris sur composant MouseListener
Déplacemt souris sur composant MouseMotionListener
Composant devenant visible ComponentListener
Composant obtenant le focus FocusListener
Changemt ds sélection liste ou table ListSelectionListener
Octobre 2007 Introduction au langage Java Page 115
9 – Conception d’IHM avec Java
Architecture
Bien que l’utilisation de composants AWT soit
moins aisée que ceux de Swing, il est
cependant intéressant de connaître quelques
détails d’architecture.
Les composants AWT (Abstract Window
Toolkit) ont été développés pour être
indépendants du système de fenêtrage utilisé :
le code source est le même quelque soit la
plateforme.
Mais si le code source ne change pas, la mise
en œuvre est dépendante de la plateforme
selon le schéma suivant :
Octobre 2007 Introduction au langage Java Page 116
9 – Conception d’IHM avec Java
Architecture (suite)
À chaque composant AWT est associé un objet
natif de la plateforme désigné sous le terme
de peer.
Pour tout composant AWT créé, il doit être créé
l’objet natif correspondant (rôle d’une classe
Toolkit).
Au moment d’afficher un conteneur, tous les
composants sont crées (Java et peer ). Si un
nouveau composant est ajouté au conteneur
après qu’il ait été rendu visible, il faut
explicitement faire appel à la méthode
validate pour que le composant peer soit
créé. On peut faire appel à la méthode
validate :
– du composant que l’on veut ajouter
– ou de la classe Container qui contient le
composant.
Octobre 2007 Introduction au langage Java Page 117
9 – Conception d’IHM avec Java
Exemple
Voici un exemple d’interface graphique
récapitulant les différents points abordés.
– Code source complet
– Démonstration
Octobre 2007 Introduction au langage Java Page 118
9 – Conception d’IHM avec Java
Exemple (suite)
public class CelsiusConverter implements ActionListener {
JFrame converterFrame;
JPanel converterPanel;
JTextField tempCelsius;
JLabel celsiusLabel, fahrenheitLabel;
JButton convertTemp;
public CelsiusConverter() {
// création et configuration de la fenêtre.
converterFrame =
new JFrame("Convertisseur Celsius to Fahrenheit");
converterFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
converterFrame.setSize(new Dimension(120, 40));
// création et configuration du panneau
converterPanel = new JPanel(new GridLayout(2, 2));
// ajout des composants graphiques (widgets)
addWidgets();
// définition du bouton par défaut
converterFrame.getRootPane().setDefaultButton(convertTemp);
// ajout du panneau à la fenêtre
converterFrame.getContentPane().add(
converterPanel, BorderLayout.CENTER);
// affichage de la fenêtre
converterFrame.pack();
converterFrame.setVisible(true);
}
Octobre 2007 Introduction au langage Java Page 119
9 – Conception d’IHM avec Java
Exemple (suite)
/**
* Création et ajout des composants graphiques.
*/
private void addWidgets() {
//Create widgets.
// affichage de la fenêtre
tempCelsius = new JTextField("0",2);
celsiusLabel = new JLabel("Celsius", SwingConstants.LEFT);
convertTemp = new JButton("Convertir");
fahrenheitLabel = new JLabel("Fahrenheit",SwingConstants.LEFT);
// écoute des événements à partir du bouton "Convertir"
convertTemp.addActionListener(this);
// ajout des composants graphiques au conteneur
converterPanel.add(tempCelsius);
converterPanel.add(celsiusLabel);
converterPanel.add(convertTemp);
converterPanel.add(fahrenheitLabel);
celsiusLabel.setBorder(
BorderFactory.createEmptyBorder(5,5,5,5));
fahrenheitLabel.setBorder(
BorderFactory.createEmptyBorder(5,5,5,5));
}
Octobre 2007 Introduction au langage Java Page 120
9 – Conception d’IHM avec Java
Exemple (suite et fin)
// procédure appelée lors de l’activation du bouton
public void actionPerformed(ActionEvent event) {
// transforme les degrés en double puis
// les convertit en Fahrenheit
int tempFahr;
try {
tempFahr = (int)
((Double.parseDouble(tempCelsius.getText()))
* 1.8 + 32);
fahrenheitLabel.setText(tempFahr + " Fahrenheit");
} catch (NumberFormatException e) {
fahrenheitLabel.setText("Température Celsius invalide");
}
}
/**
* Création et affichage de l’IHM. Pour la sûreté des threads
* cette méthode doit être appelée à partir du thread
* de gestion des événements
*/
private static void createAndShowGUI() {
CelsiusConverter converter = new CelsiusConverter();
}
public static void main(String[] args) {
// Plannifie un travail pour le thread de gestion
// des événements : création et affichage de l’IHM
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Octobre 2007 Introduction au langage Java Page 121
10 – Les threads (tâches)
Les threads (tâches)
L’environnement de la JVM (Java Virtual
Machine) est multitâches.
Cet aspect multitâches est intéressant dans le
sens où cela permet de faire plusieurs choses
en « même temps ».
Exemples :
– lire un port de données et permettre en
même temps à l’utilisateur d’interagir avec
l’interface...
– charger une image et commencer des calculs
sur les morceaux déjà chargés...
Octobre 2007 Introduction au langage Java Page 122
10 – Les threads (tâches)
Un thread représente un processus dit « léger »
(à l’opposé d’un processus de type Unix dit
« lourd ») qui possède un espace mémoire mis
en commun avec d’autres threads.
On retrouve ce concept de thread sur la
plupart des systèmes d’exploitation récents
(Linux, Windows, Solaris...).
Pour comprendre ce mécanisme, plusieurs
aspects sont à étudier :
☞ la création des tâches
☞ les différents états d’une tâche
☞ l’ordonnancement des tâches
☞ les mécanismes de synchronisation entre
tâches
Octobre 2007 Introduction au langage Java Page 123
10 – Les threads (tâches)
Création de threadsIl existe deux moyens de créer une tâche
(attention à ne pas confondre création et
activation) :
☞ soit hériter de la classe Thread puis
redéfinir la méthode run()
public class TestThread extends Thread
{
private static int threadCreees = 0;
private static int threadExec = 0;
public TestThread() { threadCreees++;}
public void run() {
threadExec++;
// traitement ...
}
public static void main(String args[])
{
try {
TestThread t = new TestThread();
}
catch (InterruptedException e) { }
}
}
Octobre 2007 Introduction au langage Java Page 124
10 – Les threads (tâches)
☞ soit implémenter l’interface Runnable et
définir la méthode run()
class ApRun extends Applet
implements Runnable
{
public ApRun() { }
public void run() {
/* traitement ... */ }
}
class EssaiApRun {
public static void main(String args[])
{
try {
Thread t;
t = new Thread(new ApRun());
}
catch (InterruptedException e) { }
}
}
Octobre 2007 Introduction au langage Java Page 125
10 – Les threads (tâches)
Gestion de threads
Les méthodes suivantes permettent de gérer
l’état d’un thread :
☞ start() : démarre l’exécution d’un thread
☞ stop() : stoppe définitivement l’exécution
☞ sleep() : suspend l’exécution durant un
certain délai
☞ suspend() : suspend l’exécution jusqu’à
une reprise via resume()
☞ resume() : reprend une exécution
suspendue via suspend()
☞ yield() : suspend provisoirement
l’exécution en redonnant « la main » à
l’ordonnanceur
Octobre 2007 Introduction au langage Java Page 126
10 – Les threads (tâches)
Les différents états d’un thread (version simplifiée)
Créé
Exécutable Exécuté
Mort
stop()
start()
yield()
stop()
fin de run()
new()
stop()
Thread vivant
Choix de l’ordonnanceur
Le choix de l’ordonnanceur dépend de la priorité de la tâche.
Cette priorité est modifiable via la méthode setPriority().
Octobre 2007 Introduction au langage Java Page 127
10 – Les threads (tâches)
Synchronisation de threads
Toutes les threads de la JVM partagent le
même espace mémoire.
☞ Avantage : accès à tous les objets
☞ Inconvénients :– risque d’indéterminisme à l’exécution
– moins connu, l’absence de synchronisation
peut perturber la communication entre
threads à l’exécutionExemple de problème (variable partagée) :
private static int prochainNumeroSerie = 0;
public static int genererNumeroSerie() {
// Lecture écriture de la variable !
return prochainNumeroSerie++;
}
Problèmes potentiels (sans synchronisation) :– plusieurs threads peuvent obtenir le même
numéro
– un thread peut obtenir [0..n] par appels
successifs puis un autre obtenir 0.
Octobre 2007 Introduction au langage Java Page 128
10 – Les threads (tâches)
Pour prévenir ces problèmes, les concepteurs
ont muni chaque objet (et chaque classe) d’un
verrou (lock) empêchant que deux threads
accèdent simultanément à un même objet.
L’acquisition d’un verrou s’effectue via le
motclé synchronized appliqué :
☞ soit à un bloc d’instructions
☞ soit à une méthode (d’instance ou de classe)
Octobre 2007 Introduction au langage Java Page 129
10 – Les threads (tâches)
L’instruction « synchronized »
Cette instruction définit une section critique
c’estàdire une partie de code accessible
simultanément que par une seule tâche.
Sa syntaxe est la suivante :
synchronized ( expression ) {
instructions
}
où l’évaluation de expression doit renvoyer une
référence à un objet ou un tableau.
Si l’objet n’est pas déjà verrouillé par une autre
tâche, la tâche courante acquiert le verrou
jusqu’à la fin du bloc d’instructions (bloquant
ainsi une autre tâche concurrente pour
l’exécution du bloc).
Octobre 2007 Introduction au langage Java Page 130
10 – Les threads (tâches)
Le qualificateur « synchronized »
Le qualificateur synchronized placé dans la
définition d’une méthode indique que
l’exécution de cette méthode est subordonnée
au verrouillage de l’objet par la tâche courante.
public synchronized void triVecteur() {
...
}
Si la tâche ne peut verrouiller l’objet (objet déjà
verrouillé) alors la tâche est bloquée.
Elle redeviendra exécutable seulement lorsque
la tâche ayant verrouillé l’objet se terminera ou
rendra volontairement le verrou.
Attention !...
☞ Java ne spécifie pas d’ordre dans le
déblocage des tâches.
☞ risques d’interblocage (deadlock)
Octobre 2007 Introduction au langage Java Page 131
10 – Les threads (tâches)
Synchronisation avec « wait() » et
« notify() »
L’utilisation de synchronized garantit
l’exclusion mutuelle mais pas un ordre
d’exécution.
Pour cela il existe plusieurs méthodes :
☞ wait() : place la tâche en attente sur un
objet et libère tous les verrous déjà acquis
par cette tâche (existe en version
temporisée)
☞ notify() : débloque une tâche en attente
sur un objet (préalablement bloquée par
wait())
☞ notifyAll() : débloque toutes les tâches
en attente sur un objet
Pour ces trois méthodes il est impératif que la
tâche qui les exécute ait au préalable verrouillé
l’objet (sinon
IllegalMonitorStateException).
Octobre 2007 Introduction au langage Java Page 132
10 – Les threads (tâches)
Exemple :
class Ressource {
synchronized void attendLaRessource() {
try {
// bonne manière d’utiliser le wait
while (condition non vérifiée) {
wait();
}
// condition vérifiée...
}
catch (InterruptedException e) { }
}
synchronized void laRessourceEstDispo() {
notify(); // ou notifyAll()
}
}
Octobre 2007 Introduction au langage Java Page 133
10 – Les threads (tâches)
Les différents états d’un thread (version étendue)
Choix de
l’ordonnanceur
Exécutable Exécuté
yield()
Thread vivant
Bloqué
resume()
délai sleep() écoulé
objet déverrouillé
Attente
suspend()sleep()
objet verrouilléwait()
notify()notifyAll()
délai wait()
écoulésuspend()
Octobre 2007 Introduction au langage Java Page 134
10 – Les threads (tâches)
Les classes fournies à partir de la
version 1.5
Ces classes sont présentes dans 3 packages :
– java.util.concurrent
– java.util.concurrent.atomic
– java.util.concurrent.locks
Elles ont pour but de fournir des objets
permettant la synchronisation de plus haut
niveau que les primitives intégrées au langage.
Octobre 2007 Introduction au langage Java Page 135
11 – Design patterns
Modèles de conception réutilisables
Les modèles de conception réutilisables
(Design patterns en anglais) sont des solutions
concernant des problèmes récurrents
architecturaux dans la conceptions de logiciels.
Le but de cette présentation n’est pas de faire
une présentation générale (cours de génie
logiciel) mais de voir quelques modèles assez
connus (parmi les 22 existants !)
Ces modèles se divisent en trois grands
domaines :
– création
– structure
– comportement
Certains schémas illustrant cette partie
proviennent du cours de A.Beugnard, ENST
Bretagne.
Octobre 2007 Introduction au langage Java Page 136
11 – Design patterns
Modèles concernant la création
Un des modèles relativement simple
concernant la création est le modèle du
Singleton.
Ce modèle s’utilise lorsque :
– il n’y a qu’une unique instance d’une classe
et qu’elle doit être accessible de manière
connue (ex. DNS, lecteur de chèque)
– une instance unique peut être sousclassée et
que les clients peuvent référencer cette
extension sans avoir à modifier leur code
Modèle de code :
class Singleton {
static Singleton unique = new Singleton();
static Singleton instance() {
return unique;
}
}
Ce modèle est assez proche du modèle
Fabrique.
Octobre 2007 Introduction au langage Java Page 137
11 – Design patterns
Modèles concernant la structure
Ces modèles concernent la manière dont les
objets sont assemblés et ils sont
complémentaires entreeux.
Un exemple simple pour débuter est le modèle
Adaptateur assez utilisé dans la bibliothèque
Java (notamment dans Swing).
Ce modèle s’utilise lorsqu’on souhaite :
– implémenter plusieurs interfaces mais
seulement quelques méthodes doivent être
définies mais il est coûteux de redéfinir les
autres méthodes.
– adapter l’interface d’une classe existante
Octobre 2007 Introduction au langage Java Page 138
11 – Design patterns
Exemple : les classes de l’API Java
javax.swing.event.MouseInputAdapter et
org.xml.sax.helpers.XMLReaderAdapter.
© rd ret
Client Cible
Request
Adapter
Request adapté.methodSpec()
Version composition
Adapté
methodeSpec.
adapté
Octobre 2007 Introduction au langage Java Page 139
11 – Design patterns
Modèles concernant le comportement
Ces modèles concernent la manière dont les
objets interagissent entreeux.
Un exemple simple pour débuter est le modèle
Itérateur implémenté dans l’API via l’interface
java.util.Iterator.
Ce modèle s’utilise lorsqu’on souhaite :
– accèder aux éléments d’un objet sans en
exposer la structure
– offrir une interface uniforme pour parcourir
différents types d’objets
© rd eta
Iterator
firstnextdonecurrent
ConcreteIterator
ConcreteAggregate
Aggregate
createIterator
Client
Octobre 2007 Introduction au langage Java Page 140
11 – Design patterns
Un autre exemple, plus complexe, est le modèle
Observateur implémenté dans l’API via la
classe java.util.Observable et l’interface
java.util.Observer.
Ce modèle s’utilise lorsqu’on souhaite :
– que le changement d’un objet affecte
d’autres objets
– que cet objet ne connaisse pas a priori les
objets à notifier
© rd ta
ConcreteSubject
Subject
AttachDetachNotify
ConcreteObserver
Update
Observer
Update
observers
subject
forall observerso.update
subject.action
Octobre 2007 Introduction au langage Java Page 141
11 – Design patterns
Le diagramme de séquence :
Octobre 2007 Introduction au langage Java Page 142
12 – Le modèle MVC
Le modèle MVC
Ce modèle est destiné à la mise en œuvre
d’applications possédant une interface
graphiquea.
Il comprend toujours 3 parties :
– Le modèle : il représente le cœur de
l’application. Il conserve l’état et les données
de l’application. Lorsque des changements
surviennent dans le modèle, il déclenche la
mise à jour de ses vues.
– Le contrôleur : il représente l’IHM fournie à
l’utilisateur pour manipuler l’application.
– La vue : elle représente l’IHM qui affiche à
l’utilisateur les informations du modèle. Tout
objet qui souhaite afficher des informations
relatives au modèle doit être enregistré
auprès du modèle (modèle Observateur).
aElle peut également présenter un intérêt même avec
une interface en mode console.
Octobre 2007 Introduction au langage Java Page 143
12 – Le modèle MVC
Mise en œuvre originale du modèle MVC
Octobre 2007 Introduction au langage Java Page 144
12 – Le modèle MVC
Application Java utilisant le MVC
Octobre 2007 Introduction au langage Java Page 145
12 – Le modèle MVC
Multiples vues utilisant le même modèle
Octobre 2007 Introduction au langage Java Page 146
12 – Le modèle MVC
MVC avec le contrôleur comme médiateur
Octobre 2007 Introduction au langage Java Page 147
12 – Le modèle MVC
Les avantages du modèle
– Conception claire : les méthodes publiques
du Modèle représentent une API
(bibliothèque) pour manipuler les données et
l’état du modèle. Cela permet une
compréhension aisée du comportement.
– Modularité efficace : cette architecture
permet des changements plus aisés dans les
3 parties (faible couplage).
– Vues multiples : l’application peut afficher
l’état du Modèle de différentes manières qui
peuvent être développées de façon itérative
et extensible. Par exemple, certaines
informations peuvent être affichées sous
forme de tableaux, d’autres graphiquement,
mais elles utilisent les mêmes données, seul
l’affichage diffère.
– Répartition aisée : cette architecture permet,
uniquement en modifiant l’initialisation de
l’application, sa répartition selon un mode
clientserveur.
Octobre 2007 Introduction au langage Java Page 148
12 – Le modèle MVC
Un petit exemple
Dans cet exemple simple on retrouve tous les
concepts décrits précédemment.
L’applet se trouve ici.
L’application se divise en trois fichiers source :
– HeartBeat.java (modèle)
– HeartController.java (contrôleur)
– HeartView.java (vue)
Discussion sur l’accès direct de la vue au
modèle ou utilisation d’un objet représentant
les données à mettre à jour.
Octobre 2007 Introduction au langage Java Page 149
13 – La bibliothèque Java
La bibliothèque Java
Elle comprend :
– plusieurs milliers de classes
(environ 12 500 classes dans le fichier
rt.jar de la version 1.5)
– plusieurs dizaines de milliers de méthodes
– beaucoup de classes facilitant et donc
accélérant le développement d’applications
☞ Un développeur compétent doit savoir
employer les bibliothèques
... Éviter de « réinventer » la roue !
Octobre 2007 Introduction au langage Java Page 150
13 – La bibliothèque Java
La bibliothèque Java (suite)
La bibliothèque dans son ensemble.
Octobre 2007 Introduction au langage Java Page 151
13 – La bibliothèque Java
Documentation associée
Elle comprend :
– le nom de la classe
– une description générale de la classe
– Une liste des constructeurs et des méthodes
– Les valeurs de retour et les paramètres des
constructeurs et des méthodes
– Une description du rôle de chaque
constructeur et méthode
☞ Cela forme l’interface de la classe
Elle ne comprend pas :
– Les attributs privés
– Les méthodes privées
– Les corps (code source) des méthodes
☞ Cela consitue la mise en œuvre de la classe
Octobre 2007 Introduction au langage Java Page 152
13 – La bibliothèque Java
Organisation
Les principaux paquetages (packages) :
Paquetage Description
java.beans Un modèle de composant logiciel
java.io Gestion des entréessorties
java.lang Les classes fondamentales :
String, Math, etc...
java.net Programmation réseau
java.security Contrôle des accès
+ authentification/crytographie
java.text Gestion de l’internationalisation
java.util Classes conteneurs : Set, List
java.sql Accès aux SGBD (JDBC)
java.awt Objets graphiques de base
javax.swing Objets graphiques avancés
Octobre 2007 Introduction au langage Java Page 153
13 – La bibliothèque Java
Conteneurs (java.util)
Architecture
Ces classes se divisent en deux catégories :
☞ celles gérant des groupes d’objets uniques
(Collection)
☞ celles gérant des associations uniques
d’objets (clé,valeur) (Map)
La distinction entre ordonné et non ordonné se
fonde sur la possiblité ou non de comparer les
objets (implémentation de Comparable)
La catégorie Map se subdivise en :
☞ HashMap = couples (clé,valeur) non
ordonnés (≡ HashTable)
☞ TreeMap = couples ordonnés (triés sur la
clé)
Octobre 2007 Introduction au langage Java Page 154
13 – La bibliothèque Java
Architecture (suite)
La catégorie Collection se subdivise en :
☞ Set = groupe d’objets non accessibles
directement
☞ List = groupe d’objets accessibles
directement via un index
La catégorie Set se subdivise en :
☞ HashSet = éléments non ordonnés
☞ TreeSet = éléments ordonnés
La catégorie List se subdivise en :
☞ LinkedList = liste doublement chaînée
☞ ArrayList = liste basée sur un tableau (≡
Vector)
☞ Stack = pile
Octobre 2007 Introduction au langage Java Page 155
13 – La bibliothèque Java
La notion d’itérateur
Un itérateur est un objet permettant de
parcourir une structure de données sans avoir
à connaître sa structure interne.
Cette abstraction permet de :
☞ retourner un élément de la structure de
donnée sur laquelle il est définit
☞ se positionner sur l’élément suivant
☞ déterminer s’il reste encore des éléments à
visiter.
Exemple :
// Soit c un objet de type Collection
for(Iterator i= c.iterator(); i.hasNext();)
traitement(i.next());
Octobre 2007 Introduction au langage Java Page 156
13 – La bibliothèque Java
Types génériques
Une des contraintes des classes conteneur est
qu’elles sont conçues pour stocker des Object.
Donc quand on récupère un objet il est
nécessaire de faire un transtypage :
List mots = new ArrayList();
mots.add("test");
String lePremier = (String) mots.get(0);
Dans la version 1.5 il est introduit la notion de
type générique ce qui évite le transtypage lors
de la récupération :
List mots = new ArrayList<String>();
mots.add("test");
String lePremier = mots.get(0);
Octobre 2007 Introduction au langage Java Page 157
13 – La bibliothèque Java
Types génériques (suite)
L’utilisation de types génériques rend le code
plus clair et plus sûr.
// Supprime les mots de 4 lettres de c.
// Les éléments doivent être du type String
static void purge(Collection c) {
for (Iterator i = c.iterator();
i.hasNext(); )
if (((String) i.next()).length() == 4)
i.remove();
}
Le même exemple utilisant des types
génériques :
// Supprime les mots de 4 lettres de c.
static void purge(Collection<String> c) {
for (Iterator<String> i = c.iterator();
i.hasNext(); )
if (i.next().length() == 4)
i.remove();
}
Octobre 2007 Introduction au langage Java Page 158
13 – La bibliothèque Java
La boucle foreach
À partir de la version 1.5 l’utilisation d’un
itérateur peut être « allégée »...
Ainsi la boucle :
List<String> ls; // déjà initialisée
for(Iterator i= ls.iterator(); i.hasNext();)
traitement(i.next());
peut s’écrire
for(String s : ls)
traitement(s);
L’opérateur « : » à la sémantique « pour
chaque s appartenant à ls »
Attention : ce type de boucle ne peut pas
s’appliquer à tous les cas notamment sur celui
du transparent précédent...
Octobre 2007 Introduction au langage Java Page 159
13 – La bibliothèque Java
Les dictionnaires
Les dictionnaires ou associations (xxxMap)
représentent des collections de paires
d’éléments.
Une paire d’éléments est constituée :
☞ d’un objet clé permettant la recherche de
l’objet valeur auquel il est associé
☞ d’un objet valeur
Exemple d’utilisation : un annuaire
téléphonique.
Octobre 2007 Introduction au langage Java Page 160
13 – La bibliothèque Java
Les dictionnaires (suite)
public class Freq {
public static void main(String[] args) {
Map<String, Integer> m = new HashMap<String, Integer>();
// Initialise une table de fréquence à partir de
// la ligne de commande
for (String a : args) {
Integer freq = m.get(a);
m.put(a, (freq == null) ? 1 : freq + 1);
}
System.out.println(m.size() + " mots distincts:");
System.out.println(m);
}
}
Octobre 2007 Introduction au langage Java Page 161
13 – La bibliothèque Java
Commentaires
☞ Les classes conteneurs permettent de gérer
un nombre quelconque d’objets
(redimensionnement dynamique)
☞ Les classes conteneurs sont déjà vérifiées
et testées
☞ Bien choisir sa classe en fonction de ses
besoins (insertion/accès)
Octobre 2007 Introduction au langage Java Page 162
13 – La bibliothèque Java
Exemples➠ Utilisation d’un HashSet
Set s = new HashSet();
s.add("test");
boolean b = s.contains("test2");
s.remove("test");
➠ Utilisation d’un TreeSet
Set s = new TreeSet();
s.add("b");
s.add("a");
for(Iterator i=s.iterator();
i.hasNext(); )
System.out.println(i.next());
➠ Utilisation de listes
// + efficace en insertion
List l = new LinkedList();
// + efficace en acces
l = new ArrayList();
// ajoute tous les elts de s
l.addAll(ss);
// m̂ chose mais en 1ere position
l.addAll(1,ss);
Object o = l.get(1); // acces indexe
Octobre 2007 Introduction au langage Java Page 163
13 – La bibliothèque Java
Entréessorties (java.io)
Concept général
Avec Java, les entréessorties reposent sur le
concept général de flux (stream).
☞ un flux représente une entité abstraite
possèdant des fonctionnalités en lecture ou
en écriture (séparation)
☞ un flux doit être spécialisé (dérivé) pour
être utilisable avec des entités « réelles » :
fichier, chaîne de caractères, socket, etc...
☞ il unifie les opérations d’écriture ou de
lecture quelque soit le medium et quelque
soit la granularité du mode de
communication (binaire, caractère, mots,
lignes, etc...)
☞ la notion de d’accès séquentiel est
inhérente à celle de flux
Octobre 2007 Introduction au langage Java Page 164
13 – La bibliothèque Java
Les entrées en accès séquentiel
Les flux d’entrée sont représentés par les
classes de base InputStream et Reader. Ces
classes se distinguent par l’unité d’info.
manipulée :
– InputStream ➠ binaire
– Reader ➠ caractère
La méthode fondamentale de ces deux classes
est read.
Ces deux classes sont rarement utilisées. Ce
sont généralement leurs sousclasses
réprésentant différentes sources de données
(binaire/caractère) :
☞ un tableau d’octets : ByteArrayInputStream
☞ une chaîne de caractères : StringReader
☞ un fichier :
FileInputStream/FileReader
☞ un « tube » : PipedInputStream/PipedReader
Octobre 2007 Introduction au langage Java Page 165
13 – La bibliothèque Java
Graphe d’héritage des entrées
InputStream
FileInputStream
PipedInputStream
....
Reader
InputStreamReader
....FileReader
PipedReader
Version binaire
Version caractère
Hiérarchie dans le package java.io
Octobre 2007 Introduction au langage Java Page 166
13 – La bibliothèque Java
Quelques exemples d’entrée en mode binaire...
➠ Lecture d’un fichier
File f = new File(args[0]);
int taille = (int) f.length();
byte[] donnees = new byte[taille];
FileInputStream ficEntree =
new FileInputStream(f);
// lire les octets et les mettre
// dans le tableau donnees
// 0 > a partir du 1er elt de donnees
// taille > lire <taille> octets
ficEntree.read(donnees, 0, taille);
➠ Lecture d’un tableau d’octets
byte[] t = new byte[]{0x4F, 0x3F, 0x55};
ByteArrayInputStream bais =
new ByteArrayInputStream(t);
byte[] donnees = new byte[t.length];
bais.read(donnees);
Octobre 2007 Introduction au langage Java Page 167
13 – La bibliothèque Java
Quelques exemples d’entrée en mode caractère...➠ Lecture de l’entrée standard
BufferedReader entree =
new BufferedReader(
new InputStreamReader(System.in));
System.out.print("Entrez une ligne :");
System.out.println(entree.readLine());
➠ Lecture d’une chaîne de caractères
StringReader sr =
new StringReader("chaine a lire");
int c;
while ((c = sr.read()) != 1)
System.out.print((char) c);
➠ Lecture d’un fichier
BufferedReader ficEntree =
new BufferedReader(
new FileReader("data.txt"));
String s, s2 = new String();
while((s = ficEntree.readLine())!= null)
s2 += s + "\n";
ficEntree.close();
Octobre 2007 Introduction au langage Java Page 168
13 – La bibliothèque Java
Les sorties (en accès séquentiel)
Les flux de sortie sont « symétriques » aux flux
d’entrée et sont représentés par les classes de
base OutputStream et Writer.
– OutputStream ➠ binaire
– Writer ➠ caractère
La méthode fondamentale de ces deux classes
est write.
Ces deux classes sont rarement utilisées. Ce
sont généralement leurs sousclasses
réprésentant différents formats de sortie des
données (binaire/caractère) :
☞ un tableau d’octets : ByteArrayOuputStream
☞ une chaîne de caractères : StringWriter
☞ un fichier :
FileOuputStream/FileWriter
☞ un « tube » : PipedOuputStream/PipedWriter
Octobre 2007 Introduction au langage Java Page 169
13 – La bibliothèque Java
Quelques exemples de sortie...
➠ Écriture d’un fichier binaire
int[] d = new int[]{81, 82, 83};
File f = new File("sortie.txt");
DataOutputStream ficSortie =
new DataOutputStream(
new FileOutputStream(f));
for(int i=0; i < d.length ;i++)
ficSortie.writeInt(d[i]);
ficSortie.close();
➠ Écriture d’un tableau d’objets
Object[] d = new Object[]
{new Integer(2), new String("abc")};
PrintWriter ficSortie =
new PrintWriter(
new FileWriter("sortie.txt"));
for(int i=0; i < d.length; i++)
ficSortie.println(d[i]);
ficSortie.close();
Octobre 2007 Introduction au langage Java Page 170
13 – La bibliothèque Java
Les entréessorties en accès direct
La bibliothèque standard de Java offre une
classe RandomAccessFile permettant
d’accèder à n’importe quelle position dans un
fichier.
Exemple d’utilisation :
File fichier = new File("donnees");
RandomAccessFile f =
new RandomAccessFile(fichier, "rw");
f.seek(100); // place sur le 100e octet
byte[] donnees = new byte[100];
f.read(donnees);
int i = f.readInt();
f.seek(100); // replace sur le 100e octet
f.writeInt(i);
f.write(donnees);
f.close();
Octobre 2007 Introduction au langage Java Page 171
13 – La bibliothèque Java
La persistance en Java
Un objet est dit persistant si son état peut être
maintenu entre deux exécutions d’un
programme.
En Java les objets sont rendus persistants par
sérialisation.
Une classe est sérialisable si elle implémente
l’interface java.lang.Serializable.
Le mécanisme de sérialisation permet de
sauvegarder un graphe cycliques d’objets
(parcours avec marquage).
Exemple :
FileOutputStream fichier = new FileOutputStream("monFichier.ser");
ObjectOutputStream sortie = new ObjectOutputStream(fichier);
sortie.writeObject(monObjet); // sérialisation
sortie.close();
FileInputStream fichier = new FileInputStream("monFichier.ser");
ObjectInputStream entree = new ObjectInputStream(fichier);
MaClasse monObjet = (MaClasse) entree.readObject();
entree.close();
Octobre 2007 Introduction au langage Java Page 172
13 – La bibliothèque Java
La persistance en Java (suite)
Si on souhaite que certains attributs ne soient
pas sérialisés, on peut les marquer
« transient ».
Exemple :
public class PersistentAnimation
implements Serializable,Runnable {
transient private Thread animator;
private int animationSpeed;
public PersistentAnimation(int animationSpeed) {
this.animationSpeed = animationSpeed;
animator = new Thread(this);
animator.start();
}
public void run() {
while(true) {
// réaliser l’animation...
}
}
}
Attention : une classe ne peut être désérialisée
qu’avec la même version de la classe avec
laquelle elle a été sérialisée.
Octobre 2007 Introduction au langage Java Page 173
14 – Les applets
Les applets
Objectif : fournir à une page Web des
fonctionnalités en termes d’interactivité et
d’animation qui ne peuvent pas être exprimées
avec du code HTML.
Comment ?
Les applets sont des programmes Java
s’exécutant dans un environnement sécurisé.
Elles sont chargées à partir d’une page Web :
<applet code="AppletWorld.class"
width="200" height="200" />
Il est possible de les tester avec un outil fournit
en standard avec le JDK :
appletviewer AppletWorld.html
Octobre 2007 Introduction au langage Java Page 174
14 – Les applets
Création d’une applet
Une applet est une classe dérivée des classes
Applet ou JApplet.
Exemple :
import javax.swing.JApplet;
import java.awt.Graphics;
public class HelloWorld extends JApplet {
public void paint(Graphics g) {
g.drawRect(0, 0,
getSize().width 1,
getSize().height 1);
g.drawString("Hello world!", 5, 15);
}
}
Une applet est gérée par un module
d’extension (plugin) du navigateur.
Octobre 2007 Introduction au langage Java Page 175
14 – Les applets
Différences applet vs. application
Swing
– une applet doit être une classe déclarée
public pour qu’elle puisse être accédée
– une applet hérite Applet/JApplet, une
application graphique hérite de Frame ou
JFrame.
– une applet ne possède pas de méthode main
– le constructeur de la classe principale est
remplacé par les méthodes start et init
– les composants graphiques sont ajoutés
directement à la classe dérivée de Applet.
Pour une application ils doivent être ajouté
au panneau de contenu (content pane) de la
classe dérivée de JFrame.
Octobre 2007 Introduction au langage Java Page 176
14 – Les applets
Cycle de vie d’une applet
Applet chargée
init()
Applet exécutée
start()
stop()
destroy()
Les quatres méthodes peuvent être redéfinies.
– La methode init peut être assimilée à une
sorte de constructeur
– La méthode start réalise le travail de
l’applet
– La méthode stop peut être utilisée pour
suspendre un travail en cours (animation)
– La méthode destroy peut être utilisée pour
libérer des ressources
Octobre 2007 Introduction au langage Java Page 177
14 – Les applets
Thread et applet
Exemple d’applet gérant une animation grâce à
un thread.
public void start() {
if (frozen) {
// Ne rien faire, animation stoppée.
} else {
// Démarrer l’animation
if (animatorThread == null) {
animatorThread = new Thread(this);
}
animatorThread.start();
}
}
public void stop() {
animatorThread = null;
}
public void run() {
...
while (Thread.currentThread() == animatorThread)
{
// Affiche l’animation
}
}
Octobre 2007 Introduction au langage Java Page 178
14 – Les applets
Restrictions de sécurité
Une applet ne peut normalement pas :
– charger des bibliothèques ou des méthodes
natives
– lire ou écrire des fichiers sur la machine sur
laquelle elle s’exécute
– ouvrir de connexion réseau sauf avec la
machine dont elle provient
– démarrer d’autres programmes sur la
machine sur laquelle elle s’exécute
– lire des propriétés système
Elle peut en revanche :
– appeler les méthodes public d’applets
situées sur la même page
– avoir aucune des restrictions précédentes si
elle est chargée à partir du système de
fichiers local.
Octobre 2007 Introduction au langage Java Page 179
15 – Les servlets
Les servlets
Les servlets ajoutent des fonctionnalités à un
serveur Web de manière similaire à ce que
permettent les applets pour un navigateur Web.
Ils sont conçus pour fonctionner en mode
clientserveur et permettent de répondre aux
requêtes d’un client (HTTP, FTP...) en effectuant
un traitement.
Exemples : traitement d’un formulaire HTML,
extraction de données d’un SGBD...
Les classes permettant d’utiliser les servlets se
situent dans les paquetages suivants :
– javax.servlet
– javax.servlet.http
Octobre 2007 Introduction au langage Java Page 180
15 – Les servlets
Exemple
import java.io.*;
import javax.servlet.*;
public class SampleServlet implements Servlet {
private ServletConfig config;
public void init (ServletConfig config)
throws ServletException {
this.config = config;
ServletContext sc = config.getServletContext();
sc.log( "Started OK!" );
}
public void destroy() {} // ne rien faire...
public ServletConfig getServletConfig() {
return config;
}
public String getServletInfo() {
return "A Simple Servlet";
}
public void service (ServletRequest req, ServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html" );
PrintWriter out = res.getWriter();
out.println( "<html>" );
out.println( "<head>" );
out.println( "<title>A Sample Servlet</title>" );
out.println( "</head>" );
out.println( "<body>" );
out.println( "<h1>A Sample Servlet</h1>" );
out.println( "</body>" );
out.println( "</html>" );
out.close();
}
}
Octobre 2007 Introduction au langage Java Page 181
15 – Les servlets
Le contexte
Un servlet s’exécute au sein d’un processus
serveur. Pour comprendre son environnement
d’exécution, il a besoin d’informations sur cet
environnement durant son cycle de vie :
– information d’initialisation du servlet (classe
ServletConfig)
– information sur le contexte serveur
– information sur le contexte d’une requête
public void service (ServletRequest req,
ServletResponse res)
throws ServletException, IOException
{
reader = req.getReader();
param1 = req.getParameter("First");
param2 = req.getParameter("Second");
}
Octobre 2007 Introduction au langage Java Page 182
15 – Les servlets
La gestion du protocole HTTP
Les servlets qui utilisent le protocole HTTP
sont assez répandus. Une aide spécifique à leur
gestion est fournie via le paquetage
javax.servlets.http.
HTTP (HyperText Transfer Protocol) définit un
protocole utilisé par les navigateurs et les
serveurs Web pour communiquer. Ce protocole
contient un ensemble de messages appelés
méthodes nécessitant un certain type de
réponses : GET, HEAD, POST, PUT...
Octobre 2007 Introduction au langage Java Page 183
15 – Les servlets
Exemple de requête POST :
POST /servlet/default.jsp HTTP/1.1
Accept: text/plain; text/html
AcceptLanguage: engb
Connection: KeepAlive
Host: localhost
Referer: http://localhost/ch8/SendDetails.htm
UserAgent: Mozilla/4.0
ContentLength: 33
ContentType: application/xwwwformurlencoded
AcceptEncoding: gzip, deflate
LastName=Martin&FirstName=Paul
Exemple de réponse à un message GET :
HTTP/1.1 200 Document follows
Date: Tue, 14 Apr 1997 09:25:19 PST
Server: JWS/1.1
Lastmodified: Mon, 17 Jun 1996 21:53:08 GMT
Contenttype: text/html
Contentlength: 4435
<4435 octets de donnees le corps du document>
Octobre 2007 Introduction au langage Java Page 184
15 – Les servlets
Classes supportant HTTP
Le principe est de dériver la classe abstraite
javax.servlet.http.HttpServlet.
La classe HttpServlet fournit une
implémentation de la méthode service() qui
aiguille les messages HTTP vers les méthodes
suivantes :
Octobre 2007 Introduction au langage Java Page 185
15 – Les servlets
Par exemple une classe redéfinissant la
méthode doGet() devra :
– lire les données associées à la requête
– préciser les entêtes de la réponse
– écrire les données composant la réponse
public void doGet (ServletRequest req,
ServletResponse res)
throws ServletException,
IOException {
res.setContentType("text/html" );
PrintWriter out = res.getWriter();
out.println("<html><head>");
out.println("<title>Bonjour</title>");
out.println("</head>");
out.println("<body>");
String nom=req.getParameter("nom");
out.println("<big>Bonjour"+nom+"</big>");
out.println("</body></html>");
out.close();
}
Exemple d’URL de test :
http://test.org/servlets/Bonjour?nom=fred
Octobre 2007 Introduction au langage Java Page 186
15 – Les servlets
Le conteneur de servlet
Exemple de méthode await implémentée par le
conteneur :
public void await() {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1,
InetAddress.getByName("127.0.0.1"));
}
catch (IOException e) { ...}
// Loop waiting for a request
while (!shutdown) {
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
Octobre 2007 Introduction au langage Java Page 187
15 – Les servlets
Le conteneur de servlet (suite)
// création d’un objet Request et analyse du flux
Request request = new Request(input);
request.parse();
// création d’un objet Response
Response response = new Response(output);
response.setRequest(request);
// vérifie si la requête concerne un servlet ou une ressource
// une requête pour un servlet débute par "/servlet/"
if (request.getUri().startsWith("/servlet/")) {
ServletProcessor1 processor = new ServletProcessor1();
processor.process(request, response);
}
else {
StaticResourceProcessor processor =
new StaticResourceProcessor();
processor.process(request, response);
}
Octobre 2007 Introduction au langage Java Page 188
15 – Les servlets
Le conteneur de servlet (suite)
// fermeture du socket
socket.close();
// vérifie si l’URI précédente est une commande d’arrêt
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}
catch (Exception e) { ... }
}
}
Octobre 2007 Introduction au langage Java Page 189
15 – Les servlets
Autres aspects
– Mécanisme de session
– Utilisation de Cookies
– Utilisation de listes de contrôle d’accès
– Gestion de la concurrence
– Implémentation de référence : Tomcat
Octobre 2007 Introduction au langage Java Page 190
16 – Références
Références
Bibliographie
Quelques références bibliographiques :
☞ Java in a Nutshell
D. Flanagan
Ed. O’Reilly (traduit en français)
☞ Thinking in Java
B. Eckel
Ed. Prentice Hall Computer Books
Version électronique :
http://64.78.49.204/TIJ3rdedition4.0.zip
☞ The Java Language Specification
J. Gosling, B. Joy & G. Steele
Ed. AddisonWesley
Version électronique :
ftp://ftp.javasoft.com/docs/specs/langspec2.0.pdf
☞ Design Patterns
E. Gamma, R. Helm, R. Johnson & J. Vlissides
Ed. International Thomson Publishing
Octobre 2007 Introduction au langage Java Page 191
16 – Références
Liens
Et quelques (parmi des centaines !) sites
intéressants :
☞ Le site de référence (Sun) : java.sun.com
☞ Une revue (en anglais) avec des articles
intéressants : www.javaworld.com
☞ Des exemples sur www.gamelan.com
☞ et un français pour terminer :
www.clubjava.com
Octobre 2007 Introduction au langage Java Page 192
Liste des transparents
2 Typage
2 Types primitifs
3 Les conversions de type
4 Exemple de conversions
5 Type énuméré
6 Déclarations de variables locales
8 Transtypage des types primitifs
10 Classes et objets
10 Création d’objets
11 Création d’objets : cas particuliers
12 Référencement d’objets
13 Utilisation d’objets
14 Copie d’objets
16 Le motclé this
17 Comparaison d’objets
19 Surcharge de méthode
21 Allocation mémoire et ramassemiettes
22 Les exceptions
22 Gestion des erreurs
23 La syntaxe
24 Exemple
25 Exemple (suite)
26 Discrimination des exceptions
27 Discrimination des exceptions (suite)
28 La clause finally
29 La clause finally (suite)
30 Deux types d’exception
31 Les exceptions d’exécution
32 Pour résumer...
33 Les « packages »
34 Définition d’un « package »
35 Importation de classes
36 Unicité des noms de packages
37 Structure de fichiers associée
38 Différences entre C et Java
39 L’héritage
40 Un exemple simple
41 Un exemple simple (suite)
42 Utilisation de l’héritage
43 Utilisation de extends
44 Héritage et termes associés
45 Héritage et constructeurs (1)
46 Héritage et constructeurs (2)
47 Héritage et constructeurs (3)
48 Soustypage
49 Sousclasses et soustypage
50 Sousclasses et affectation
50 Sousclasses et passage de paramètres
51 Héritage : classe vs. objet
52 Héritage & transtypage (1)
53 Héritage & transtypage (2)
54 Polymorphisme (1)
55 Polymorphisme (2)
56 Polymorphisme (3)
57 Type statique vs. type dynamique
58 Redéfinition de méthode
59 Recherche et sélection de méthodes
60 Recherche et sélection de méthodes
61 Recherche de méthode à l’exécution
62 Exemple de la classe Object
63 Masquage des données et encapsulation
64 Masquage des données et encapsulation (suite)
65 Contrôle des accès
66 Contrôle des accès (suite)
67 Contrôle des accès (suite)
68 Contrôle des accès (suite)
69 Contrôle des accès et héritage
70 Exemples avec différents qualificateurs d’accès
71 Exemples avec différents qualificateurs d’accès
72 Contrôle des accès
73 Contrôle des accès
74 Accès aux champs dans les superclasses
75 Différences entre redéfinition et masquage
76 Différences entre redéfinition et masquage (suite)
77 Conformité à un protocole
78 Méthodes qualifiées final
79 Appeler une méthode redéfinie
80 Retour sur la surcharge...
81 Classes abstraites
82 Héritage d’une classe abstraite
83 Héritage d’une classe abstraite (suite)
84 Héritage d’une classe abstraite (suite)
85 Les interfaces
86 Les interfaces (suite)
87 Les interfaces (suite)
88 Les interfaces (suite)
89 Comparaison classe abstraite ↔ interface
90 Utilisation d’interfaces multiples
91 Dériver des interfaces
92 Utiliser des interfaces pour « marquer » des classes
93 Utiliser des interfaces pour « masquer » des classes
95 Utiliser des interfaces pour « masquer » des classes (suite)
96 L’héritage multiple ou comment contourner les limitations de Java
97 Réutiliser une classe parent sans héritage
99 Hériter d’une classe et implémenter une interface
100 Hériter d’une classe et implémenter une interface
101 Les limites de la technique interfacedélégation
102 Les classes internes
103 Les classes internes
104 Classe interne
105 Classe interne (suite)
106 Classe interne statique
107 Classe interne locale
108 Classe anonyme
109 Différences entre C++ et Java
110 Conception d’IHM avec Java
111 Les composants graphiques
112 Les conteneurs
113 Les gestionnaires de présentation
114 Les événements
115 Les événements (suite)
116 Architecture
117 Architecture (suite)
118 Exemple
119 Exemple (suite)
120 Exemple (suite)
121 Exemple (suite et fin)
122 Les threads (tâches)
124 Création de threads
126 Gestion de threads
127 Les différents états d’un thread (version simplifiée)
128 Synchronisation de threads
130 L’instruction « synchronized »
131 Le qualificateur « synchronized »
132 Synchronisation avec « wait() » et « notify() »
134 Les différents états d’un thread (version étendue)
135 Les classes fournies à partir de la version 1.5
136 Design patterns
137 Modèles concernant la création
138 Modèles concernant la structure
140 Modèles concernant le comportement
143 Le modèle MVC
144 Mise en œuvre originale du modèle MVC
145 Application Java utilisant le MVC
146 Multiples vues utilisant le même modèle
147 MVC avec le contrôleur comme médiateur
148 Les avantages du modèle
150 Un petit exemple
151 La bibliothèque Java
152 La bibliothèque Java (suite)
153 Documentation associée
154 Organisation
155 Conteneurs (java.util)
165 Entréessorties (java.io)
173 La persistance en Java
174 La persistance en Java (suite)
175 Les applets
176 Création d’une applet
177 Différences applet vs. application Swing
178 Cycle de vie d’une applet
179 Thread et applet
180 Restrictions de sécurité
181 Les servlets
182 Exemple
183 Le contexte
184 La gestion du protocole HTTP
186 Classes supportant HTTP
188 Le conteneur de servlet
189 Le conteneur de servlet (suite)
190 Le conteneur de servlet (suite)
191 Autres aspects
192 Références
192 Bibliographie
193 Liens
194 Table des matières