Sie sind auf Seite 1von 140

J1 Préambule 1

' $

Stage Java
Emmanuel Chailloux
mél : Emmanuel.Chailloux@lip6.fr
www : http://cadillac.lip6.fr/~emmanuel
Slide 1
du 29 juin au 3 juillet 1998

UFR d’Informatique
Université Pierre et Marie Curie
www : http://www.ufr-info-p6.jussieu.fr

& %

' $

Organisation

• cours le matin : 9h30-12h30


Slide 2 couloir 45-46 porte 305
• TP l’AM : 13h30-16h30
couloir 45-46 salle GLA
15 machines, comptes individuels
environnement Windows NT et Unix

& %
J1 Préambule 2

' $

Prérequis

Slide 3 • connaissance d’un langage impératif (C ou Pascal)


• utilisation d’un OS : Unix/X ou Windows NT
• manipulation d’un navigateur

& %

' $

Objectifs

Description: via le langage Java de la


• programmation objet
Slide 4 • programmation graphique et par événements
• programmation concurrente
• programmation distribuée
• implantation des langages
pour l’enseignement, le développement d’applications et la recherche

& %
J1 Préambule 3

' $

Plan du stage

1. noyau du langage Java


Slide 5 2. types, interfaces et paquetages
3. processus légers, graphisme et applets
4. persistance et distribution
5. implantation et extensions

& %
J1 Préambule 4

' $

Bibliographie

• “Java in a Nutshell”, D. Flanagan,


O’Reilly, 1997
Très bon pour le programmeur C ou C++,
JDK 1.1
• “Java : de l’esprit à la méthode -
distribution d’applications sur Internet”,
M. Bonjour, G. Falquet, J. Guyot et A. Le
Slide 6
Grand - International Thomson Publisher,
1996.
Très clair, bonne pédagogie, JDK 1.0
• “Just JAVA and Beyond”, P. van der
Linden, SUN Press 1998.
Très bonne présentation avancée, JDK 1.1
• “Data Structures and Algorithms in Java”,
M. T. Goodrich, R. Tamassia, Wiley 1998.
Algorithmique en Java + un “Primer” en
annexe, JDK 1.1
& %
J1 Présentation générale 5

' $

Remerciements

• Christian Queinnec : transparents


• Vassiliki Spathis : polycopié
Slide 7
• Jean François Perrot, Philippe Codognet : exemples
• Michelle Joab : organisation
• François Barthélemy (CNAM) et Pascal Molli (LORIA) : cours
en ligne
• l’équipe du DESS GLA : préparation des machines

& %

' $

Plan du 1er jour

• présentation générale de Java


Slide 8
• noyau impératif : expressions - instructions
• noyau objet : classes, instances, héritage, liaison retardée
• gestion mémoire
• contrôle d’exécution

& %
J1 Présentation générale 6

' $

JAVA

• Simple
• Orienté Objet
• Typé
• Compilé/Interprété
• Indépendant de l’architecture machine
Slide 9
• Distribué
• Processus Légers (Threads)
• Robuste
• Petit
• Rapide
• Sûr
• à chargement dynamique

& %
J1 Présentation générale 7

' $

Historique

⇒ 1994, Java SUN


James Gosling (emacs, NeWS)
Slide 10
“Un coktail innovant de techniques éculées!”

“L’originalité de Java est de n’en avoir aucune!”

Influences: C, C++, Lisp, ML, Modula3

& %
J1 Présentation générale 8

' $

Mise en Oeuvre

toto.class
Java BC

INTERNET

stdin BC stdout
Slide 11 C
stderr

event GUI order

BC

appletviewer
HTTP-browser

& %
J1 Noyau Impératif 9

' $

JDK

BC BC
la JVM .o .o
C C

µ BC
µ

C .o
la biblio C .o
native
µ

Slide 12 le Java BC Java BC


compilo
Java Java BC BC
Java

BC

BC

bibliothèques Java Java BC BC


de classes JDK
BC

BC

& %
J1 Noyau Impératif 10

' $

Noyau impératif

à la C
Expressions:
expression := variable
| operateur expression
Slide 13
| expression operateur
| expression operateur expression
| ( expression )
| (type de base) expression
| expression ? expression
: expression
| variable = expression
| variable operateur= expression

& %
J1 Noyau Impératif 11

' $

Types de base:

type tnb bit défaut


boolean false,true 1 false
char Unicode 16 \u0000
byte tous signés 8 0
Slide 14 short ““ 16 0
int ““ 32 0
long ““ 64 0
float IEEE 754 32 0.0 (F)
double ““ 64 0.0 (D)
Remarque: Ces valeurs ne sont pas des objets, il existe cependant
des classes associées qui sont Boolean, Char, Byte, . . . , Double.
& %

' $

Exemples d’expressions

z=18 x = x + 1
x += 1 x++
(byte)i (z % 3) << 2
(x<2) ? 2.7 : 3.14
Slide 15
(x != null) || (y >= 3.14)
(b = !b) & (( i ^= ~i) == 0)
s + "Hello" : concaténation
"an " + 1998 : avec conversion

Stricte séparation entre booléens et entiers


Non conversion pointeur - booléen
& %
J1 Noyau Impératif 12

' $

Instructions

instruction ::= { instruction; ... }


| if ( bool) {instructions};
| if ( bool ) {instructions}
else {instructions}
| L: while (bool) {instructions}
| L: do {instructions} while (bool);
| L: for (expressions;
Slide 16
bool;
expressions)
{instructions}
| L:switch (expressions)
{case constant : intruction;
... default : instruction;}
continue label;
continue;
break label;
break;

& %
J1 Noyau Impératif 13

' $

Exemple d’instructions

i=1;
for (i=1; i < j ; i++) { while (i < j) {
if (i*i > j ) break; if (i*i > j ) break;
Slide 17 i++;
} }
switch (x % 5) {
case 0: { ... ; break;}
case 1: case 3: { ...; break;}
default: {... }
}

& %

' $

Types des variables

1. les types de base


Slide 18
2. les noms de classe
3. les noms d’interface
4. les types tableaux

& %
J1 Noyau Impératif 14

' $

Variables locales

à l’intérieur d’un bloc


{ // debut du bloc 1
...
int i;
int j = 18;
...
int h = 22;
Slide 19 { // debut du bloc 2

int w = J + 4;
// float i = 3.14;

} // fin du bloc 2

{ double w = 3.14;
...}
} // fin du bloc 1
for (int i = 0; i < 10; i++) { ...}
& %
J1 Noyau Impératif 15

' $

Premier programme

/∗ premier programme
calcul de fibonacci
∗/

class Fibo {

public static void main (String [] args){


int i;
Slide 20
int j = 1;
int n = 8;
int r = 0;

for (int v = 1; v < n; v++) {


r = r + j;
i = j;
j = r;
} // que vaut r en sortie?
}
}
& %
J1 Noyau Impératif 16

' $

Tableaux

type [] : un type suivi du symbole []


Déclaration:
instruction ::= type [] variable;
Slide 21 | type [] variable = {value ...} ;
Création:
expression ::= new type [taille];
Allocation dynamique de l’espace
Vérification des indices - indice à partir de 0
Pas de dimension multiple : utilisation de tableaux de tableaux.

& %
J1 Noyau Impératif 17

' $

Tableau : un exemple

{ int [] ft;
int i;
int n = 8;

Slide 22 ft = new int [n+1];


ft[0]=1;
ft[1]=1;
for (i = 2; i < ft.length; i++) {
ft[i] = ft[i-1] + ft[i-2];
}
// que contient ft a‘la sortie
}

& %
J1 Noyau Impératif 18

' $

Tableaux de Tableaux

...
int [][] m,t;
int p = 4;
int q = 5;

m = new int [p][q];


t = new int [q][p];
// remplissage
Slide 23 for (i=0; i<p; i++) {
for (j=0; j< q; j++) {
m[i][j] = i*j;
}
}
// transposee
for (i=0; i<p; i++) {
for (j=0; j< q; j++) {
t[j][i]=m[i][j];
}
}

& %
...
J1 Noyau Objet 19

' $

Tableaux (suite)

dimension possiblement hétérogène

Slide 24 int [] [] a;
a = new int [5] [];
a[0] = new int[1];
a[1] = new int [ a[0].length + 1];
a[0][0] = 33;
a[2].length; // BOOM !!!!
Les tableaux sont des objets avec une classe associée.

& %

' $

Slide 25 Pause Java

& %
J1 Noyau Objet 20

' $

Généralités

Encapsulation:
Classes et Instances:
Slide 26
Surcharge:
Héritage:
Redéfinition et Liaison Retardée:
Polymorphisme et Sous-Typage:

& %

' $

Terminologie Objet

• classe = description des données et des procédures qui les


manipulent ⇒ définit des comportements
Slide 27
• objet = instance d’une classe (possède tous les comportements de
la classe)
• méthode = action (procédure, fonction) que ln peut effectuer sur
un objet
• envoi de message = demande d’exécution d’une méthode

& %
J1 Noyau Objet 21

' $

Déclaration de Classes

[ modifieur ]* class la_classe [ extends la_superclasse ] {


// champs
[modifieur]* type champ [ = expression] ;
// constructeurs
[modifieur]* la_classe ( [type variable]*) {
Slide 28
instructions // sans return
}
// methodes
[modifieur]* TypeRetour methode ([Type variable)*)
[throws [exception]+] {
instructions // avec return
}

& %
}

' $

Statique ou Dynamique

modifieur static variable ou méthode de classe!!!


• variables de classe 6= variables d’instance
Slide 29
• méthodes de classe 6= méthodes d’instance
Par défaut dynamique (non statique) ⇒ variables ou méthodes
d’instances!!!

Possibilité de mélanger les 2.

& %
J1 Noyau Objet 22

' $

Java statique : programmation modulaire

Les variables et méthodes de classes :


• sont déclarées avec static
• existent dès le chargement de la classe (sans instance)
Slide 30
• existent en un unique exemplaire
• accessible par la notation “point”
Une classe qui ne contient que des champs statiques peut être
considérée comme un module classique (Unit Pascal) :
où les méthodes sont les fonctions du modules et les variables les
variables globales.

& %
J1 Noyau Objet 23

' $

Exemple en Java statique

class ES {

static void writeln( String s) {


System.out.println(s);
}

}
Slide 31

