Vous êtes sur la page 1sur 199

UNIVERSITÉ

RO CH EL L
A E
L

Licence IMAE

U. E. PARI54 / PARP521

« Programmation objet »

Introduction au langage Java


et à 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


mot-clé 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 mot-clé 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 mot-clé this

Ce mot-clé 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 ramasse-miettes

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 ramasse-miettes (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 ramasse-miettes.

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 plate-forme 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 mot-clé
« package » suivi du nom de celui-ci 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


sous-paquetages (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 mot-clé « 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 :

BiblioMultimédia

CD K7Video
titre : string
emprunt : boolean
artiste : string
commentaires : string
nbTitres : string
metteurEnScene : string
durée : integer
titre : string
emprunt : boolean
durée : integer
commentaires : string
fixeCommentaires()
fixeCommentaires()
donneCommentaires()
donneCommentaires()
fixeEtatEmprunt()
fixeEtatEmprunt()
donneEtatEmprunt()
donneEtatEmprunt() affiche()
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

ElementMultimédia

titre : string
durée : integer
emprunt : boolean
commentaires : string
fixeCommentaires()
donneCommentaires()
fixeEtatEmprunt()
donneEtatEmprunt()
affiche()

K7Video CD

metteurEnScene : string artiste : string


nbTitres : integer

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 sous-classes K7Video et CD
☞ La superclasse définit les attributs
communs
☞ Les sous-classes héritent des attributs de la
superclasse
☞ Les sous-classes 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 sous-classes :
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 sous-classe doit


comporter un appel au constructeur de la
super-classe (super).
☞ S’il n’existe pas, le compilateur ajoute
l’appel au constructeur par défaut de la
super-classe (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 sous-classe.

Octobre 2007 Introduction au langage Java Page 47


6 – L’héritage

Sous-typage

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 sous-classes, 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

Sous-classes et sous-typage

☞ Les classes définissent des types.


☞ Les sous-classes définissent des sous-types.
☞ Des objets des sous-classes 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

Sous-classes et affectation

Des instances d’une sous-classe peuvent être


affectés à des variables des super-classes :
ElementMultimédia unElt = new K7Video(...);
ElementMultimédia unElt = new CD(...);

Sous-classes et passage de paramètres

Des instances d’une sous-classe peuvent être


passés comme paramètres des super-classes :
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 eltPossedé ElementMultimédia


1 1..*

CD K7Video

Diagramme de classes

... de la représentation mémoire des objets


créés au cours de l’exécution
laBase: BiblioMultimédia

uneK7Video:K7Video unCD:CD uneAutreK7Video:K7Video

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 sous-type à 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

eltPossedé ElementMultimédia
BiblioMultimédia
1 1..*
affiche()

CD K7Video

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 sous-classe hérite des champs de la
superclasse
– la superclasse ne sait rien des champs de la
sous-classe

Octobre 2007 Introduction au langage Java Page 54


6 – L’héritage

Polymorphisme (2)

Une solution envisageable...

eltPossedé ElementMultimédia
BiblioMultimédia
1 1..*

CD K7Video

affiche() affiche()

Mais :
– pour afficher les champs communs, il ne faut
pas que ceux-ci 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 eltPossedé ElementMultimédia


1 1..*
afficheElement()
affiche()

CD K7Video

affiche() affiche()

La méthode affiche présente dans


ElementMultimédia est redéfinie dans les
deux sous-classes CD et K7Video.

Une méthode qui redéfinit celle héritée de sa


super-classe doit posséder la même signature.

☞ Comment une méthode redéfinie est-elle


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

uneK7.affiche(); ElementMultimédia
+affiche()

K7Video uneK7;
K7Video

{instance-de}

:K7Video

☞ 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

unElt.affiche(); ElementMultimédia
+affiche()

ElementMultimédia unElt; K7Video


+affiche()

{instance-de}

:K7Video

☞ 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 super-classe 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... »

méthodes

données

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 mots-clé 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
sous-jacent (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 sous-classes (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 sous-classe accède toujours aux membres


protected de sa super-classe... (sauf des
constructeurs)

Les membres private sont hérités mais la


sous-classe 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.C3 B.C6
A.C1

B.C5
A.C2
A.C4

Accès private
package A package B

A.C3 B.C6
A.C1
B.C5
A.C2
A.C4

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.C3 B.C6
A.C1

B.C5
A.C2
A.C4

Accès par défault


package A package B

A.C3
A.C1 B.C6
B.C5
A.C2
A.C4

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 sous-classe ✔ ✔ - -
dans un autre paquetage
Une non sous-classe ✔ - - -
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
sous-classé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


super-classes

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 sous-classe hérite des méthodes


de sa super-classe permet de substituer à toute
instance de la super-classe une instance de la
sous-classe.

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 sous-classe 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 mot-clé 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 sous-classes.

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 sous-classe 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 sous-classes 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 super-classe.

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 sous-classes
☞ 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


sous-interfaces.

Une sous-interface 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 sous-classe 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 :
Component
(from java.awt)

+ paint(Graphics)

CercleGraphique
Cercle

− couleur : Color − origine : Point


- cercle : Cercle − rayon : float
+ paint(Graphics) + circonference(): float
+ circonference(): float + aire() : float
+ aire() : float

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 interface
Il 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 <<interface>>
(from java.awt) Cercle

+ circonference(): float
+ paint(Graphics) + aire() : float

CercleGraphique
CercleImpl

− couleur : Color − origine : Point


- cercle : CercleImpl − rayon : float
+ paint(Graphics) + circonference(): float
+ circonference(): float + aire() : float
+ aire() : float

Octobre 2007 Introduction au langage Java Page 100


6 – L’héritage

Les limites de la technique


interface-dé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 celle-ci
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 internes


Il 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

attLocal
référence à la
classe
englobante 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 locale


Comme 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 anonyme
C’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
plate-forme (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
plate-forme.

Mais si le code source ne change pas, la mise


en œuvre est dépendante de la plate-forme
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 plate-forme 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 multi-tâches.

Cet aspect multi-tâ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 threads
Il 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)


new()

stop()
Créé Mort
stop()

stop()
start() fin de run()

yield()

Exécutable Exécuté

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écution
Exemple 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


mot-clé 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)

yield()

Exécutable Exécuté
Choix de
l’ordonnanceur
resume()
notify() suspend()
délai sleep() écoulé
notifyAll() sleep() wait()
objet déverrouillé
délai wait() objet verrouillé
suspend() écoulé

Bloqué Attente

Thread vivant

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 sous-classé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 entre-eux.

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.

Version composition

Client Cible Adapté

Request methodeSpec.

adapté
Adapter

Request adapté.methodSpec()

© rd ret

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 entre-eux.

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

Iterator
Aggregate Client
first
createIterator next
done
current

ConcreteAggregate

ConcreteIterator

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

observers
Subject Observer
Attach Update
Detach
Notify forall observers
o.update

subject
ConcreteSubject ConcreteObserver

Update

subject.action

© rd ta
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).

a Elle
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
client-serveur.

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ées-sorties
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 for-each

À 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ées-sorties (java.io)
Concept général

Avec Java, les entrées-sorties 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 sous-classes
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
Version binaire

PipedInputStream

....

Reader

InputStreamReader

Version caractère

....
FileReader

PipedReader

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 sous-classes
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ées-sorties 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 (plug-in) 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

init(
)

start()
Applet Applet
chargée stop() exécutée

y ()
s tro
d e

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


client-serveur 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
Accept-Language: en-gb
Connection: Keep-Alive
Host: localhost
Referer: http://localhost/ch8/SendDetails.htm
User-Agent: Mozilla/4.0
Content-Length: 33
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: 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
Last-modified: Mon, 17 Jun 1996 21:53:08 GMT
Content-type: text/html
Content-length: 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 en-tê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/TIJ-3rd-edition4.0.zip

☞ The Java Language Specification


J. Gosling, B. Joy & G. Steele
Ed. Addison-Wesley
Version électronique :
ftp://ftp.javasoft.com/docs/specs/langspec-2.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.club-java.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 mot-clé this

17 Comparaison d’objets

19 Surcharge de méthode

21 Allocation mémoire et ramasse-miettes

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 Sous-typage

49 Sous-classes et sous-typage

50 Sous-classes et affectation

50 Sous-classes 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 super-classes

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 interface-dé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ées-sorties (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