class TestES {

public static void main (String [] args) {


ES.writeln("Salut tout le monde");
}
}
Enfin, un point d’entrée d’un programme est
une classe qui contient une méthode public
static void main ... : java TestES

& %
J1 Noyau Objet 24

' $

Java dynamique : programmation objet

Les variables et méthodes de d’instances :


• ne sont pas déclarées avec static
Slide 32
• sont allouées à la création d’une instance (new)
• existent pour chaque instance
• accessible aussi par la notation “point”
o.m(a) : envoi du message m avec le paramètre a sur l’objet o dne
classe c.

& %

' $

Constructeur

Chaque classe possède au moins un constructeur pour initialiser un


Slide 33 nouvel objet de ce type.
• méthode de même nom que la classe
• sans type de retour
• appelé dès l’allocation (new)

& %
J1 Noyau Objet 25

' $

Surcharge

La surcharge (overloading) permet de définir au sein de la même


Slide 34
classe des méthodes de même nom qui diffèrent par le type des
paramètres ou par le type du résultat.

y compris pour les constructeurs.

& %

' $

Classe Point

class Point {
// variables d’instance
int x, y;
// constructeurs
Slide 35 Point(int a, int b){x=a;y=b;}
Point(){x=0;y=0;}
// methodes d’instance
void moveto (int a, int b){x=a;y=b;}
void rmoveto (int dx, int dy){x+=dx;y+=dy;}
void affiche(){ES.writeln("(" + x + "," + y + ")");}
double distance(){return Math.sqrt(x∗x+y∗y);}
}
& %
J1 Noyau Objet 26

' $

Programme test de Point

class Test {

public static void main(String args[])


{
Point p0 = new Point();
Point p1 = new Point(3,4);
Slide 36
p0.affiche(); p1.affiche();
p0.rmoveto(7,12);
p1.rmoveto(5,6);
p0.affiche(); p1.affiche();
if (p0.distance() == p1.distance())
ES.writeln("c’est le hasard");
else
ES.writeln("on pouvait parier");
}
}

& %
J1 Noyau Objet 27

' $

Héritage

Avantage principal de la programmation objet :

Extension du comportement d’une classe existante tout en continuant


Slide 37
à utiliser les variables et les méthodes décrites par la classe originale.

Toute définition de classe étend une classe existante.

Si l’on ne précise rien on étend la classe Object


⇒ on hérite toujours de quelqu’un!!!

& %

' $

Exemple d’Héritage

class PointColore extends Point {

String c;
Slide 38
PointColore(){c="blanc";}
PointColore(int a, int b, String x){moveto(a,b);c=x;}

void affiche bis(){


ES.writeln("(" + x + "," + y + ") de couleur " + c);
}
} // fin de la classe PoinColore

& %
J1 Noyau Objet 28

' $

Redéfinition

La redéfinition (overriding) permet de définir


une méthode de même nom et de même
signature (type) qu’une méthode héritée.
Ce sera donc cette dernière qui sera appelée
lors de l’envoi d’un message de ce nom avec les
paramètres correspondants.

Slide 39 class PointColore extends Point {


String c;
PointColore(){c="blanc";}
PointColore(int a, int b, String x) {
moveto(a,b);c=x;
}
void affiche(){ // redefinition
ES.writeln("(" + x + "," + y +
") de couleur " + c);
}
} // fin de la classe PointColore

& %
J1 Noyau Objet 29

' $

this et super

this correspond à l’instance qui exécute la méthode. Tout envoi de


message sans récepteur est un envoi à this (paramètre implicite).
Utile pour distinguer les variables locales ou les paramètres des
variables d’instance. :
Slide 40 void Point(int x, int yy){ this.x=x; y = yy;}

En cas de redéfinition d’une méthode, il peut être utile d’appeler la


méthode ancêtre : super
void affiche() {
super.affiche();
ES.write("de couleur "+c);

& %
}

' $

Retour sur les constructeurs

Un constructeur dne classe descendante effectue un appel explicite au


constructeur ancêtre sans paramètre (super()).
Slide 41
Pour appeler un constructeur ancêtre avec paramètres, il faut
expliciter l’appel : super(3,2.1)

Comme toute classe descend au moins d’Object, un constructeur est


toujours appelé au new.

& %
J1 Noyau Objet 30

' $

Liaison retardée

Le choix de la méthode s’effectuera à l’exécution (runtime).

Slide 42
Intérêts :
• permet donc de modifier facilement le comportement d’une classe
• y compris pour une classe compilée (sans le source)
• autorise le polymorphisme d’inclusion (voir sous-typage)

& %
J1 Noyau Objet 31

' $

Exemple

class InputString{
String txt;
InputString(){txt="";}
String value(){return txt;}

void input(String msg) {


ES.write(msg + " : ");
txt=this.read str(); //
Slide 43 ES.writeln();
}

String read str() {


String s = new String();
char c;
while ((c=ES.readkey()) 6= ’\n’)
{ES.write(c);s=s+c;}
return s;
}
}

& %
J1 Noyau Objet 32

' $

Exemple de redéfinition

class InputPasswd extends InputString {

String read str() {


String s = "";
Slide 44 char c;
do {
c = ES.readkey();
if (c 6= ’\n’) {ES.write(’∗’); s = s + c;}
} while (c 6= ’\n’);
return s;
}
}

& %
J1 Noyau Objet 33

' $

Exécution

class TestInput {

public static void main(String args[])


{ InputString s1 = new InputString();
InputPasswd s2 = new InputPasswd();

s1.input("login");
Slide 45 s2.input("passwd");
ES.writeln("\n\n");
ES.write(s1.value() + " a " +
s2.value());
ES.write(" comme mot de passe");
}
}
java TestInput
login : emmanuel
passwd : *******
emmanuel a pilpoil comme mot de passe
& %
J1 Gestion mémoire 34

' $

Polymorphisme

Réutilisation du même nom sur des types différents.


• paramétrique (à la Caml) : même code pour n’importe quel
Slide 46 paramètre;
• ad hoc (surcharge) : code différent selon le type des paramètres;
• d’inclusion (ou d’héritage) : code différent selon les sous-types.
En Java polymorphisme ad hoc et d’inclusion (sous-cas plus fin du
premier).

& %

' $

Relations

• Est-un (is-a) :
Slide 47 s’il est un descendant
• A-un (has-a) :
s’il possède une variable d’instance
Une difficulté de conception objet provient de la communication
entre objets!!!

& %
J1 Exceptions 35

' $

Mémoire et Egalité

pointeur = référence = adresse mémoire


pointeur nul = null
les objets et les tableaux sont des références!!!
Slide 48
pas les types de base

opérateur == teste uniquement les adresses, pas le contenu de la zone


pointée
Utiliser alors la méthode equals(o) héritée d’Object!!!
Allocation explicite (new mais récupération automatique (GC).

& %
J1 Exceptions 36

' $

Exceptions

Une exception est une rupture de calcul.

utilisée :

Slide 49 • pour éviter les erreur de calcul


– division par zéro
– accès à la référence null
– ouverture dn fichier inexistant
– ...
• comme style de programmation
En Java une exception est un objet

& %
J1 Exceptions 37

' $

Exceptions : Syntaxe

pose d’un récupérateur :


instruction ::=
try {instructions}
catch (type variable) { instructions}
Slide 50
...
finally { instructions }
déclenchement :
throw ThrowableObject ;
indication d’échappement d’une méthode “
throws ExceptionClass}
& %
J1 Exceptions 38

' $

Exemples d’exceptions

class Exemple1 {
public int division(int a,int b) {
return (a/b);
}
}

class Division par zero extends Exception {


}
Slide 51
class Exemple2 {

private int division aux(int a,int b)


throws Division par zero
{ if (b == 0)
throw new Division par zero();
else return (a/b);
}

public int division(int a, int b)


& %
J1 Exercices d’application 39

' $

{
try { return division aux(a,b); }
catch(Division par zero e) { return 0;}
finally {ES.writeln("on passe ici");}
Slide 52
}
}
La clause finally est facultative. Son code est
exécuté à la sortie du try.

& %
J1 Exercices d’application 40

' $

Environnement : salle GLA

• Windows NT
• Solaris (Unix S5)
Slide 53
• SunOS (Unix BSD)
• jdk 1.1.6 sur Windows NT et Solaris
• SunOS utilisé comme terminal X
• Emacs sur toutes les machines

& %

' $

Premiers pas

Connexion:

Slide 54 • constituer 15 binômes


• récupérer les login/mdt
• effectuer le premier login
catalogue de travail: Créer un catalogue de travail TP1 à partir
de votre HOMEDIR.

& %
J1 Exercices d’application 41

' $

Conventions

Slide 55 • Java distingue les minuscules et les majuscules


• les noms des classes et des interfaces commencent par une
majuscule
• les noms de méthodes commencent par une minuscule

& %
J1 Exercices d’application 42

' $

3 types de commentaires

double valeur = 3.45; // commentaire

/* un commentaire
sur plusieurs lignes
*/

Slide 56 /**
un commentaire special
pouvant etre traite
par javadoc
pour la construction de
la documentation
se place devant une classe
une interface, une methode
ou une variabel
*/

& %
J1 Exercices d’application 43

' $

Prise en main de l’éditeur

Ecrire sous Emacs:


Dans le “buffer”scratch sauver le buffer sous le nom P1.java dans
la catalogue TP1.

Slide 57
Ensuite ecrire le programme suivant :
class P1 {
public static void main() {
System.out.printl("Bonjour!!!");
}
}

& %
et sauver le une fois écrit.
J1 Exercices d’application 44

' $

test de l’environnement

Ouvrir un shell: dans le menu d’Emacs


Test du compilateur: aller dans la fenêtre
shell
Slide 58 dans le catalogue TP1
et compiler le programe Java : javac P1.java
Test de l’exécution: dans le shell
exécuter le programme P1.class :
java P1
Impression: : imprimer le

& %
J1 Exercices d’application 45

' $

Utilisation de ES

Pour simplifier l’affichage et la lecture clavier


en mode texte, on utilise les méthodes de classe
de la classe ES du paquetage SJ.
En écriture:
• void ES.write(String s)

Slide 59 • void ES.writeln(String s)


En lecture:
• String ES.readln()
• int ES.readln int()
En mode caractère:
• char ES.readkey()
Hasard:
• double ES.random()

& %
J1 Exercices d’application 46

' $

Chemin des classes


Slide 60
Pour vérifier que vous atteignez bien la class ES, ajouter dans le
programme précédent l’affichage d’une chaı̂ıne de caractères.

& %

' $

Exercices

1. c’est plus / c’est moins :


Dans ce jeu la machine peut soit chercher à déterminer un
nombre caché entré par l’utilisateur, soit répondre à un
Slide 61 utilisateur qui cherche un nombre.

Cet exercice est une mise en route pour s’habituer à la syntaxe


Java.
2. liste d’associations : une liste d’association est une liste de
couples (clé,valeur) permettant de rechercher une valeur à partir
de sa clé.

& %
J1 Exercices d’application 47

Exercices
C+/C-
On définit une classe arbitre qui possède une variable entière et les méthodes
suivantes : void nouveau() : qui choisit un nouveau nombre, String verif(int
a) qui retourne une chaine selon le nombre proposé.

Le programme principal sera constitué d’une boucle demandant un nom-


bre à l’utilisateur, et demandant à une instance d’Arbitre de vérifié ce nom-
bre. Selon le retour, le programme repart dans la boucle ou en sort.

Liste d’association
On cherche à définir des listes d’associations (ensemble de (clé,valeur)) per-
mettant la recherche d’une valeur par sa clé.

1. Ecrire une classe CoupleIC pour la construction de couples composés


d’un entier et d’une chaine.
2. Ecrire une classe ListeAssoc contenant les méthodes : ajoute(couple)
qui ajoute un couple à la liste, recherche(c) qui retourne la valeur
associée à la clé si elle existe et sinon déclenche une exception, et une
méthode enleve(c) qui retire l’association de la liste.

1
On représentera la liste par un tableau et un indice.
3. Tester ces classes à partir d’un programme principal
4. Ecrire une classe ListeAssocOpt qui hérite de la première, en ajoutant
un champs indiquant qu’elle peut être optimisée, une méthode optimise
qui effectue le travail (trie le tableau) permettant ensuite une recherche
rapide (dichotomique) en modifiant en conséquence la recherche.
5. Tester cette nouvelle classe.

6. Ecrire une classe, sous classe de ListeAssocPOpt, qui optimise toujours


l’accès.
7. Tester cette nouvelle classe.

1 Dans le cas d’une liste chaı̂ınée comment représente-t-on la liste vide?


J1 Exercices d’application 48

' $

Application : jeu de la vie

Le jeu de la vie est une simulation d’automates cellulaires.

Le monde est représenté par un ensemble de cellules. Chaque cellule


Slide 62 a 8 voisins (monde torique type chambre à air).
Les règles de vie sont les suivantes :
• une cellule meurt si elle a moins de 2 voisins (isolement) ou plus
de 3 (surpopulation).
• une cellule nait sur une case vide si celle-ci a exactement 3
voisins.

& %

Jeu de la vie
1. Ecrire une classe Cell contenant un champs booléen et une méthode
est vivante qui retourne son état.
2. Ecrire la classe Monde contenant l’ensemble des cellules sous la forme
dn tableau de cellules à deux dimensions.
Cette classe contiendra 2 types de remplissage : un aléatoire et un
deuxième manuel. Les autres méthodes seront void affiche() pour
l’affichage en mode texte, Cell get cell(x,y), void set cell(x,y,c),
int voisins(x,y), void gen suiv pour le calcul de la génération
suivante.
3. Enfin la classe JDLV sera le point d’entré du programme.
J1 Exercices d’application 49

/∗∗
@author Emmanuel Chailloux
@organization Universite Pierre et Marie Curie
@version 1.0
∗/

/∗∗
representation du monde des cellules
contient la taille du monde
un tableau de cellules correspondant
le numero de la generation
∗/

class Monde {

int maxx, maxy;


Cell m[][];
int num=1;

/∗∗
constructeur sans parametre : construit un monde de taille 20x8
∗/

Monde() {
maxx = 20;
maxy = 8;
m=new Cell[maxx][maxy];
monde vide();

/∗∗
constructeur avec taille : construit le monde de cette taille
∗/

Monde(int x, int y) {
maxx=x;
maxy=y;
m = new Cell[maxx][maxy];
monde vide();
}

/∗∗
alloue chaque cellule du monde
∗/
J1 Exercices d’application 50

void monde vide() {


for (int i=0; i<maxx; i++) {
for (int j=0; j<maxy; j++) {
m[i][j]=new Cell();
}
}
}

/∗∗
remplissage aleatoire du monde
favorise les cases vides (80 %)
∗/

void init alea() {


for (int i=0; i<maxx; i++) {
for (int j=0; j<maxy; j++) {
if (ES.random() > 0.8) set cell(i,j,new Cell(true));
}
}
}

/∗∗
remplissage manuel du monde
on indique seulement les cellules vivantes en donnat leurs coordonnees
pour sortir on indique des coordonnees inexistantes
∗/

void init man() {


int x,y;
while(true) {
ES.writeln("Entrer les coordonnees de la case (sur 2
lignes) ");
ES.writeln("ou des coordonnees en dehors du monde pour
sortir");
x=ES.readln int();
y=ES.readln int();
if ((x≥0)&&(x<maxx)&&(y≥0)&&(y<maxy))
{set cell(x,y,new Cell(true));}
else {break;}
}
}

/∗∗
change le contenu d’une cellule du monde
∗/

void set cell(int x,int y, Cell c) {


J1 Exercices d’application 51

m[x][y]=c;
}

/∗∗
demande le contenu d’une cellule du monde
∗/

Cell get cell(int x, int y) {


return m[x][y];
}

/∗∗
retourne le tableau de cellules du monde
∗/

Cell [][] get cells(){return m;}

/∗∗
calcule le nombre de voissins d’une cellule
on suppose que le monde est un tore (chambre a air)
on calcule le nombre de cellules vivantes dans un carre 3x3, puis on soustrait
si la case centrale etait vivante.
∗/

int voisins(int x, int y) {


int r=0;
for (int i = x-1;i≤x+1;i++) {
int k = (i+maxx) % maxx;
for (int j = y-1;j≤y+1;j++) {
int l = (j+maxy) % maxy;
if (m[k][l].est vivante()) r++;
}
}
if (m[x][y].est vivante()) r--;
return r;
}

/∗∗
calcul de la generation suivante
pour chaque cellule on calcule le nombre de voisins
puis on applique les regles de vie et de mort de la simulation
∗/

void gen suiv() {


Monde m2 = new Monde(maxx,maxy);
J1 Exercices d’application 52

// toutes les cellules sont vides

for (int i=0;i<maxx;i++) {


for (int j=0; j<maxy; j++) {
int n = voisins(i,j);
if (m[i][j].est vivante()) {
if ((n== 2) || (n==3)) {m2.set cell(i,j,new Cell(true));}
}
else {
if (n==3) {m2.set cell(i,j,new Cell(true));}
}
}
}
m=m2.get cells();
num++;

/∗∗
affiche la generation i
∗/

void affiche() {
for (int j=0; j<maxy; j++) {
for (int i=0; i<maxx; i++) {
if (m[i][j].est vivante())
ES.write("∗ ");
else
ES.write(". ");
}
ES.writeln();
}
ES.writeln("Generation "+num);
}

/∗∗
classe minimale pour les cellules
∗/

class Cell {

boolean val;
J1 Exercices d’application 53

Cell() {val=false;}
Cell (boolean b) {val = b;}

boolean est vivante() {return val;}

/∗∗
classe de l’application JDLV
∗/

class JDLV {

/∗∗
initialisation du monde :
taille et type de remplissage
toute la partie initialisation du monde est dans la methode init

∗/

/∗∗
determine la taille du monde et le type de remplissage
∗/

public static Monde init() {


String s;

Monde m;

ES.write("Voulez-vous donner la taille du monde? (O/N)");


s=ES.readln();
ES.writeln();
if (!(s.equals("O"))) {m = new Monde(30,10);}
else {
int x,y;
ES.write("largeur : ");
x=ES.readln int();
ES.write("hauteur : ");
y=ES.readln int();
m = new Monde(x,y);
}

do {
ES.writeln("Appuyer sur la touche <A> pour un remplissage
J1 Exercices d’application 54

aleatoire");
ES.writeln(" ou <M> manuel");
s=ES.readln();
} while ((!(s.equals("A"))) && (!(s.equals("M"))));

if (s.equals("A")) m.init alea(); else m.init man();


return m;
}

/∗∗
boucle sans fin d’attente d’evenements
sortie en appuyant sur F (break)
∗/

public static void boucle(Monde m) {


String s;

ES.writeln("Appuyer sur la touche <F> pour sortir du


programme");
ES.writeln(" ou sur une autre touche pour continuer");

while (true) {
m.affiche();
s=ES.readln();
if (s.equals("F")) break;
else m.gen suiv();
}
}

/∗∗
derniere methode appelee avant la sortie
∗/

public static void fin() {


ES.writeln("\n ... A bientot \n");
}

/∗∗
point d’entree de l’application
∗/

public static void main(String args[]) {


Monde m;
m=init();
boucle(m);
fin();
J1 Exercices d’application 55

}
J2 Interfaces 56

' $

Plan du 2ème jour

• Interfaces
Slide 63 • sous-typage et polymorphisme
• paquetages
• modifieurs
• bibliothèque standard

& %

' $

Interfaces

[ public ] interface l_intf [ extends [ a_intf]+ ] {


declarations
Slide 64 }
Une interface déclare un protocole de communication.
Les déclarations peuvent mentionner des méthodes et des constantes.

Les interfaces sont souvent nommées par des adjectifs.

& %
J2 Polymorphisme 57

' $

Implantation d’interfaces

[public] class la_classe [extends superclasse]


[implements [l_intf]+] {
}
Une classe peut implanter une ou plusieurs interfaces.
Slide 65
Elle est alors conforme au protocole décrit dans l’interface.

Intérêts: :
• permet d’être vu de différentes manières
• ne nécessite pas d’hériter
• simule de l’héritage multiple (sans code)
& %

' $

Types des variables

1. les types de base


Slide 66
2. les noms de classe
3. les noms d’interface
4. les types tableaux

& %
J2 Polymorphisme 58

' $

Sous-type

ST ≤ T : ST est sous-type de T :
une valeur ST peut toujours être utilisée à la place d’une valeur T !
Slide 67
En Java : une sous-classe est un sous-type
En effet une instance d’une sous-classe saura toujours répondre aux
messages que peuvent recevoir les instances de la classe ancêtre.

De même une sous-interface est un sous-type!

& %

' $

Conversion implicite

pour le passage d’arguments (et l’affectation) :

Slide 68 C x = new C();


SC y = new SC(); // SC sous-classe de C

x = y; // OK
Pas de problème à l’exécution, le nouvel x saura répondre à tous les
messages de C.

& %
J2 Polymorphisme 59

' $

Conversion explicite

est utilisée quand la relation de sous-typage n’est pas vérifiée :


Slide 69
SC z = (SC) x;
un test dynamique (à l’exécution) est alors effectué.
Utile: car il n’y a pas de polymorphisme paramétrique en Java!

& %

' $

sous-type, surcharge et redéfinition

Java évite les problèmes de typage des méthodes en différenciant


Slide 70 redéfinition et surcharge y compris si les types des paramètres ou le
type du résultat est un sous-type.

Simplification: quelques fois gênante, car cela force a‘ coercer le


type dans le programme.

& %
J2 Polymorphisme 60

' $

Exemple

class TestC {
public static void main(String args[])
{
PointColore p0 = new PointColore();
Point p1 = new PointColore(3,4,"bleu");

Slide 71 p0.affiche(); p1.affiche();


p0.rmoveto(7,12);
p1.rmoveto(5,6);
p0.affiche(); p1.affiche();
if (p0.distance() == p1.distance())
ES.writeln("c’est le hasard");
else
ES.writeln("on pouvait parier");
}
}

& %
J2 Paquetages 61

' $

Polymorphisme

Réutilisation du même nom sur des types différents.


• paramétrique (à la Caml) : même code pour n’importe quel
Slide 72 paramètre;
• ad hoc (surcharge) : code différent selon le type des paramètres;
• d’inclusion (ou d’héritage) : code différent selon les sous-types.
En Java polymorphisme ad hoc et d’inclusion (sous-cas plus fin du
premier).

& %

' $

Paquetage

Regroupement de classes et d’interfaces dans un archivage


hiérarchique (.class).
Déclaration:
La déclaration d’un paquetage est la première instruction d’un
Slide 73 programme.
package nom[.nom]* ;
utilisation:
import nomqualifie;
nomqualifie.*;
autorise les références abrégées.

& %
collisions interdites.
J2 Modifieurs 62

' $

Paquetage (suite)

Sans rien préciser dans son programme, celui-ci est considéré faisant
partie du “paquetage anonyme”.
Slide 74

La hierarchie des paquetages suit la hiérarchie des catalogues du


système.

L’appartenance à un paquetage modifie les règles de visibilité.

& %

' $

Modifieurs généraux

abstract final
doit être sous-classée C ne peut être sous-classée
Slide 75
doit avoir une implantation M ne peut être raffinée
V ne peut être modifiée
et toujours static :
M et V : méthode ou variable de classe.
(pas de this dans ces méthodes)

& %
J2 Modifieurs 63

' $

Classe abstraite : un exemple

Listes:
abstract class List { // classe abstraite racine
// de l’arbre d’heritage
Slide 76 abstract boolean empty() ;
abstract int head() throws EmptyList;
abstract List tail() throws EmptyList;
abstract List cons(int x);
abstract void display();
}

class EmptyList extends Exception {}

& %

' $

classes concrètes : Nil

class Nil extends List {


static List NIL = null;
boolean empty(){return true;}
List cons(int x){return new Cons(x,this);}
int head()throws EmptyList {throw new EmptyList();}
Slide 77
List tail()throws EmptyList{throw new EmptyList();}
void display(){System.out.print("[]");}
}
\end{slide}
\begin{slide}
\heading{Classes concr\‘etes : Cons}
\begin{verbatim}

& %
class Cons extends List {
J2 Modifieurs 64

' $

int car;
List cdr;
Cons(){car=0;cdr=Nil.NIL;}
Cons(int a, List b){car=a;cdr=b;}

Slide 78 boolean empty(){return false;}


List cons(int x) {return new Cons(x,this);}
int head(){return car;}
List tail(){return cdr;}
void display(){System.out.print(car + "::"); cdr.display();}
}

& %

' $

final

static final pour une variable en fait une constante!!!


Slide 79

final empêche de raffiner une méthode

final d’une classe empêche le sous-classement.

& %
J2 Modifieurs 65

' $

Modifieurs de visibilité

C
M public C protected

Slide 80 V V
C
M default
V
M private M private
V protected V

& %
J2 Modifieurs 66

' $

Visibilité

// P.A.ja // Q.D.java
package P; package Q;
public class A { import P.*;
int i; class D {
} }
Slide 81
// P/B.java // Q/E.java
package P; package Q;
class B extends A { import P.*;
} class E extends A {
}
// P/C.java
package P;
class C {
}

& %
J2 Bibliothèque standard 67

' $

Représentation graphique

Slide 82 P D Q
C A
B E

& %

' $

Slide 83 Bibliothèque standard

& %
J2 Exercices d’application 68

' $

Que fait ce programme?

// classe C
int M1() { ...}
String M2() { ... this.M1() ... }
// Sous-classe SC de C
int M1() { autre code}
... main ... {
C x = new C();
SC y = new SC();
Slide 84
C z = y;
...
x.M1();
x.M2();
y.M1();
y.M2();
z.M1();
z.M2();
En particulier quelles sont les méthodes
déclenchées? Vous pouvez écrire un programme

& %
correspondant à ce squelette.
J2 Exercices d’application 69

' $

Que fait ce programme?

// class C { ...
int M(C c) { ...}

// sous classe SC de C
int M (C c) { ...}
int M (SC c) { ...}
Slide 85 void main ... {
C x = new SC();
SC y = (SC) x;
y.M(y) + y.M(x) +
x.M(x) // + x.M(y)
En particulier quelles sont les méthodes
déclenchées? Vous pouvez écrire un programme
correspondant à ce squelette avec des
affichages. Que se passe-t-il si on décommente
la dernière ligne?

& %
J2 Exercices d’application 70

' $

Interface

1. Définir une interface pour les listes d’association. On pourra


Slide 86
définir des interfaces pour les “clés” et les “valeurs” ou pour les
couples “clé”,”valeur”..
2. Définir des classes conformes aux interfaces précédentes. On
utilisera des listes chaı̂nées.

& %

' $

Classe abstraite

On cherche à étendre les fonctionnalités de la classe ExpAr vue en


cours.
Slide 87
1. Ajouter une classe Div
2. Ecrire une classe Lecteur qui fasse l’analyse syntaxique d’une
chaine pour en construire un ExpAr. On prendra des formules
sous forme préfixe. Les constantes, comme les opérateurs, ne
prendront qu’un caractère.

& %
J2 Exercices d’application 71

Calculateur de Bureau
Soit le début de la hiérarchie suivante :
class Div0 extends Exception {}

abstract class ExpAr { // classe abstraite racine de l’arbre d’heritage


abstract int eval () throws Div0;
abstract String scp () ;
}

class Cte extends ExpAr { // premiere sous-classe concrete


int val ;
Cte (int v) {val = v ;}
int eval () { return val ;}
String scp () {return (new Integer(val)).toString() ;}
}

abstract class Bin extends ExpAr {


ExpAr og, od ;
abstract int oper (int g , int d) throws Div0;
abstract String cop () ;

int eval () throws Div0 {return oper (og.eval(), od.eval()) ;}


String scp () {return ("("+ og.scp() + cop() + od.scp() +")") ; }
void init (ExpAr g, ExpAr d) {og = g ; od = d ;}
}

class Add extends Bin {


Add (ExpAr g, ExpAr d) {init (g, d) ;}
int oper (int g, int d) {return (g+d) ;}
String cop () {return ("+") ;}
}

class Mult extends Bin {


Mult (ExpAr g, ExpAr d) {init (g, d) ;}
int oper (int g, int d) {return (g∗d) ;}
String cop () {return ("∗") ;}
}
J2 Exercices d’application 72

' $

Coercion de type

Ecrire une classe implantant l’interface suivante :


public interface Stack {
Slide 88 public int size();
public boolean isEmpty();
public void push(Object e);
public Object pop()
throws StackEmptyException;
}

& %

Piles d’Objets
On suppose la définition suivante de l’exception :

public class StackEmptyException extends Exception {


}
Ecrire un programme principal manipulant une pile d’entiers et une pile de
caractères.
J2 Exercices d’application 73

' $

paquetage
Slide 89
Faire un paquetage des différents interfaces, classes pour utiliser les
piles précédentes.

& %

' $

Ressources

Slide 90 • Explorez la hiérarchie de classes de la bibliothèque initiale.


• Surfez sur le tutorial de Sun.
Ces ressources existent en local sur les machines du GLA.

& %
J2 Exercices d’application 74

' $

Application : Vérificateur de formules

Dans la même veine que le calculateur d’expressions arithmétique, on


se propose d’écrire un calculateurs d’expressions booléennes dans le
but de vérifier si une formule est toujours vraie.
1. Ecrire la hiérarchie de classes pour les ExprBool
Slide 91 2. Ajouter une classe var pour les variables.
3. Pour accepter les variables, une possibilité est de passer un
environnement comme paramètre d’eval. Effectuer ces
modifications. Regarder si vous pouvez le faire , soit directement,
soit en dérivant et en implantant une interface plus précise.
4. Définir une classe Formule, qui contiendra la formule et
l’environnement contenant toutes les variables associées à une

& %
valeur. Ecrire la méthode env suivant qui calule une nouvelle

' $

série de valeurs pour les variables de la formule.


Slide 92
5. Ecrire une méthode qui calcule toutes les valeurs possibles des
variables d’une formule pour construire sa table de vérité.

& %
J3 Processus Légers 75

' $

Plan du 3ème jour

• Processus légers
Slide 93
• Interface graphique : AWT
• Classes locales
• Applet

& %

' $

Processus légers (Thread)

Modèle de parallélisme à mémoire partagée


• contexte d’exécution sur une même machine virtuelle
• même zone mémoire (6= fork)
Slide 94
• ne dépend pas du système (Windows 3.1)
• possède un nom et une priorité
• pas de préemption à priorité égale
⇒ le faire à la main
• ne va pas plus vite
• sert à exprimer des algos concurrents
& %
J3 Processus Légers 76

' $

Création et Exécution

2 possibilités :
• sous-classer la classe Thread
et redéfinir la méthode public void run()
Slide 95
MCThread x = new MCThread (); x.start();
• Implanter l’interface Runnable
et implanter public void run
MCTheadI x = new MCThreadI();
MCThreadI y = new Thread(x,"Nom"); y.start()
Quand start() retourne, la tâche termine.

& %

' $

Méthodes sur les threads

• start() et stop()
• suspend() et resume()
Slide 96
• wait() et notify (synchronisation)
• sleep(i)
• yield()
• interrupt() (exception)

& %
J3 Processus Légers 77

' $

Relations entre threads

1. sans relation
Slide 97
2. avec relation mais sans synchronisation
3. relation d’exclusion mutuelle
4. relation d’exclusion mutuelle avec communication

& %
J3 Processus Légers 78

' $

Sans relation

public class SR {
public static void main ( String []s) {
Thread t1 = new Aff("Bonjour");
t1.start();
new Aff("Au revoir").start();
}
}

Slide 98
class Aff extends Thread {
String txt;
Aff (String s){txt=s;}

public void run () {


while(true) {
ES.writeln(txt);
yield();
}
}
}
& %
J3 Processus Légers 79

' $

Relation sans synchronisation

sur une même structure de données à des endroits différents :


Slide 99
Exemple : calcul de la nouvelle génération du jeu de la vie
par différentes threads.

ou ouverture d’une connexion sur une socket

& %

' $

Synchronisation

Verrou (accès exclusif) sur un objet :


synchronized (o) { ... }
Slide 100 }

// ou sur une methode

synchronized type nom_methode( ..) { ...}


Une seule thread peut prendre le verrou (les autres attendent).
Le verrou est rendu à la sortie du bloc de synchronisation.

& %
J3 Processus Légers 80

' $

Relation d’exclusion mutuelle

Dès que le verrou est pris :


Slide 101 1. appel d’une méthode synchronized
il garantit qu’une seule méthode “synchronisee” peut être
appelée sur cet objet
2. bloc synchronized sur un objet
il verouille l’objet.

& %

' $

Communication

à l’intérieur d’un bloc de synchronisation

Slide 102
• o.wait() : relache le verrou et attend une notification
• o.notify() : relance une tâche en attente (une au hasard). Elle
doit en premier réacquérir le verrou.
• o.notifyAll() : relance toutes les tâches.

& %
J3 AWT 81

' $

Exclusion mutuelle avec communication

Producteur/Consommateur :

Slide 103 // thread du producteur // thread consommateur


entree code sync entree code sync
while(buffer plein) while (buffer vide)
wait() wait()
produit_1() consomme_1()
notify() notify()

& %

' $

Abstract Windowing Toolkit

Paquetage de classes pour la construction d’interfaces graphiques :


Slide 104
• système graphique indépendant d’une plateforme
⇒ avoir les boutons Mac sur MAc, Motif sous Motif, ...
• avoir une API de porgrammation simple (??)
• qui pourra être intégré dans un navigateur.

& %
J3 AWT 82

' $

Hiérarchie de classes

Object

Component Event Graphics Color Rectangle

Button
Slide 105 Canvas
Checkbox Container
Choice
Label Panel
List
Window
Scrollbar
TextComponent
Applet
Frame Dialog

TextAera TextField FileDialog

& %

' $

Composants

objet abstrait ayant : une position, une taille, dessinable et pouvant


Slide 106 recevoir des évènements
• composants simples : Button, Label, . . .
• conteneurs : pouvant recevoir d’autres composants
possèdent un contexte graphique (Graphics).

& %
J3 AWT 83

' $

Conteneurs

• Ceux qui n’ouvrent pas de fenêtres : Panel, Applet


Slide 107
• Ceux qui ouvrent une fenêtre : Dialog, FileDialog et Frame
Pouvant suivre différents algorithmes de placement de composants.
Application graphique : instancie au moins une fois une Frame
Applet : est un composant graphique

& %
J3 AWT 84

' $

Dessiner

import java.awt.∗;
import java.awt.event.∗;

class TestXframeD {
static public void main(String [] args) {
XframeD d = new XframeD();
d.dessine();
Slide 108 }
}

class XframeD extends Frame {

Canvas p;

XframeD() {
super("DESSIN");

p = new Canvas();
& %
J3 AWT 85

' $

p.setSize(400,300);

this.add(p);
this.pack();
this.show();
}

void dessine() {
Slide 109 Color c1 = Color.blue;
Color c2 = Color.red;
Graphics g = p.getGraphics();
g.drawString("Mon dessin",160,40);

for (int i = 0; i< 10; i++) {


g.fillRect(40+i∗20,100,10,10);
}
}
}

& %
J3 AWT 86

' $

Créer une interface

import java.awt.∗;
import java.awt.event.∗;

class TestXframe {
static public void main(String [] args) {
Xframe e = new Xframe();
e.init event();
Slide 110 }
}

class Xframe extends Frame {

String monlogin ="emmanuel";


String monpasswd ="pilpoil";
TextField login;
TextField passwd;
Panel p;

& %
J3 AWT 87

' $

Xframe() {
super("LOGIN");
p = new Panel();
p.setSize(400,500);
login = new TextField(8);
passwd = new TextField(8);
p.add(new Label("Login : "));
p.add(login);
p.add(new Label("Password : "));
Slide 111 passwd.setEchoChar(’∗’);
p.add(passwd);
this.add(p);
this.pack();
this.show();
}

void init event() {


}
}

& %
J3 AWT 88

' $

Evénements

En JDK 1.1 : modèle par délégation.

D1
C1
D2
Slide 112
C2
D3

C3

D4
C4

Source Délégué

& %

' $

Sources et délégués

Les composants (Source) peuvent déclencher des évènements


Ceux-ci seront traités par les “délégués” enregistrés:
instances de classe implantant des interfaces ‘Listener

Slide 113 public <TypeEvt>Listener set<TypeEvt>Listener(


<TypeEvt>Listener monDelegue)
public <TypeEvt>Listener add<TypeEvt>Listener(
<TypeEvt>Listener monDelegue)
public <TypeEvt>Listener remove<TypeEvt>Listener(
<TypeEvt>Listener monDelegue)

où <TypeEvt> est remplacé par un événement :


addMouseListener(MouseListener monDelegue)

& %
J3 AWT 89

' $

Evénements et Composants

Chaque composant peut déclencher certains événements :


un Panel pourra déclencher un événement souris (MouseEvent).

Un délégué implante une interface Listener.


Slide 114

Il existe des adaptateur implantant certaines interfaces (méthodes


> 1).

Listener Interface Adaptater Class Methods


ActionListener NON actionPerformed
MouseListener MouseAdapter mousePressed . . .

& %

' $

Délégué

import java.awt.∗;
import java.awt.event.∗;

class AdaptateurAction implements ActionListener {

Slide 115
XframeE A;

AdaptateurAction(XframeE a) {
A=a;
}

public void actionPerformed(ActionEvent e) {


if ((e.getSource() == A.login) || (e.getSource() == A.passwd))
& %
J3 AWT 90

' $

{ if ((A.login.getText().equals(A.monlogin)) &&
(A.passwd.getText().equals(A.monpasswd)))
{A.OK=true; A.good();}
Slide 116 else {A.nogood();}
}
}
}

& %
J3 AWT 91

' $

Enregistrement

import java.awt.∗;
import java.awt.event.∗;

class TestXframeE {
static public void main(String [] args) {
XframeE e = new XframeE();
e.init event();
}
Slide 117 }

class XframeE extends Xframe {

boolean OK = false;

void init event () {


AdaptateurAction aa;
aa = new AdaptateurAction(this);
login.addActionListener(aa);
passwd.addActionListener(aa);
}
& %
J3 AWT 92

' $

void good() {
ES.writeln("C’est parti");
System.exit(0);
}
Slide 118
void nogood() {
ES.writeln("Essaie encore!!!");
}

& %
J3 AWT 93

' $

Classes locales

Pour simplifier la communication entre le délégué et le composant :


le JDK 1.1 a introduit les classes locales ou internes (y compris
Slide 119 anonymes).

Rightarrow cela permet de ne pas passer le composant comme


variable du délégué.

Les variables dnstance du composant sont directement accessibles.

& %

' $

Déclaration de classes locales

1. nouveau membre (champs) d’une classe


Slide 120
2. à l’intérieur d’un bloc d’instructions
Premier cas : accessible par la notation “point”
Deuxième cas : non accessible en dehors du bloc
mais la valeur peut sortie du bloc (si implantation d’une interface)

& %
J3 AWT 94

' $

Exemple d’une classe locale

import java.awt.∗;
import java.awt.event.∗;
import java.applet.∗;

class Test3 1 extends Applet {


Slide 121

class AdaptateurSouris extends MouseAdapter


implements MouseListener {
public void mousePressed (MouseEvent e)
{
int x = e.getX();
int y = e.getY();
System.out.println("x = " + x + " y = "+y);
& %

' $
getGraphics().drawString("salut tout le monde",x,y);
}
}

Test3 1() {
MouseListener clic = new AdaptateurSouris();

Slide 122
addMouseListener(clic);
}

public void init () {


this.setBackground(Color.white);
}
}

& %
J3 AWT 95

' $

Classe (locale) anonyme


Slide 123
Dans les cas où le nom de la classe n’a pas d’importance :
elle peut être déclarée anonymement!!!

& %

' $

Exemple d’une classe locale

import java.awt.∗;
import java.awt.event.∗;
import java.applet.∗;

class Test3 2 extends Applet {


Slide 124

Test3 2() {
MouseListener clic = new MouseAdapter () {
public void mousePressed (MouseEvent e)
{
int x = e.getX();
int y = e.getY();
System.out.println("x = " + x + " y = "+y);
& %
J3 Applets 96

' $

getGraphics().drawString("salut tout le monde",x,y);


}
};
addMouseListener(clic);
}
Slide 125
public void init () {
this.setBackground(Color.white);
}
}

& %

' $

Applets

Slide 126
La classe Applet hérite de Panel et implante Runnable.
Une applet possède une zone graphique (conteneur Panel) qui
n’ouvre pas une nouvelle fenêtre.

& %
J3 Applets 97

' $

cycle de vie

init()⇒start()⇒stop()⇒destroy() où :
• init() : appelée au démarrage de l’applet(initialisation);
• start() : appelée pour lancer l’applet (après l’initialisation ou
Slide 127
après un stop()), effectue le travail;
• stop() : appelée pour arrêter l’applet (quand la page HTML
disparaı̂t);
• destroy() : appelée pour libérer les ressources allouées par
l’applet (juste avant la disparition de l’applet).
void paint(Graphics g) : sera appelée à chaque réaffichage.

& %

' $

Exécution

• Ecrire un fichier “HTML”avec une balise <APPLET>


Slide 128 ... </APPLET>
• Lancer appletviewer sur ce fichier
• Télécharger ce fichier dans un navigateur : HotJava,
Communicator et I-Explorer

& %
J3 Applets 98

' $

Balise

<html>
<head> Exercices en Java
</head>
<body>
Slide 129
<H1> Test </H1>
<P>
<applet code="Test1" height=400 width=400>
<P><EM> Not a java-powered browser! </EM>
</applet>
</body>
</html>

& %
J3 Applets 99

' $

Applet dessin

import java.awt.∗;
import java.awt.event.∗;
import java.applet.∗;

public class graf extends Applet {

Slide 130 public void paint(Graphics g) {


g.drawRect(25,30,60,40);
g.drawRect(125,30,100,100);

g.setColor(Color.cyan);
g.drawOval(25,30,60,40);
g.drawOval(125,30,100,100);
}

& %
J3 Applets 100

' $

Applet login

import java.applet.∗;
import java.awt.∗;
import java.awt.event.∗;

Slide 131 public class passwdTest extends Applet {

String monlogin ="tartempi";


String monpasswd ="itaparit";
TextField login;
TextField passwd;
boolean OK = false;

& %

' $

ActionListener RC = new ActionListener() {


public void actionPerformed(ActionEvent e) {
if ((e.getSource() == login) || (e.getSource() == passwd))
{ if ((login.getText().equals(monlogin)) &&
(passwd.getText().equals(monpasswd)))
{OK=true; good();}
else {nogood();}
Slide 132
}
}
};

public void init() {


login = new TextField(8);
passwd = new TextField(8);
add(new Label("Login : "));
& %
J3 Exercices 101

' $
add(login);
add(new Label("Password : "));
passwd.setEchoChar(’∗’);
add(passwd);
login.addActionListener(RC);
passwd.addActionListener(RC);
}
Slide 133
public void good() {
resize(120,180);
this.getGraphics().drawString("c’est parti...",10,150);
}

public void nogood() {


this.getGraphics().drawString("identification
& %

' $

incorrecte",10,100);
Slide 134 }
}

& %
J3 Exercices 102

' $

Producteur/Consommateur

Ecrire un programme gérant un entrepot de voitures.


1. Ecrire une classe Entrepot contenant un tableau de noms, et les
méthodes boolean estVide(), boolean estPlein();, int
retire() et void ajoute(String i). Les méthodes ajoute et
Slide 135 retire sont synchronisées.
2. Ecrire une classe Usine, dérivant de Thread qui produit des
voitures d’un certain nom. Quand une voiture est produite, elle
est rangée dans un entrepot.
3. Ecrire une classe Concessionaire, dérivant de Thread, qui vend
des voitures. Quand une voiture est vendue, elle est retirée de
l’entrepot.

& %
4. Ecrire le programme principal pour 1 entrepot, 1 usine et 1

' $

concessionaire.

Slide 136 5. Ajouter-lui des concessionaires et des usines.


6. Dériver la classe Entrepot pour visualiser graphiquement les
entrées et les sorties de l’entrepot.

& %
J3 Exercices 103

' $

Calculateur d’expressions

Slide 137 La classe suivante est une (mini) interface pour l’entrée d’une formule
dans une applet.
• intégrer la avec la classe LectExprAr et ExprAr
• tester la avec appletviewer etu un navigateur

& %

Calcul d’une expression


On reprend le programme de calcul d’expressions arithmétiques préfixées
pour en faire une applet.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Essai2 extends java.applet.Applet {

TextField ligne = new TextField ("Votre expression") ;


String res = "Debut" ;

ActionListener RC = new ActionListener() {


public void actionPerformed(ActionEvent e) {
if (e.getSource() == ligne) agir(ligne.getText());
}
};

public void init () {


add (new Label (" Une expression en notation prefixee S.V.P."));
add (ligne) ;
J3 Exercices 104

void agir (String lu) {


LectExpAr lec = new LectExpAr (lu) ;
ExpAr ex = lec.lpf() ;
res = ex.scp() + " = " + ex.eval() ;
repaint();
}

public void paint (Graphics g) {


g.drawString(res, 50, 100) ;
}
}

' $

Jeu de la vie

On cherche à interfacer graphiquement le jeu de la vie dont le listing


a été présenté, le tout sans retoucher au listing initial,
Slide 138
• Dérivez la classe principale JDLV pour en faire une applet. On
construira les boutons génération automatique, et remise à vide,
et génération suivante.
• Ajouter des menus pour sauvegarder et lire, sous forme d’objets
persistants, des générations.

& %
J3 Exercices 105

' $

Éditeur de Bitmap

On cherche à faire l’interface graphique d’un éditeur de bitmaps.


Slide 139 • la classe Bitmap est en annexe.
• la classe BitmapIO permettant de lire un format simple (ascii) de
bitmaps suit ce texte.
Ecrire une applet permettant de dessiner un bitmap à la souris, puis
ajouter une interface minimale pour sauver ou lire un bitmap.

& %

un éditeur de bitmaps
On cherche à un écrire un petit éditeur de bitmap (à la manière de la com-
mande bitmap de X-window). Pour cela on représentera un bitmap par sa
taille (largeur et hauteur) et pour les pixels un tableau à 2 dimensions con-
tenant la couleur de chaque pixel.

Code de la classe Bitmap :

package TP3;

import java.awt.∗;

public class Bitmap {

public int width;


public int height;
J3 Exercices 106

int pixel size;

public Color fg;


public Color bg;

public Color [][] bitmap;

public Bitmap(int w, int h, int s) {


width=w; height=h; bitmap = new Color [width][height];
bg=Color.white; fg=Color.black;
pixel size = s;
for (int i=0;i<width;i++) {
for (int j=0;j<height;j++) {
bitmap[i][j] = bg;
}}
}

public int get width(){return width;}


public int get height(){return height;}

public void show pixel(int x, int y, Graphics g) {


g.setColor(bitmap[x][y]);
g.fillRect(x∗pixel size+1,y∗pixel size+1,pixel size-2,pixel size-2);
}

public int get pixel size(){return pixel size;}

public void set color(int x,int y, Color c){bitmap[x][y]=c;}

public void flipflop(int x, int y){


if (bitmap[x][y] == fg){bitmap[x][y]=bg;}
else {bitmap[x][y]=fg;}
}

1. Ecrire une applet permettant de dessiner à la souris un bitmap en


conservant les valeurs des pixels.
2. Ajouter un champs de saisie pour indiquer le nom du fichier du bitmap
et ajouter deux menus pour sauver et lire un bitmap. On utilisera le
format ASCII pour les bitmaps où un pixel allumé est représenté par
le caractère #, l’absence d’un pixel par le caractère -. Chaque ligne
de caractère représente une ligne du bitmap. Les fonctions atobm et
bmtoa de X-window effectueront les conversions entre ce format ASCII
et le format des bitmaps de X-window.
J3 Exercices 107

###################-------------#######---------######
###################---------------###-------------##--
###-----###-----###---------------###-------------#---
##------###------##----------------###-----------##---
#-------###-------#-----------------###---------##----
#-------###-------#-----------------###--------##-----
--------###--------------------------###-------#------
--------###-------###############-----###----##-------
--------###-------###---------###------###--##--------
--------###-------###----------##-------###-#---------
--------###-------###-----------#-------#####---------
--------###-------###-----------#--------###----------
--------###-------###--------------------####---------
--------###-------###--------------------####---------
--------###-------###------#-----------##---###-------
--------###-------###------#----------##----###-------
--------###-------##########----------#------###------
--------###-------##########---------##-------###-----
--------###-------###------#--------##--------###-----
--------###-------###------#-------##----------###----
--------###-------###--------------#------------###---
------#######-----###-----------#######--------#######
------------------###---------------------------------
------------------###-----------#---------------------
------------------###-----------#---------------------
------------------###----------##---------------------
------------------###---------###---------------------
------------------###############---------------------

On suppose connues les deux méthodes suivantes :

public static Bitmap read_bitmap(String file) throws IOException {}


public static void write_bitmap(Bitmap b, String file ) throws IOException

3. Simplifier les entrées/sorties en sérialisant les bitmaps que l’on désire


sauvegarder.

Code des fonctions d’ES :


package TP3;

import java.io.∗;

public class BitmapIO {

static char cfg=’#’;


static char cbg=’-’;

public static Bitmap read bitmap(String file) throws IOException {


FileInputStream in;
int c;
int nc = 0;
int nl=0;
Bitmap b;

/∗
∗ ouverture du fichier
∗/
J3 Exercices 108

try
{ in = new FileInputStream(file);}
catch(FileNotFoundException e) {return new Bitmap(0,0,0);}

/∗
∗ calcul du nombre de colonnes
∗/

try
{ while ((c = in.read()) 6= ’\n’) {nc++;}
nl++;
while ((c = in.read()) 6= -1){if (c == ’\n’) nl++;}}
catch (EOFException e) {System.out.println("par ici " +
nl);nl++;}
catch (IOException e) {return new Bitmap(0,0,0);}
finally {in.close();}
System.out.println("par la " + nl);

System.out.println("nl = " + nl + " nc = " + nc);

/∗
∗ lecture des donne’es
∗/

b= new Bitmap(nc,nl,10);

try
{ in = new FileInputStream(file);}
catch(FileNotFoundException e) {return new Bitmap(0,0,0);}
System.out.println("lecture reelle");
nc=0; nl=0;
try
{ while ((c = in.read()) 6= -1) {
if (c==’\n’) {nl++;nc=0;}
else {
if (c==cbg) {b.bitmap[nc][nl]=b.bg;}
else {b.bitmap[nc][nl]=b.fg;}
nc++;
}
}
}
catch(EOFException e) {return b;}
catch(IOException e) {return new Bitmap(0,0,0);}
finally {in.close();}
System.out.println(b);
return b;
J3 Exercices 109

public static void write bitmap(Bitmap b, String file ) throws


IOException {
FileOutputStream out = new FileOutputStream(file);

for (int j=0;j<b.height;j++) {


for(int i=0;i<b.width;i++) {
if (b.bitmap[i][j] == b.fg) {out.write(cfg);}
else {out.write(cbg);}
}
out.write(’\n’);
}
out.close();

}
J4 Persistance 110

' $

Plan du 4ème jour


Slide 140
• Persistance
• Distribution

& %

' $

Persistance

conservation d’un objet en dehors de l’exécution courante :


dans un fichier ou un flux
But: récupération ultérieure dans le même programme ou un
autre.
Slide 141
Difficultés: :
• lecture/écriture de données
• structures circulaires
• coercion de type à la relecture
• sauvegarde de code

& %
En jdk1.1 : mécanisme de sérialisation!!!
J4 Persistance 111

' $

Sérialisation

• classes de flux
Slide 142 – ObjectOutputStream : flux de sérialisation
– ObjectInputStream : flux de désérialisation
• interface
– Serializable : doit être implantée (vide) pour être sérialisé

& %

' $

Que stocke-t-on?

Le stockage contient :
• le nom et une clé (checksum) de la classe
• tous les champs (de données) sérialisables
Slide 143
La clé permet de vérifier la version de la classe.
Le modifieur transient permet d’indiquer qu’un champs ne doit pas
être sérialisé.

possibilité de changer le mécanisme de sérialisaiton en implantant


une classe Externalizable respectant les interfaces writeExternal
et readExternal.
& %
J4 Persistance 112

' $

Exemple

import java.io.∗;

class Exemple20 implements Serializable {


String nom;
Exemple20 autres;

Exemple20() {nom=null;autres=null;}
Exemple20(String n, Exemple20 e) {
Slide 144 nom=n;autres=e;
}

boolean estVide() {return (nom ==


null);}
void detruit() {nom=null;autres=null;}

public String toString() {


if (estVide()) return "[]";
else if (autres.estVide()) return nom;
else return nom+"::"+autres.toString();
}
& %
J4 Persistance 113

' $

public void ajoute (String unNom) {


System.out.println("∗");
Exemple20 e = new
Exemple20(nom,autres);
autres=e;
nom=unNom;
}

Slide 145 class Execute {


public static void main (String[] args) {
Exemple20 e = new Exemple20();
ObjectOutputStream out;
ObjectInputStream in;

try {
e.ajoute("machin");
e.ajoute("truc");
System.out.println("1 : "+e);
out = new ObjectOutputStream(new

& %
FileOutputStream("Exemple20.dat"));
J4 Persistance 114

' $

out.writeObject(e);
out.flush(); out.close();
e.detruit();
System.out.println("2 : "+e);
in = new ObjectInputStream(new
FileInputStream("Exemple20.dat"));
e.ajoute("bidule");
e.autres = (Exemple20)in.readObject();
in.close();
Slide 146 System.out.println("3 : "+e);
}
catch (java.lang.ClassNotFoundException
exc){System.err.println(exc);}
catch (StreamCorruptedException exc)
{System.err.println(exc);}
catch (IOException exc)
{System.err.println(exc);}
}
}

& %
J4 Distribution 115

' $

Exécution

java Execute

*
Slide 147
*
1 : truc::machin
2 : []
*
3 : bidule::truc::machin
* : trace de ajoute(..)

& %
J4 Distribution 116

' $

Programmation distribuée

Chaque processus gère sa propre mémoire et


communique avec les autres via un medium
(protocoles).
------ /\ ------
| M1 |-----P1 <--> / \ <--> P3-----| M3 |
------ / \ ------
/medium\
----------
Slide 148 ^
|
|
v
P2
|
|
------
| M2 |
------

La communication est explicite et la


synchronisation est implicite :
6= du modèle à mémoire partagée (threads).

& %
J4 Distribution 117

' $

Internet*

organisation du réseau Internet :


----------------
| APPLICATIONS |
----------------
^ |
| |
| v
----------------
| UDP / TCP |
Slide 149
----------------
^ |
| |
| v
----------------
| IP/Interfaces|
----------------
^ |
| |
| v
----------------
| MEDIAS |

& %
----------------
J4 Distribution 118

' $

Protocoles Internet

IPv4 : adresse sur 32 bits : chaque machine a une adresse unique


IP : protocole non fiable : traite juste le routage du datagramme.
Slide 150 UDP : (User Datagram Protocol) non fiable - non connecté
(multiplexage)
TCP : (Transfert Control Protocol) protocole orienté connexion et
fiable
Rightarrow gère les acquitements.

& %

' $

Services Internet

utilisent le modèle client/serveur : le serveur est un programme


offrant un service spécifique (il gère les requêtes des clients en
établissant une connexion ou non selon le protocole.
asymétrie entre le client et le serveur.
Slide 151
Implantation de protocoles de plus haut niveau :
• FTP, TELNET, SMTP, HTTP
• autres c/s : NFS, X-window, rlogin, mysql
Coomunication entre applications via des prises (socket) de
communication, à partir de plusieurs processus/machines. Différents
processus peuvent lire et écrire dessus.
& %
J4 Distribution 119

' $

Communication sur sockets

Le schéma classique d’un serveur est le suivant :


creation de ls socket (socket) : (TCP/UDP)

attachement de la socket (bind) :(ADR_IP,PORT)

ouverture du service (listen) : (nombre)

Slide 152 attente de connexion (accept) : (acceptation)

creation d’un processus (fork) : (ou thread)

proc : boucle sur l’attente de la connexion


newproc : traite la demande

et le client :
creation de la socket (socket) : (TCP/UDP)

connexion sur la prise : (ADR_IP_serv,PORT)

& %
J4 Distribution 120

' $

Classes

paquetage : java.net : fournit un ensemble de classes pour


communiquer sur le réseau Internet.
Slide 153
• classe de bas niveau : pour les couches basses
(DatagramPacket,...)
• et de haut niveau : pour les clients/serveurs
La classe InetAddress représente les adresses Internet. Elle est
utilisée dans la classe Socket. Les classes de haut niveau sont :

& %

' $

Classes de haut niveau

• ServerSocket : méthode accept retourne une socket quand une


Slide 154 demande est reçue;
• Socket (classe finale) : pour la communication à travers le
réseau. Les méthodes getOutputStream() et getInputStream
permettent de récupérer les canaux de communication.
• URL : permet de dialoguer via une URL.

& %
J4 Distribution 121

' $

Exemple de client/serveur

Conversion de chaı̂nes en MAJUSCULE via un serveur (Java : de


l’esprit à la méthode)

Slide 155
Le serveur est construit à partir de 2 classes :
• Serveur : classe générique (au numéro du port près)
• Connexion : pour les canaux et le traitement
Lors d’une connexion d’un client au serveur (Serveur.run()) une
nouvelle instance de Connexion est créée.

& %
J4 Distribution 122

' $

Partie serveur

import java.io.*;
import java.net.*;

public class Serveur extends Thread {


protected static final int PORT =45678;
protected ServerSocket ecoute;

Serveur ()
Slide 156 { try
{ ecoute = new ServerSocket(PORT);}
catch (IOException e)
{System.err.println(e.getMessage());
System.exit(1);
}
System.out.println(
"Serveur en ecoute sur le port : "+PORT);
this.start();
}

public void run ()

& %
{ try
J4 Distribution 123

' $

{while (true)
{Socket client=ecoute.accept();
Connexion c = new Connexion (client);}}
catch (IOException e)
{System.err.println(e.getMessage());
Slide 157 System.exit(1);}
}

public static void main (String[] args)


{new Serveur();}

& %
J4 Distribution 124

' $

Partie Connexion

class Connexion extends Thread {


protected Socket client;
protected DataInputStream in;
protected PrintStream out;

public Connexion(Socket client_soc)


{ client=client_soc;
try
{ in=new DataInputStream(client.getInputStream());
out=new PrintStream(client.getOutputStream());}
catch (IOException e)
{try {client.close();}
catch (IOException e1){}
System.err.println(e.getMessage());
Slide 158 return;}
this.start();
}

public void run()


{ try
{ while (true)
{String ligne=in.readLine();
if (ligne.toUpperCase().compareTo("FIN")==0) break;
System.out.println(ligne.toUpperCase());
out.println(ligne.toUpperCase());
out.flush();
}}
catch (IOException e)
{System.out.println("connexion : "+e.toString());}
finally
{try {client.close();} catch (IOException e) {}}

& %
J4 Distribution 125

' $

Partie client
import java.io.*;
import java.net.*;

public class Client {


protected static final int PORT=45678;

public static void main(String[] args)


{
Socket s=null;
if (args.length != 1)
Slide 159
{System.err.println("Usage: java Client <hote>");
System.exit(1);}
try
{ s=new Socket (args[0],PORT);
DataInputStream canalLecture = new DataInputStream(s.getInputStream());
DataInputStream console = new DataInputStream (s.getInputStream());
PrintStream canalEcriture = new PrintStream(s.getOutputStream());
System.out.println("Connexion etablie : "+
s.getInetAddress()+" port : "+s.getPort());
String ligne = new String();
char c;
while (true)
{ System.out.print("?"); System.out.flush();
ligne = "";
while ((c=(char)System.in.read()) != ’\n’) {ligne=ligne+c;}

& %
// ligne=ligne + ’\n’;;

' $

canalEcriture.println(ligne);
canalEcriture.flush();
ligne=canalLecture.readLine();
if (ligne == null)
{System.out.println("Connexion terminee"); break;}
System.out.println("!"+ligne);
}
Slide 160 }
catch (IOException e) {System.err.println(e);}
finally
{ try {if (s != null) s.close();}
catch (IOException e2) {}
}
}
}

& %
J5 Exercices 126

' $

Execution

[chaillou@ippc56]$ java Serveur


Serveur en ecoute sur le port : 45678
ADIEU
MONDE CRUEL

Slide 161 coté client


[chaillou@ippc56]$ java Client ippc56
Connexion etablie : ippc56/134.157.116.56 port : 45678
?adieu
!ADIEU
?monde cruel
!MONDE CRUEL
?fin

& %
Connexion terminee

' $

Communication avancée

Pour établir un nouveau service, il est souvent nécessaire de définir


un “protocole” de communication entre le serveur et les clients.
Slide 162
• HTTP
• FTP
• SQL serveur
...

& %
J5 Objets distribués 127

' $

Plan du 5ème jour


Slide 163
• Objets distibués : RMI, CORBA
• Synthèse

& %

' $

Objets distribués

Possibilités:

Slide 164 clients/serveurs + persistance ⇒ transport d’objets par copie (et


création de nouvelles instances)

Références distantes: références de plusieurs endroits du réseau


au même objet
pour invoquer ses métodes et/ou modifier ses variables d’instances.

& %
J5 Objets distribués 128

' $

Difficultés de mise en œuvre

• transparence référentielle

Slide 165 • Garbage Collector


• typage des objets copiés
• exceptions distantes
le jdk 1.1 offre un mécanisme simple nommé RMI (Remote Method
Invokation) permettant de manipuler des objets distants.

& %

' $

RMI

• objet distant : sur une autre machine virtuelle Java


Slide 166
• garde le même modèle objet
• utilisation d’interface étendant Remote
• passage de paramètre et résultat par copie (Serializable)

& %
J5 Objets distribués 129

' $

Structure générale

client serveur
^ ^
| |
| |
| |
Slide 167
v v
--------------- ---------------
| stub | | skeleton |
-----------------------------------
| couche des references |
-----------------------------------
| couche transport |

& %
-----------------------------------

' $

Serveur

Le serveur s’en trouve compliqué sur les services suivants :


Slide 168
• GC des objets distribués
• réplication d’objets distants
• activation d’objets persistants

& %
J5 Objets distribués 130

' $

Paquetages

Les paquetages utiles sont :


• java.rmi : pour le coté client

Slide 169 • java.rmi.server : pour le coté serveur


• java.rmi.registry : pour l’utilisation d’un service
d’enregistrement et de référentiel des objets serveurs,
• tt java.rmi.dgc : pour le GC distribué.
L’interface d’objets distants étend l’interface Remote en ajoutant les
méthodes désirées qui peuvent déclencher des RemoteException.

& %

' $

Exemple : Points distants

Interface:
import java.rmi.*;
public interface PointRMI extends Remote {

Slide 170
void moveto (int a, int b) throws RemoteException;

void rmoveto (int dx, int dy) throws RemoteException;

void affiche() throws RemoteException;

double distance() throws RemoteException;

& %
}
J5 Objets distribués 131

' $

Implantation d’interfaces distantes

Implantation de l’interface:
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

Slide 171 public class PointD extends UnicastRemoteObject


implements PointRMI {

int x,y;
PointD(int a, int b) throws RemoteException {x=a;y=b;}
PointD() throws RemoteException {x=0;y=0;}

public void moveto (int a, int b)

& %
throws RemoteException

' $

{ x=a; y=b;}

public void rmoveto (int dx, int dy)


throws RemoteException
{ x = x + dx; y = y + dy;}

Slide 172 public void affiche()


throws RemoteException
{ System.out.println("(" + x + "," + y + ")");}

public double distance()


throws RemoteException
{ return Math.sqrt(x*x+y*y);}
}

& %
J5 Objets distribués 132

' $

Compilation

Slide 173 • interface et implantation par : javac


• stubs et skeletons par : rmic de la manière suivante :
rmic PointD qui créera les fichiers PointD_Stub.class et
PointD_Skel.class.

& %

' $

création et enregistrements

Le serveur de points lui va créer des instances de PointD et les


enregistrer (rebind) auprès du démon (rmiregistery) qui gère le
protocole rmi.
import java.rmi.*;
Slide 174 import java.rmi.server.UnicastRemoteObject;

public class Creation {

public static void main (String args[]) {

System.setSecurityManager(new RMISecurityManager());
try {

& %
PointD p0 = new PointD();
J5 Objets distribués 133

' $

PointD p1 = new PointD(3,4);

Naming.rebind("//youpou.lip6.fr/point0",p0);
Naming.rebind("//youpou.lip6.fr/point1",p1);
System.out.println("Objets distribues ’p0’ " +
Slide 175 "et ’p1’ sont enregistres");
}
catch (Exception e) { e.printStackTrace();
}
}
}

& %

' $

Commentaires

• le “security manager” garantit (??) qu’il n’y aura pas


Slide 176 d’opérations illégales.
• l’enregistrement nécessite de nommer chaque instance
La classe Naming permet de nommer des objets pour leur
enregistrement sur le serveur (bind, rebind, unbind, list, lookup).
Compilation classique avec javac.

& %
J5 Objets distribués 134

' $

un client

import java.rmi.*;
public class Client {
public static void main( String argv[]) {
String url0="rmi://youpou.lip6.fr/point0";
String url1="rmi://youpou.lip6.fr/point1";
try {
PointRMI p0 = (PointRMI)Naming.lookup(url0);
PointRMI p1 = (PointRMI)Naming.lookup(url1);
p0.affiche(); p1.affiche();
Slide 177 p0.rmoveto(7,12);
p1.rmoveto(5,6);
p0.affiche(); p1.affiche();
if (p0.distance() == p1.distance())
System.out.println("c’est le hasard");
else
System.out.println("on pouvait parier");
}
catch (Exception e) {
System.err.println("exception : " +
e.getMessage());
e.printStackTrace();

& %
} } }
J5 Objets distribués 135

' $

Exécution

1ère exécution:
(0,0)
(3,4)
(7,12)
Slide 178 (8,10)
on pouvait parier

2ème exécution:
(7,12)
(8,10)
(14,24)
(13,16)
on pouvait parier

& %
J5 Objets distribués 136

' $

Exceptions

Si le démon ne fonctionne plus au moment de l’utilisation d’un objet


distant, on récupère l’exception dans le catch et on affiche les
messages suivants :
Slide 179
exception : Connection refused to host;
...
et si l’objet demandé n’est pas enregistré, la suivante :
exception : point0
java.rmi.NotBoundException: point0

& %

' $

port de communication

Par défaut, le port du service rmi est le 1099. Il est possible de


changer de numéro. Pour cela le serveur d’enregistrement doit être
Slide 180 lancé avec le paramètre du port :

rmiregistry 2000&
et il faut indiquer ce nouveau port aux URL employées :
//youpou.lip6.fr:2000

& %
J5 Exercices 137

' $

CORBA

Common Object Request Broker Architecture : norme (OMG - 1990)


permettant :
Slide 181 • d’être indépendant des langages
• d’avoir des services d’enregistrements plus complets
• de ne pas dépendre d’un constructeur :
de nombreux ORB, y compris gratuit
Pour être indépendant CORBA définit le langage IDL.

& %

' $

IDL

Langage de définition d’interfaces qui permet de décrire les méthodes


et champs visibles des objets.
Accepte l’héritage simple et multiple d’interfaces. Point:
interface Point {
Slide 182 void moveto(in int a, in int b);
void rmoveto(in int dx, in int dy);
void affiche();
double distance();
}
A partir de cette description, le compilateur IDL (fourni avec un
ORB), engendreles stubs et les skeletons pour le serveur et cela pour
différents langages (Smalltalk, C++, Java . . . )
& %
J5 Exercices 138

' $

Client HTTP

Le protocole des serveurs WWW (HTTP) est assez simple : 3


méthodes (HEAD, GET et POST).
1. Ecrire un client qui se connecte à un serveur HTTP et récupère
une page HTML complète;
Slide 183
2. Analyser cette page pour ressortir toutes les URL (HREF="...
")
3. Relancer la recherche de page sur toutes les URL locales à ce
serveur.
4. Conserver les messages d’erreurs associés à certaines pages
5. Afficher toutes les pages accédées avec l’indication d’erreur s’il y

& %
en a.

On utilisera uniquement la méthode GET pour récupérer une page dans


l’arborescence d’un serveur WWW. En général la première page s’appelle
/index.html. Exemple d’un message du client : GET /index.html HTTP/1.0,
le serveur renvoie une première ligne que la page soit valide ou non sous la
forme

HTTP/n code s
où n est le numéro de version du protocole, et code un code indiquant soit
que la page est bonne code=200) ou bien qu’il y a une erreur (dans les 400
et plus).
J5 Exercices 139

' $

Points distants

En reprenant l’exemple sur les points distants, ajouter une méthode


toString retournant la conversion du Point en chaı̂ne.

Slide 184
1. Compiler les interfaces et les classes.
2. Compiler avec rmic pour construire les stubs et skeletons.
3. Compiler le serveur de points.
4. Lancer le sur une machine Solaris.
5. Compiler puis exécuter le client sur une machine Windows NT.

& %

' $

Monde de robots

On cherche à décrire un monde où évolue des robots en utilisant les


différents traits de programmation vus pendant le stage.

Slide 185 Sur un monde découpé en cases se déplacent des robots, il existe
différents types de robots : le robot fixe, le robot fou, le robot poli, le
robot pressé, le robot humanoide, . . .

Il peut avoir différentes sortes de monde : le monde fermé (avec des


bords infranchissables), le monde “chambre à air” où quand l’on sort
d’un coté, on se retrouve de l’autre, . . .

& %
J5 Exercices 140

Description de quelques robots:


• Le robot fou qui se de’place dans une des huits cases libres qui l’entourent
de manière aléatoire.
• Le robot poli qui se déplace tout droit, s’immobilise lorsqu’il y a un
autre robot sur l’une des huits cases qui l’entoure et tourne à droite
lorsqu’il rencontre un des bords du plan.
• Le robot pressé qui ne s’arrête jamais, se déplace tout droit et tourne
à gauche aussitôt qu’il rencontre un obstacle.
• Le robot amical qui choisit un robot et se dirige vers lui jusqu’à ce qu’il
soit sur une case contigue de ce dernier. Il choisit alors un autre robot.
• le robot humanoide qui est controlé par un humain.
Une version graphique manipulant un processus léger par robot est donné
en annexe.

1. Ecrire une version client/serveur, où le monde est le serveur et les


robots les clients. Comme chaque client sera servi par une thread
différentes, il sera là aussi nécessaire de synchroniser les accès aux cases.
Il faudra définir un protocole de communication entre le monde et les
robots.

2. Ecrire une version RMI où un monde est un objet distant enregistré.
Un client graphique (applet) permet d’ajouter des robots au monde
distant et affiche les positions de tous les robots du monde.