Java est un langage de programmation dvelopp par Sun Microsystems en 1995. Il a russi intresser
beaucoup de dveloppeurs travers le monde. Et pourquoi donc ?
La rponse est vaste et forcment sujet polmiques. En voici les principaux avantages :
C'est un langage orient objet driv du C, mais plus simple que le C++.
Il est multi-plateforme : tous vos programmes tourneront sans modification sur toutes les
plateformes o existe Java.
Il est dot en standard d'une riche bibliothque de classes, comprenant la gestion des interfaces
graphiques (fentres, boites de dialogue, contrles, menus, graphisme), la programmation multithreads (multitches), la gestion des exceptions, les accs aux fichiers et au rseau (notamment
Internet),...
Les deux derniers points ont contribu utiliser d'abord ce langage pour dvelopper des applets, qui sont
des applications qui peuvent tre tlcharges via Internet et excutes dans un navigateur sur n'importe
quelle plateforme. Ainsi, une page statique HTML peut s'enrichir de programmes qui lui donneront un
comportement dynamique.
Principe de fonctionnement
Java est langage qui doit tre compil et interprt. Compil et interprt ? En fait dans une premire
phase, vous compilez un programme (un ou plusieurs fichiers source .java) en fichiers .class et le
compilateur gnre un fichier .class. L'ensemble des fichiers .class est ensuite interprt par la Machine
Virtuelle Java (Java Virtual Machine) pour excuter le programme.
Pourquoi ne pas interprter directement le programme Java ?
1. Les fichiers .class contiennent du bytecode, une sorte de code machine Java (comparable au code
machine d'un microprocesseur), qui sera excut beaucoup plus rapidement par l'interprteur.
2. Seuls les fichiers .class sont ncessaires l'excution d'un programme Java. Comme ils
contiennent du code machine, ils ne peuvent tre lus.
3. tant compils, les fichiers .class sont de taille plus petite que le code source Java ; ceci est un
argument important pour transfrer les programmes sur Internet.
4. Chaque fichier .class dcrivant une classe d'objet, une mme classe peut tre utilis par diffrents
programmes, sans que cette classe ne soit duplique dans chacun des programmes.
Structure d'un programme
La structure d'un programme Java est plus simple qu'en C.
1
Float.valueOf(chaine).floatValue()
La conversion d'une chane vers un nombre peut chouer si la chane ne reprsente pas un nombre valide.
Il y a alors gnration d'une erreur fatale appele exception en Java. Cette erreur peut tre gre par la
clause try/catch suivante :
try{
appel de la fonction susceptible de gnrer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
Voici un exemple :
public class test1{
public static void main(String arg[]){
float[][] taux=new float[2][2];
taux[1][0]=0.24F;
taux[1][1]=0.33F;
System.out.println(taux[1].length);
System.out.println(taux[1][1]);
}
}
dans ce flux de caractres les informations qui l'intressent. Le type InputStream ne permet pas de lire d'un
seul coup une ligne de texte. Le type BufferedReader le permet avec la mthode readLine.
Afin de pouvoir lire des lignes de texte tapes au clavier, on cre partir du flux d'entre System.in de type
InputStream, un autre flux d'entre de type BufferedReader cette fois :
BufferedReader IN=new BufferedReader(new InputStreamReader(System.in));
Nous n'expliquerons pas ici les dtails de cette instruction qui fait intervenir la notion de constructions
d'objets. Nous l'utiliserons telle-quelle.
La construction d'un flux peut chouer : une erreur fatale, appele exception en Java, est alors gnre. A
chaque fois qu'une mthode est susceptible de gnrer une exception, le compilateur Java exige qu'elle soit
gre par le programmeur. Aussi, pour crer le flux d'entre prcdent, il faudra en ralit crire :
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
System.err.println("Erreur " +e);
System.exit(1);
}
De nouveau, on ne cherchera pas expliquer ici la gestion des exceptions. Une fois le flux IN prcdent
construit, on peut lire une ligne de texte par l'instruction :
String ligne;
ligne=IN.readLine();
La ligne tape au clavier est range dans la variable ligne et peut ensuite tre exploite par le programme.
Expression arithmtique
Les oprateurs des expressions arithmtiques sont les suivants :
+
addition
soustraction
*
multiplication
/
division : le rsultat est le quotient exact si l'un au moins des oprandes est rel. Si les
deux oprandes sont entiers le rsultat est le quotient entier. Ainsi 5/2 -> 2 et 5.0/2 ->2.5.
%
division : le rsultat est le reste quelque soit la nature des oprandes, le quotient tant lui
entier. C'est donc l'opration modulo.
Il existe diverses fonctions mathmatiques :
double sqrt(double x)
racine carre
double cos(double x)
Cosinus
double sin(double x)
Sinus
double tan(double x)
Tangente
double pow(double x,double y) x la puissance y (x>0)
double exp(double x)
Exponentielle
double log(double x)
Logarithme nprien
double abs(double x)
valeur absolue
etc...
4
Toutes ces fonctions sont dfinies dans une classe Java appele Math. Lorsqu'on les utilise, il faut les
prfixer avec le nom de la classe o elles sont dfinies. Ainsi on crira :
double x, y=4;
x=Math.sqrt(y);
Ici il est ncessaire de changer le type de i ou j en rel sinon la division donnera le quotient entier et non
rel.
Il y a donc transcodage de la valeur de i. Ce transcodage n'a lieu que le temps d'un calcul, la variable i
conservant toujours son type int.
Structure de cas
La syntaxe est la suivante :
switch(expression) {
case v1:
actions1;
break;
case v2:
actions2;
break;
Les bases 19
. .. .. .. .. ..
default: actions_sinon;
}
notes
La valeur de l'expression de contrle, ne peut tre qu'un entier ou un caractre.
l'expression de contrle est entoure de parenthses.
la clause default peut tre absente.
les valeurs vi sont des valeurs possibles de l'expression. Si l'expression a pour valeur vi, les actions
derrire la clause case vi sont excutes.
l'instruction break fait sortir de la structure de cas. Si elle est absente la fin du bloc d'instructions de
la valeur vi, l'excution se poursuit alors avec les instructions de la valeur vi+1.
Structure de rptition
Notes
les 3 arguments du for sont l'intrieur d'une parenthse.
les 3 arguments du for sont spars par des points-virgules.
chaque action du for est termine par un point-virgule.
l'accolade n'est ncessaire que s'il y a plus d'une action.
l'accolade n'est pas suivie de point-virgule.
On boucle tant que la condition est vrifie. La boucle peut ne jamais tre excute.
notes :
la condition est entoure de parenthses.
chaque action est termine par point-virgule.
l'accolade n'est ncessaire que s'il y a plus d'une action.
l'accolade n'est pas suivie de point-virgule.
Structure rpter jusqu' (do while)
La syntaxe est la suivante :
do{
instructions;
}while(condition);
On boucle jusqu' ce que la condition devienne fausse ou tant que la condition est vraie. Ici la boucle est
faite au moins une fois.
notes:
la condition est entoure de parenthses.
chaque action est termine par point-virgule.
l'accolade n'est ncessaire que s'il y a plus d'une action.
l'accolade n'est pas suivie de point-virgule.
Structure pour gnrale (for)
La syntaxe est la suivante :
for(instructions_dpart;condition;instructions_fin_boucle){
instructions;
}
On boucle tant que la condition est vraie (value avant chaque tour de boucle). Instructions_dpart sont
effectues avant d'entrer dans la boucle pour la premire fois. Instructions_fin_boucle sont excutes aprs
chaque tour de boucle.
7
notes:
les 3 arguments du for sont l'intrieur de parenthses.
les 3 arguments du for sont spars par des points-virgules.
chaque action du for est termine par un point-virgule.
l'accolade n'est ncessaire que s'il y a plus d'une action.
l'accolade n'est pas suivie de point-virgule.
les diffrentes instructions dans instructions_depart et instructions_fin_boucle sont spares par des
virgules.
Exemples
Les programmes suivants calculent tous la somme des n premiers nombres entiers.
1 for(i=1, somme=0;i<=n;i=i+1)
somme=somme+a[i];
2 for (i=1, somme=0;i<=n;somme=somme+a[i], i=i+1);
3 i=1;somme=0;
while(i<=n)
{ somme+=i; i++; }
4 i=1; somme=0;
do somme+=i++;
while (i<=n);
ou
public static void main(String[] arg){
Le nom de l'argument arg peut tre quelconque. C'est un tableau de chanes de caractres reprsentant les
arguments de la ligne de commande. Nous y reviendrons un peu plus loin.
Arguments du programme principal
La fonction principale main admet comme paramtres un tableau de chanes : String[]. Ce tableau contient
les arguments de la ligne de commande utilise pour lancer l'application. Ainsi si on lance le programme P
avec la commande :
java P arg0 arg1 argn
import java.io.*;
public class param1{
public static void main(String[] arg){
int i;
System.out.println("Nombre d'arguments="+arg.length);
for (i=0;i<arg.length;i++)
System.out.println("arg["+i+"]="+arg[i]);
}
}
Classes et interfaces
Nous abordons maintenant, par l'exemple, la programmation objet. Un objet est une entit qui contient des
donnes qui dfinissent son tat (on les appelle des attributs ou proprits) et des fonctions (on les
appelle des mthodes). Un objet est cr selon un modle qu'on appelle une classe :
public class
type1 p1; //
type2 p2; //
type3 m3(){
}
type4 m4(){
C1{
proprit p1
proprit p2
// mthode m3
// mthode m4
Si O1 est un objet de type C1, O1.p1 dsigne la proprit p1 de O1 et O1.m1 la mthode m1 de O1.
Dfinition de la classe personne
La dfinition de la classe personne sera la suivante :
import java.io.*;
public class personne{
// attributs
private String prenom;
private String nom;
private int age;
// mthode
public void initialise(String P, String N, int age){
this.prenom=P;
this.nom=N;
this.age=age;
}
// mthode
public void identifie(){
System.out.println(prenom+","+nom+","+age);
}
}
Nous avons ici la dfinition d'une classe, donc un type de donne. Lorsqu'on va crer des variables de ce
type, on les appellera des objets. Une classe est donc un moule partir duquel sont construits des objets.
Les membres ou champs d'une classe peuvent tre des donnes ou des mthodes (fonctions). Ces
champs peuvent avoir l'un des trois attributs suivants :
priv
Un champ priv (private) n'est accessible que par les seules mthodes internes de la
classe
public
Un champ public est accessible par toute fonction dfinie ou non au sein de la classe
protg
Un champ protg (protected) n'est accessible que par les seules mthodes internes de la
classe ou d'un objet driv (voir ultrieurement le concept d'hritage).
La mthode initialise
Quel est le rle de la mthode initialise ? Parce que nom, prenom et age sont des donnes prives de la
classe personne, les instructions
personne p1;
p1.prenom="Jean";
p1.nom="Dupont";
p1.age=30;
sont illgales. Il nous faut initialiser un objet de type personne via une mthode publique. C'est le rle de
la mthode initialise. On crira :
personne p1;
p1.initialise("Jean","Dupont",30);
dclare p1 comme une rfrence un objet de type personne. Cet objet n'existe pas encore et donc p1 n'est
pas initialis. C'est comme si on crivait :
personne p1=null;
est valide.
Le mot cl this
Regardons le code de la mthode initialise
L'instruction this.prenom=P signifie que l'attribut prenom de l'objet courant (this) reoit la valeur P. Le
mot cl this dsigne l'objet courant : celui dans lequel se trouve la mthode excute.
La mthode initialise aurait aussi pu tre crite comme suit :
public void initialise(String P, String N, int age){
prenom=P;
nom=N;
this.age=age;
}
Lorsqu'une mthode d'un objet rfrence un attribut A de cet objet, l'criture this.A est implicite. On doit
l'utiliser explicitement lorsqu'il y a conflit d'identificateurs. C'est le cas de l'instruction :
this.age=age;
o age dsigne un attribut de l'objet courant ainsi que le paramtre age reu par la mthode. Il faut alors
lever l'ambigut en dsignant l'attribut age par this.age.
10
Un programme de test
Voici un programme de test :
public class test1{
public static void main(String arg[]){
personne p1=new personne();
p1.initialise("Jean","Dupont",30);
Classes et interfaces 33
p1.identifie();
}
}
La classe personne est dfinie dans le fichier source personne.java et est compile :
E:\data\serge\JAVA\BASES\OBJETS\2>javac personne.java
E:\data\serge\JAVA\BASES\OBJETS\2>dir
10/06/2002 09:21 473 personne.java
10/06/2002 09:22 835 personne.class
10/06/2002 09:23 165 test1.java
On peut s'tonner que le programme test1.java n'importe pas la classe personne avec une instruction :
import personne; Lorsque le compilateur rencontre dans le code source une rfrence de classe non dfinie
dans ce mme fichier source, il recherche la classe divers endroits :
dans les paquetages imports par les instructions import
dans le rpertoire partir duquel le compilateur a t lanc
Nous pouvons maintenant excuter le fichier test1.class :
E:\data\serge\JAVA\BASES\OBJETS\2>java test1
Jean,Dupont,30
On a maintenant deux mthodes portant le nom initialise : c'est lgal tant qu'elles admettent des
paramtres diffrents. C'est le cas ici. Le paramtre est maintenant une rfrence P une personne. Les
attributs de la personne P sont alors affects l'objet courant (this).
Voici un test de la nouvelle classe personne :
11
// import personne;
import java.io.*;
public class test1{
public static void main(String arg[]){
personne p1=new personne();
p1.initialise("Jean","Dupont",30);
System.out.print("p1=");
p1.identifie();
personne p2=new personne();
p2.initialise(p1);
System.out.print("p2=");
p2.identifie();
}
}
et ses rsultats :
p1=Jean,Dupont,30
p2=Jean,Dupont,30
12
Nos deux constructeurs se contentent de faire appel aux mthodes initialise correspondantes. On rappelle
que lorsque dans un constructeur, on trouve la notation initialise(P) par exemple, le compilateur traduit
par this.initialise(P). Dans le constructeur, la mthode initialise est donc appele pour travailler sur l'objet
rfrenc par this, c'est dire l'objet courant, celui qui est en cours de construction.
Voici un programme de test :
// import personne;
import java.io.*;
public class test1{
public static void main(String arg[]){
personne p1=new personne("Jean","Dupont",30);
System.out.print("p1=");
p1.identifie();
personne p2=new personne(p1);
System.out.print("p2=");
p2.identifie();
}
}
p1 rfrence l'objet personne("Jean","Dupont",30) mais n'est pas l'objet lui-mme. En C, on dirait que
c'est un pointeur, c.a.d. l'adresse de l'objet cr. Si on crit ensuite :
p1=null
13
Ce n'est pas l'objet personne("Jean","Dupont",30) qui est modifi, c'est la rfrence p1 qui change de
valeur. L'objet personne("Jean","Dupont",30) sera "perdu" s'il n'est rfrenc par aucune autre variable.
Lorsqu'on crit :
personne p2=p1;
on initialise le pointeur p2 : il "pointe" sur le mme objet (il dsigne le mme objet) que le pointeur p1.
Ainsi si on modifie l'objet "point" (ou rfrenc) par p1, on modifie celui rfrenc par p2.
Lorsqu'on crit :
personne p3=new personne(p1);
il y a cration d'un nouvel objet, copie de l'objet rfrenc par p1. Ce nouvel objet sera rfrenc par p3.
Si on modifie l'objet "point" (ou rfrenc) par p1, on ne modifie en rien celui rfrenc par p3. C'est ce
que montrent les rsultats obtenus.
Un tableau de personnes
Un objet est une donne comme une autre et ce titre plusieurs objets peuvent tre rassembls dans un
tableau :
// import personne;
public class test1{
public static void main(String arg[]){
personne[] amis=new personne[3];
System.out.println("----------------");
amis[0]=new personne("Jean","Dupont",30);
amis[1]=new personne("Sylvie","Vartan",52);
amis[2]=new personne("Neil","Armstrong",66);
int i;
for(i=0;i<amis.length;i++)
amis[i].identifie();
}
}
L'instruction personne[] amis=new personne[3]; cre un tableau de 3 lments de type personne. Ces 3
lments sont initialiss ici avec la valeur null, c.a.d. qu'ils ne rfrencent aucun objet. De nouveau, par
abus de langage, on parle de tableau d'objets alors que ce n'est qu'un tableau de rfrences d'objets. La
cration du tableau d'objets, tableau qui est un objet lui-mme (prsence de new) ne cre donc en soi
aucun objet du type de ses lments : il faut le faire ensuite.
On obtient les rsultats suivants :
---------------Classes et interfaces 41
Constructeur personne(String, String, int)
Constructeur personne(String, String, int)
Constructeur personne(String, String, int)
Jean,Dupont,30
Sylvie,Vartan,52
Neil,Armstrong,66
14
Le mot-cl this est utile lorsquon a besoin de se rfrer l'instance de l'objet dans laquelle on se trouve.
15
La mthode identifie a t lgrement modifie pour rendre une chane de caractres identifiant la
personne et porte maintenant le nom identite. Ici la classe enseignant rajoute aux mthodes et attributs de
la classe personne :
un attribut section qui est le n de section auquel appartient l'enseignant dans le corps des enseignants
(une section par discipline en gros)
un nouveau constructeur permettant d'initialiser tous les attributs d'un enseignant
Construction d'un objet enseignant
Le constructeur de la classe enseignant est le suivant :
// constructeur
public enseignant(String P, String N, int age,int section){
super(P,N,age);
this.section=section;
}
L'instruction super(P,N,age) est un appel au constructeur de la classe parent, ici la classe personne. On
sait que ce constructeur initialise les champs prenom, nom et age de l'objet personne contenu l'intrieur
de l'objet tudiant. Cela parat bien compliqu et on pourrait prfrer crire :
// constructeur
public enseignant(String P, String N, int age,int section){
this.prenom=P;
this.nom=N
this.age=age
this.section=section;
}
C'est impossible. La classe personne a dclar privs (private) ses trois champs prenom, nom et age. Seuls
des objets de la mme classe ont un accs direct ces champs. Tous les autres objets, y compris des objets
fils comme ici, doivent passer par des mthodes publiques pour y avoir accs. Cela aurait t diffrent si la
classe personne avait dclar protgs (protected) les trois champs : elle autorisait alors des classes
drives avoir un accs direct aux trois champs. Dans notre exemple, utiliser le constructeur de la classe
parent tait donc la bonne solution et c'est la mthode habituelle : lors de la construction d'un objet fils, on
appelle d'abord le constructeur de l'objet parent puis on complte les initialisations propres cette fois
l'objet fils (section dans notre exemple).
Tentons un premier programme :
// import personne;
// import enseignant;
public class test1{
public static void main(String arg[]){
System.out.println(new enseignant("Jean","Dupont",30,27).identite());
}
}
Ce programme ce contente de crer un objet enseignant (new) et de l'identifier. La classe enseignant n'a
pas de mthode identit mais sa classe parent en a une qui de plus est publique : elle devient par hritage
une mthode publique de la classe enseignant.
16
Les fichiers source des classes sont rassembls dans un mme rpertoire puis compils :
E:\data\serge\JAVA\BASES\OBJETS\4>dir
10/06/2002 10:00
765 personne.java
10/06/2002 10:00
212 enseignant.java
10/06/2002 10:01
192 test1.java
E:\data\serge\JAVA\BASES\OBJETS\4>javac *.java
E:\data\serge\JAVA\BASES\OBJETS\4>dir
10/06/2002 10:00
765 personne.java
10/06/2002 10:00
212 enseignant.java
10/06/2002 10:01
192 test1.java
10/06/2002 10:02
316 enseignant.class
10/06/2002 10:02
1 146 personne.class
10/06/2002 10:02
550 test1.class
La mthode identite de la classe enseignant s'appuie sur la mthode identite de sa classe mre
(super.identite) pour afficher sa partie "personne" puis complte avec le champ section qui est propre la
classe enseignant.
La classe enseignant dispose maintenant deux mthodes identite :
celle hrite de la classe parent personne
la sienne propre
Si E est un ojet enseignant, E.identite dsigne la mthode identite de la classe enseignant. On dit que la
mthode identite de la classe mre est "surcharge" par la mthode identite de la classe fille. De faon
gnrale, si O est un objet et M une mthode, pour excuter la mthode O.M, le systme cherche une
mthode M dans l'ordre suivant :
dans la classe de l'objet O
dans sa classe mre s'il en a une
dans la classe mre de sa classe mre si elle existe
etc
L'hritage permet donc de surcharger dans la classe fille des mthodes de mme nom dans la classe mre.
C'est ce qui permet d'adapter la classe fille ses propres besoins.
17
Les interfaces
Une interface est une catgorie un peu spciale de classe abstract, dont le corps ne contient que la
dclaration de constantes et de mthodes.
Une classe ne peut hriter que d'une super classe, mais par contre peut implmenter plusieurs
interfaces.
Une classe doit implmenter toutes les mthodes de linterface implmente.
Une interface vide (comme l'interface Cloneable) permet de crer une catgorie de classes :
chaque classe implmentant ce type d'interface appartient telle ou telle catgorie. Pour tester si
la classe d'un objet appartient une catgorie, il suffit d'utiliser l'oprateur instanceof avec le nom
de l'interface.
Une interface peut servir aussi pour dclarer un ensemble de constantes, qui seront utilises dans
des classes sans lien d'hritage entre elles,
18
int
19
champs[0]=[l'oiseau]
champs[1]=[vole]
champs[2]=[au-dessus]
champs[3]=[des]
champs[4]=[nuages]
(" abc ").trim()=[abc]
La classe Vector
Un vecteur est un tableau dynamique dont les lments sont des rfrences d'objets. C'est donc un tableau
d'objets dont la taille peut varier au fil du temps ce qui n'est pas possible avec les tableaux statiques qu'on
a rencontrs jusqu'ici. Voici certains champs, constructeurs ou mthodes de cette classe :
public Vector()
public final int size()
public final void addElement(Object obj)
public final Object elementAt(int index)
public final Enumeration elements()
public final Object firstElement()
public final Object lastElement()
public final boolean isEmpty()
public final void removeElementAt(int index)
public final void removeAllElements()
public final String toString()
Compilons ce programme :
E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>dir
20
Par la suite, nous ne rpterons plus le processus de compilation et d'excution des programmes de tests. Il
suffit de reproduire ce qui a t fait ci-dessus.
La classe ArrayList
La classe ArrayList est analogue la classe Vector. Elle n'en diffre essentiellement que lorsquelle est
utilise simultanment par plusieurs threads d'excution. Les mthodes de synchronisation des threads
pour l'accs un Vector ou un ArrayList diffrent. En dehors de ce cas, on peut utiliser indiffremment
l'un ou l'autre. Voici certains champs, constructeurs ou mthodesde cette classe :
ArrayList()
int size()
void add(Object obj)
void add(int index,Object obj)
Object get(int index)
boolean isEmpty()
void remove(int index)
void clear()
Object[] toArray()
String toString()
21
// le polymorphisme
personne p2=(personne)en;
System.out.println("p2="+p2);
personne p3=(personne)et;
System.out.println("p3="+p3);
// un vecteur
ArrayList personnes=new ArrayList();
personnes.add(p);personnes.add(en);personnes.add(et);
System.out.println("Nombre de personnes = "+personnes.size());
for(int i=0;i<personnes.size();i++){
p2=(personne) personnes.get(i);
System.out.println("personnes["+i+"]="+p2);
}
} // fin main
}// fin classe
La classe FileWriter offre un certain nombre de mthodes pour crire dans un fichier, mthodes hrites
de la classe Writer. Pour crire dans un fichier texte, il est prfrable d'utiliser la classe PrintWriter dont
les constructeurs souvent utiliss sont les suivants :
PrintWriter(Writer out)
PrintWriter(Writer out, Boolean autoflush)
22
try{
fic=new PrintWriter(new FileWriter("out"));
} catch (Exception e){
Erreur(e,1);
}
// criture dans le fichier
try{
fic.println("Jean,Dupont,27");
fic.println("Pauline,Garcia,24");
fic.println("Gilles,Dumond,56");
} catch (Exception e){
Erreur(e,3);
}
// fermeture du fichier
try{
fic.close();
} catch (Exception e){
Erreur(e,2);
}
}// fin main
private static void Erreur(Exception e, int code){
System.err.println("Erreur : "+e);
System.exit(code);
}//Erreur
}//classe
Lire
Pour lire le contenu d'un fichier, il faut disposer d'un flux de lecture associ au fichier. On peut utiliser
pour cela la classe FileReader et le constructeur suivant :
FileReader(String nomFichier)
La classe FileReader possde un certain nombre de mthodes pour lire dans un fichier, mthodes hrites
de la classe Reader. Pour lire des lignes de texte dans un fichier texte, il est prfrable d'utiliser la classe
BufferedReader avec le constructeur suivant :
BufferedReader(Reader in)
lit un caractre
lit une ligne de texte
lit taille caractres dans le fichier et les met dans le
tableau buffer partir de la position offset.
ferme le flux de lecture
23
import java.io.*;
public class lire{
public static void main(String[] arg){
personne p=null;
// ouverture du fichier
BufferedReader IN=null;
try{
IN=new BufferedReader(new FileReader("out"));
} catch (Exception e){
Erreur(e,1);
}
// donnes
String ligne=null;
String[] champs=null;
String prenom=null;
String nom=null;
int age=0;
// gestion des ventuelles erreurs
try{
while((ligne=IN.readLine())!=null){
champs=ligne.split(",");
prenom=champs[0];
nom=champs[1];
age=Integer.parseInt(champs[2]);
System.out.println(""+new personne(prenom,nom,age));
}// fin while
} catch (Exception e){
Erreur(e,2);
}
// fermeture fichier
try{
IN.close();
} catch (Exception e){
Erreur(e,3);
}
}// fin main
// Erreur
public static void Erreur(Exception e, int code){
System.err.println("Erreur : "+e);
System.exit(code);
}
}// fin classe
24
La mthode sauveAttributs reoit en unique paramtre le flux PrintWriter dans lequel elle doit crire. Un
programme de test pourrait tre le suivant :
// imports
import java.io.*;
// import personne;
public class sauver{
public static void main(String[] arg){
// ouverture du fichier
PrintWriter fic=null;
try{
fic=new PrintWriter(new FileWriter("out"));
} catch (Exception e){
Erreur(e,1);
}
// criture dans le fichier
try{
new personne("Jean","Dupont",27).sauveAttributs(fic);
new personne("Pauline","Garcia",24).sauveAttributs(fic);
new personne("Gilles","Dumond",56).sauveAttributs(fic);
} catch (Exception e){
Erreur(e,3);
}
// fermeture du fichier
try{
fic.close();
} catch (Exception e){
Erreur(e,2);
}
}// fin main
// Erreur
private static void Erreur(Exception e, int code){
System.err.println("Erreur : "+e);
System.exit(code);
}//Erreur
}//classe
25
3\sauveAttributs>javac sauver.java
3\sauveAttributs>dir
3\sauveAttributs>java sauver
3\sauveAttributs>dir
3\sauveAttributs>more out
TTT readTTT()
long length()
long getFilePointer()
La classe article
Tous les exemples qui vont suivre utiliseront la classe article suivante :
// la structure article
private static class article{
// on dfinit la structure
public String code;
public String nom;
public double prix;
public int stockActuel;
public int stockMinimum;
}//classe article
26
crire un enregistrement
27
C'est le programme suivant qui nous permet de vrifier que l'excution s'est correctement faite.
Lire un enregistrement
// classes importes
import java.io.*;
public class test2{
// teste l'criture d'une structure (au sens du C) dans un fichier binaire
// la structure article
private static class article{
// on dfinit la structure
public String code;
public String nom;
public double prix;
public int stockActuel;
public int stockMinimum;
}//classe article
public static void main(String arg[]){
// on dfinit le fichier binaire dans lequel seront rangs les articles
RandomAccessFile fic=null;
// on ouvre le fichier en lecture
try{
fic=new RandomAccessFile("data","r");
} catch (Exception E){
erreur("Impossible d'ouvrir le fichier data",1);
}//try-catch
// on lit l'article unique du fichier
article art=new article();
try{
lire(fic,art);
} catch (IOException E){
erreur("Erreur lors de la lecture de l'enregistrement",2);
}//try-catch
// on affiche l'enregistrement lu
affiche(art);
// c'est fini
try{
fic.close();
} catch (Exception E){
erreur("Impossible de fermer le fichier data",2);
}//try-catch
}// fin main
// mthode de lecture
public static void lire(RandomAccessFile fic, article art) throws IOException{
// lecture code
art.code="";
for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
// nom
art.nom="";
for(int i=0;i<20;i++) art.nom+=(char)fic.readByte();
art.nom=art.nom.trim();
// prix
art.prix=fic.readDouble();
// stocks
art.stockActuel=fic.readInt();
art.stockMinimum=fic.readInt();
}// fin crire
// ---------------------affiche
public static void affiche(article art){
System.out.println("code : "+art.code);
System.out.println("nom : "+art.nom);
System.out.println("prix : "+art.prix);
System.out.println("Stock actuel : "+art.stockActuel);
System.out.println("Stock minimum : "+art.stockMinimum);
}// fin affiche
// ------------------------erreur
public static void erreur(String msg, int exitCode){
System.err.println(msg);
28
System.exit(exitCode);
}// fin erreur
}// fin class
29
Interfaces graphiques
Nous voyons tout d'abord quelles sont les classes de base qui nous permettent de construire une interface
graphique. Il y a deux groupes principaux de classes (librairies) utilises pour crer des fentres en Java :
AWT et Swing.
Au dbut, seule la librairie AWT (Abstract Window Toolkit) tait disponible pour travailler avec du
graphique. Cette librairie est un simple ensemble de classes telles que Button (bouton), TextField (champ
textuel), Label (libell) et autres. Peu aprs, une autre librairie, plus volue, apparut : Swing. Elle inclut
aussi les boutons, les champs textuels et d'autres contrles. Le nom des composants Swing commence par
la lettre J, par exemple JButton, JTextField, JLabel, etc.
Une fentre ou un cadre (frame) qui peut tre cr en utilisant la classe JFrame.
Un panneau (panel) ou un carreau (pane) contenant tous les boutons, champs textuels, libells et
autres composants. Les panneaux sont crs l'aide de la classe JPanel.
Les contrles graphiques tels que les boutons (JButton), les champs textuels (JTextField), les
listes (JList)...
Les gestionnaires de disposition (layout managers) qui aident organiser tous ces boutons et
champs dans un panneau.
Habituellement, un programme cre une instance de JPanel et lui affecte un gestionnaire de disposition.
Ensuite, il peut crer des contrles graphiques et les ajouter au panneau. Enfin, il ajoute le panneau au
cadre, fixe les dimensions du cadre et le rend visible.
30
La classe de base JFrame dfinit une fentre de base avec des boutons de fermeture,
agrandissement/rduction, une taille ajustable, etc ... et gre les vnements sur ces objets graphiques. Ici
nous spcialisons la classe de base en lui fixant un titre et ses largeur (300 pixels) et hauteur (100 pixels).
Ceci est fait dans son constructeur :
// le constructeur
public form1() {
// titre de la fentre
this.setTitle("Mon premier formulaire");
// dimensions de la fentre
this.setSize(new Dimension(300,100));
}//constructeur
Le titre de la fentre est fixe par la mthode setTitle et ses dimensions par la mthode setSize. Cette
mthode accepte pour paramtre un objet Dimension(largeur,hauteur) o largeur et hauteur sont les
largeur et hauteur de la fentre exprimes en pixels.
La mthode main lance l'application graphique de la faon suivante :
new form1().setVisible(true);
Un formulaire de type form1 est alors cr (new form1()) et affich (setVisible(true)), puis l'application se
met l'coute des vnements qui se produisent sur le formulaire (clics, dplacements de souris, ...) et fait
excuter ceux que le formulaire gre. Ici, notre formulaire ne gre pas d'autres vnements que ceux grs
par la classe de base JFrame (clics sur boutons fermeture, agrandissement/rduction, changement de taille
de la fentre, dplacement de la fentre, ...).
Lorsqu'on teste ce programme en le lanant partir d'une fentre Dos par :
java form1
pour excuter le fichier form1.class, on constate que lorsqu'on ferme la fentre qui a t affiche, on ne
"rcupre pas la main" dans la fentre Dos, comme si le programme n'tait pas termin. C'est
effectivement le cas. L'excution du programme se fait de la faon suivante :
- au dpart, un premier thread d'excution est lanc pour excuter la mthode main
- lorsque celle-ci cre le formulaire et l'affiche, un second thread est cr pour grer spcifiquement les
vnements lis au formulaire
- aprs cette cration et dans notre exemple, le thread de la mthode main se termine et seul reste alors
le thread d'excution de l'interface graphique.
- lorsqu'on ferme la fentre, celle-ci disparat mais n'interrompt pas le thread dans lequel elle
s'excutait
- on est oblig pour l'instant d'arrter ce thread en faisant Ctrl-C dans la fentre Dos d'o a t lance
l'excution du programme.
Vrifions l'existence de deux threads spars, l'un dans lequel s'excute la mthode main, l'autre dans
lequel s'excute la fentre graphique :
// classes importes
import javax.swing.*;
import java.awt.*;
import java.io.*;
// la classe formulaire
public class form1 extends JFrame {
// le constructeur
public form1() {
// titre de la fentre
this.setTitle("Mon premier formulaire");
// dimensions de la fentre
this.setSize(new Dimension(300,100));
}//constructeur
31
// fonction de test
public static void main(String[] args) {
// suivi
System.out.println("Dbut du thread main");
// on affiche le formulaire
new form1().setVisible(true);
// suivi
System.out.println("Fin du thread main");
}//main
}//classe
la cration d'une calculatrice simple capable d'ajouter deux nombres et d'afficher le rsultat.
import javax.swing.*;
import java.awt.FlowLayout;
public class CalculatriceSimple {
public static void main(String[] args) {
// Cre un panneau
JPanel contenuFentre = new JPanel();
// Affecte un gestionnaire de disposition ce panneau
FlowLayout disposition = new FlowLayout();
contenuFentre.setLayout(disposition);
// Cre les contrles en mmoire
JLabel label1 = new JLabel("Nombre 1 :");
JTextField entre1 = new JTextField(10);
JLabel label2 = new JLabel("Nombre 2 :");
JTextField entre2 = new JTextField(10);
JLabel label3 = new JLabel("Somme :");
JTextField rsultat = new JTextField(10);
JButton lancer = new JButton("Ajouter");
// Ajoute les contrles au panneau
contenuFentre.add(label1);
contenuFentre.add(entre1);
contenuFentre.add(label2);
contenuFentre.add(entre2);
contenuFentre.add(label3);
contenuFentre.add(rsultat);
contenuFentre.add(lancer);
// Cre le cadre et y ajoute le panneau
JFrame cadre = new JFrame("Ma premire calculatrice");
cadre.setContentPane(contenuFentre);
// Positionne les dimensions et rend la fentre visible
cadre.setSize(400,100);
cadre.setVisible(true);
}
}
Pour utiliser un gestionnaire de disposition, un programme doit l'instancier puis affecter cet objet un
conteneur (container), par exemple un panneau, comme dans la classe CalculatriceSimple.
FlowLayout
FlowLayout disposition = new FlowLayout();
this.setLayoutManager(disposition);
GridLayout
GridLayout disposition = new GridLayout(4,2);
Tu peux aussi fixer un espace, horizontal ou vertical, entre les cellules, par exemple cinq pixels (les
images sur l'cran de l'ordinateur sont constitues de minuscules points appels pixels).
GridLayout disposition = new GridLayout(4,2,5,5);
BorderLayout
La classe java.awt.BorderLayout partage la fentre en cinq zones : South (sud), West (ouest), North
(nord), East (est) et Center (centre). La rgion North est toujours en haut de la fentre, la rgion South en
bas ; la rgion West est gauche et la rgion East droite.
Par exemple, dans la calculatrice de la page suivante, le champ textuel qui affiche les nombres est situ
dans la zone North.
Voici comment crer une disposition BorderLayout et y placer un champ textuel :
BorderLayout disposition = new BorderLayout();
this.setLayoutManager(disposition);
JTextField affichageTexte = new JTextField(20);
this.add("North", affichageTexte);
BoxLayout
La classe javax.swing.BoxLayout permet de disposer de multiples composants soit horizontalement (selon
l'axe des X) ou verticalement (selon l'axe des Y). Contrairement au gestionnaire FlowLayout, les contrles
ne changent pas de ligne quand la fentre est retaille. Avec BoxLayout, les contrles peuvent avoir des
tailles diffrentes (ce qui n'est pas possible avec GridLayout).
Les deux lignes de code suivantes mettent en place une prsentation de type BoxLayout avec un
alignement vertical dans un JPanel.
JPanel panneauChiffres = new JPanel();
setLayout(new BoxLayout(panneauChiffres, BoxLayout.Y_AXIS));
Pour rendre ce code plus compact, je ne dclare pas de variable pour stocker une rfrence l'objet
BoxLayout ; je cre plutt une instance de cet objet et la passe immdiatement en argument la mthode
setLayout().
33
34
Le code doit affecter les coordonnes du coin suprieur gauche, la largeur et la hauteur de chaque
composant de la fentre. Cet exemple montre comment on peut donner un bouton une largeur de 40
pixels, une hauteur de 20 pixels et le placer 100 pixels droite et 200 pixels au-dessous du coin
suprieur gauche de la fentre :
JButton monBouton = new JButton("Nouvelle partie");
monBouton.setBounds(100, 200, 40, 20);
o
o
o
o
o
o
o
JList
JTabbedPane
JTable
JToolTip
JTree
JViewPort
ImageIcon
On peut aussi crer des menus (JMenu et JPopupMenu), des fentres la demande (popup), des cadres
imbriqus dans d'autres cadres (JInternalFrame) et utiliser les fentres standard de manipulation
d'informations : JFileChooser (choix de fichier), JColorChooser (choix de couleur) et JOptionPane (choix
d'option).
Java est accompagn d'une excellente application de dmonstration qui prsente tous les composants
Swing disponibles en action. Elle se trouve dans le rpertoire demo\jfc\SwingSet2 du rpertoire
d'installation de J2SDK. Ouvre simplement le fichier SwingSet2.html,
L'un des outils gratuits de conception d'interface utilisateur graphique (Graphic User Interface ou GUI),
permettant de crer facilement des composants Swing est jigloo.
Rcepteur d'vnements
Chaque composant d'une fentre peut traiter un certain nombre d'vnements ou, comme on dit, tre
l'coute (listen) de ces vnements,
Pour ragir aux actions de l'utilisateur il faut associer un gestionnaire d'vnements aux composants.
Le gestionnaire d'vnements qui gre le clic sur le bouton est l'interface ActionListener.
Celle-ci ne dfinit qu'une mthode :
void actionPerformed(ActionEvent e)
on va essayer un exemple qui affiche une bote de message (message box) depuis la mthode
actionPerformed().
on peux afficher n'importe quel message en utilisant la classe JOptionPane et sa mthode
showConfirmDialog().
Il y a diffrentes version de la mthode showConfirmDialog(). Nous allons utiliser celle qui prend quatre
arguments. Dans le code cidessous, le mot-cl null signifie que cette bote de message n'a pas de fentre
mre, le deuxime argument contient le message, le troisime le titre de la bote de message et le
quatrime te permet de choisir le(s) bouton(s) inclure dans la bote (PLAIN_MESSAGE signifie que
seul un bouton OK est affich).
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;
public class MoteurCalcul implements ActionListener {
public void actionPerformed(ActionEvent vnement) {
JOptionPane.showConfirmDialog(null,
"Quelque chose s'est produit...",
"Juste un test",
JOptionPane.PLAIN_MESSAGE);
}
}
On sait bien que, dans notre fentre, seuls les boutons peuvent tre l'origine de l'vnement d'action.
alors on va faire une conversion de type explicite (casting) de l'Object retourn en un JButton,
JButton boutonCliqu = (JButton) vnement.getSource();
Si les vnements d'une fentre proviennent non seulement des boutons, mais aussi d'autres composants,
Nous ne voulons pas convertir n'importe quel objet en JButton, on doit utiliser l'oprateur Java spcial
instanceof pour effectuer la conversion de type approprie.
L'exemple suivant vrifie d'abord quel type d'objet est l'origine de l'vnement, puis effectue une
conversion de type, soit en JButton soit en JTextField :
public void actionPerformed(ActionEvent vnement) {
JTextField monChampAffichage = null;
JButton boutonCliqu = null;
Object sourceEvnement = vnement.getSource();
if (sourceEvnement instanceof JButton) {
boutonCliqu = (JButton) sourceEvnement;
}
else if (sourceEvnement instanceof JTextField) {
monChampAffichage = (JTextField) sourceEvnement;
}
}
Fin de la calculatrice
Intressons-nous quelques rgles (un algorithme) concernant la faon dont notre calculatrice doit
fonctionner :
1. L'utilisateur entre tous les chiffres du premier nombre.
2. Si l'utilisateur tape l'un des boutons d'action +, -, / ou *, alors stocker le premier nombre et l'action
slectionne dans des variables membres, puis effacer le nombre du champ textuel.
3. L'utilisateur entre un deuxime nombre et appuie sur le bouton gale.
4. Convertir la valeur de type String du champ textuel dans le type numrique double pour pouvoir
stocker de grands nombres dcimaux. Excuter l'action slectionne en utilisant cette valeur et le
nombre stock dans la variable l'tape 2.
5. Afficher le rsultat de l'tape 4 dans le champ textuel et stocker cette valeur dans la variable
utilise l'tape 2.
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.text.NumberFormat;
import java.text.ParsePosition;
import javax.swing.JButton;
public class MoteurCalcul implements ActionListener {
Calculatrice parent; // une rfrence la Calculatrice
char actionSlectionne = ' '; // +, -, /, ou *
double rsultatCourant = 0;
NumberFormat formatNombres = NumberFormat.getInstance();
// un objet capable de lire et prsenter les nombres
// Le constructeur stocke la rfrence la fentre
// Calculatrice dans la variable membre parent
MoteurCalcul(Calculatrice parent) {
this.parent = parent;
}
public void actionPerformed(ActionEvent vnement) {
// Retrouve la source de l'action
JButton boutonCliqu = (JButton) vnement.getSource();
String texteChampAffichage =
parent.champAffichage.getText();
double valeurAffiche = 0;
// Retrouve le nombre prsent dans le champ texte
37
38
39
bouton6.addActionListener(moteurCalcul);
bouton7.addActionListener(moteurCalcul);
bouton8.addActionListener(moteurCalcul);
bouton9.addActionListener(moteurCalcul);
boutonVirgule.addActionListener(moteurCalcul);
boutonPlus.addActionListener(moteurCalcul);
boutonMoins.addActionListener(moteurCalcul);
boutonDiviser.addActionListener(moteurCalcul);
boutonMultiplier.addActionListener(moteurCalcul);
boutonEgale.addActionListener(moteurCalcul);
}
public static void main(String[] args) {
// Instancie la classe Calculatrice
Calculatrice calc = new Calculatrice();
}
}
Les tableaux suivants donnent une liste de quelques gestionnaires d'vnements et les vnements
auxquels ils sont lis.
Gestionnaire
ActionListener
Composant(s)
Mthode d'enregistrement
JButton , JCheckbox, public void addActionListener(ActionListener)
JButtonRadio,
JMenuItem, JTextField
ItemListener
InputMethodListener
JComboBox, JList
JTextField, JTextArea
CaretListener
JTextField, JTextArea
AdjustmentListener
JScrollBar
MouseMotionListener
WindowListener
MouseListener
FocusListener
KeyListener
40
JFrame
vnement
Composant
JButton
JCheckbox
JCheckboxMenuItem
JComboBox
Container
JComponent
JFrame
JList
JMenuItem
JPanel
JScrollPane
JScrollBar
JTextComponent
JTextArea
JTextField
Tous les composants, sauf ceux du type TextXXX, tant drivs de la classe JComponent, possdent
galement les mthodes associes cette classe.
Les mthodes des gestionnaires d'vnements
Le tableau suivant liste les mthodes que doivent implmenter les diffrents gestionnaires d'vnements.
Interface
ActionListener
AdjustmentListener
ComponentListener
ContainerListener
FocusListener
ItemListener
KeyListener
MouseListener
MouseMotionListener
TextListener
InputmethodListener
CaretLisetner
WindowListener
41
Mthodes
public void actionPerformed(ActionEvent)
public void adjustmentValueChanged(AdjustmentEvent)
public void componentHidden(ComponentEvent)
public void componentMoved(ComponentEvent)
public void componentResized(ComponentEvent)
public void componentShown(ComponentEvent)
public void componentAdded(ContainerEvent)
public void componentRemoved(ContainerEvent)
public void focusGained(FocusEvent)
public void focusLost(FocusEvent)
public void itemStateChanged(ItemEvent)
public void keyPressed(KeyEvent)
public void keyReleased(KeyEvent)
public void keyTyped(KeyEvent)
public void mouseClicked(MouseEvent)
public void mouseEntered(MouseEvent)
public void mouseExited(MouseEvent)
public void mousePressed(MouseEvent)
public void mouseReleased(MouseEvent)
public void mouseDragged(MouseEvent)
public void mouseMoved(MouseEvent)
public void textValueChanged(TextEvent)
public void InputMethodTextChanged(InputMethodEvent)
public void caretPositionChanged(InputMethodEvent)
public void caretUpdate(CaretEvent)
public void windowActivated(WindowEvent)
public void windowClosed(WindowEvent)
public void windowClosing(WindowEvent)
public void windowDeactivated(WindowEvent)
public void windowDeiconified(WindowEvent)
public void windowIconified(WindowEvent)
public void windowOpened(WindowEvent)
et crire :
public class gestionnaireSouris implements MouseListener{
// on crit les 5 mthodes de l'interface MouseListener
// mouseClicked, ..., mouseReleased)
}// fin classe
Comme on ne souhaite grer que les clics de souris, il est cependant prfrable d'crire :
public class gestionnaireSouris extends MouseAdapter{
// on crit une seule mthode, celle qui gre les clics de souris
public void mouseClicked(MouseEvent evt){
}
}// fin classe
Le tableau suivant donne les classes adapteurs des diffrents gestionnaires d'vnements :
Gestionnaire d'vnements
ComponentListener
ContainerListener
FocusListener
KeyListener
MouseListener
MouseMotionListener
WindowListener
42
Adaptateur
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter
Thread(Runnable object)
cre une rfrence sur une tche asynchrone. Celle-ci est encore inactive.
La tche cre doit possder la mthode run : ce sera le plus souvent une
classe drive de Thread qui sera utilise.
idem mais c'est l'objet Runnable pass en paramtre qui implmente la
mthode run.
Regardons une premire application mettant en vidence l'existence d'un thread principal d'excution,
celui dans lequel s'excute la fonction main d'une classe :
// utilisation de threads
import java.io.*;
import java.util.*;
public class thread1{
public static void main(String[] arg)throws Exception {
// init thread courant
Thread main=Thread.currentThread();
// affichage
System.out.println("Thread courant : " + main.getName());
// on change le nom
main.setName("myMainThread");
// vrification
System.out.println("Thread courant : " + main.getName());
// boucle infinie
while(true){
// on rcupre l'heure
Calendar calendrier=Calendar.getInstance();
String H=calendrier.get(Calendar.HOUR_OF_DAY)+":"
+calendrier.get(Calendar.MINUTE)+":"
+calendrier.get(Calendar.SECOND);
// affichage
System.out.println(main.getName() + " : " +H);
// arrt temporaire
Thread.sleep(1000);
}//while
}//main
}//classe
43
44
}
};//df tches[i]
// on fixe le nom du thread
tches[i].setName(""+i);
// on lance l'excution du thread i
tches[i].start();
}//for
// fin de main
System.out.println("fin du thread " +main.getName());
}//Main
public static void affiche() {
// on rcupre l'heure
Calendar calendrier=Calendar.getInstance();
String H=calendrier.get(Calendar.HOUR_OF_DAY)+":"
+calendrier.get(Calendar.MINUTE)+":"
+calendrier.get(Calendar.SECOND);
// affichage dbut d'excution
System.out.println("Dbut d'excution de la mthode affiche dans le Thread " +
Thread.currentThread().getName()+ " : " + H);
// mise en sommeil pendant 1 s
try{
Thread.sleep(1000);
}catch (Exception ex){}
// on rcupre l'heure
calendrier=Calendar.getInstance();
H=calendrier.get(Calendar.HOUR_OF_DAY)+":"
+calendrier.get(Calendar.MINUTE)+":"
+calendrier.get(Calendar.SECOND);
// affichage fin d'excution
System.out.println("Fin d'excution de la mthode affiche dans le Thread "
+Thread.currentThread().getName()+ " : " + H);
}// affiche
}//classe
Le thread principal, celui qui excute la fonction main, cre 5 autres threads chargs d'excuter la mthode
statique affiche. Les
rsultats sont les suivants :
dbut du thread myMainThread
Dbut d'excution de la mthode affiche dans le Thread
fin du thread myMainThread
Dbut d'excution de la mthode affiche dans le Thread
Dbut d'excution de la mthode affiche dans le Thread
Dbut d'excution de la mthode affiche dans le Thread
Dbut d'excution de la mthode affiche dans le Thread
Fin d'excution de la mthode affiche dans le Thread 0
Fin d'excution de la mthode affiche dans le Thread 1
Fin d'excution de la mthode affiche dans le Thread 2
Fin d'excution de la mthode affiche dans le Thread 3
Fin d'excution de la mthode affiche dans le Thread 4
0 : 15:48:3
1
2
3
4
:
:
:
:
:
: 15:48:3
: 15:48:3
: 15:48:3
: 15:48:3
15:48:4
15:48:4
15:48:4
15:48:4
15:48:4
Modifions notre programme pour le terminer la mthode main par les instructions :
// fin de main
System.out.println("fin du thread " +main.getName());
// arrt de l'application
System.exit(0);
45
affiche
affiche
affiche
affiche
dans
dans
dans
dans
le
le
le
le
Thread
Thread
Thread
Thread
0
1
2
3
:
:
:
:
16:5:45
16:5:45
16:5:45
16:5:45
elle arrte tous les threads de l'application et non simplement le thread main. La mthode main pourrait
vouloir attendre la fin d'excution des threads qu'elle a crs avant de se terminer elle-mme. Cela peut se
faire avec la mthode join de la classe Thread :
// attente de tous les threads
for(int i=0;i<tches.length;i++){
// on attend le thread i
tches[i].join();
}//for
// fin de main
System.out.println("fin du thread " +main.getName());
// arrt de l'application
System.exit(0);
0
1
2
3
4
:
:
:
:
:
: 16:11:9
: 16:11:9
: 16:11:9
: 16:11:9
: 16:11:9
16:11:10
16:11:10
16:11:10
16:11:10
16:11:10
Voil deux programmes trs simples pour mieux te faire comprendre pourquoi les fils d'excution sont
ncessaires.
import javax.swing.*;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ExempleSansFils extends JFrame
implements ActionListener {
// Constructeur
ExempleSansFils() {
// Cre un cadre contenant un bouton et un champ textuel
GridLayout disposition = new GridLayout(2,1);
this.getContentPane().setLayout(disposition);
JButton monBouton = new JButton("Tuer le temps");
monBouton.addActionListener(this);
this.getContentPane().add(monBouton);
this.getContentPane().add(new JTextField());
}
// Traite les clics sur le bouton
public void actionPerformed(ActionEvent vnement) {
// Tue juste un peu le temps pour montrer que
// les contrles de la fentre sont verrouills.
for (int i = 0; i < 30000; i++) {
this.setTitle("i = " + i);
}
}
public static void main(String[] args) {
// Cre une instance du cadre
ExempleSansFils maFentre = new ExempleSansFils();
// Permet la fermeture de la fentre par clic sur la
// petite croix dans le coin.
maFentre.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE);
46
La version suivante de cette petite fentre cre et lance un thread spar pour la boucle ;
En Java, on peut crer un fil d'excution par l'un des moyens suivants :
1. Crer une instance de la classe Java Thread et lui passer un objet qui implante l'interface Runnable. Si
cette classe implante l'interface Runnable, le code ressemble ceci :
Thread travailleur = new Thread(this);
Cette interface t'impose d'crire dans la mthode run() le code qui doit tre excut comme un fil
d'excution spar. Mais pour lancer le fil d'excution, tu dois appeler la mthode start(), qui va en fait
appeler ta mthode run(). D'accord, c'est un peu troublant, mais c'est comme a que tu dmarres le fil
d'excution :
travailleur.start();
2. Crer une sous-classe de la classe Thread et y implanter la mthode run(). Pour dmarrer le fil
d'excution, appeler la mthode start().
public class MonFil extends Thread {
public static void main(String[] args) {
MonFil travailleur = new MonFil();
travailleur.start();
}
public void run() {
// Place ton code ici.
}
}
J'utilise la premire mthode dans la classe ExempleAvecFils parce que cette classe hrite dj de JFrame
et qu'on ne peut pas hriter de plus d'une classe en Java.
import javax.swing.*;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ExempleAvecFils extends JFrame
implements ActionListener, Runnable {
// Constructeur
ExempleAvecFils() {
// Cre un cadre contenant un bouton et un champ textuel.
GridLayout disposition = new GridLayout(2,1);
this.getContentPane().setLayout(disposition);
JButton monBouton = new JButton("Tuer le temps");
monBouton.addActionListener(this);
this.getContentPane().add(monBouton);
this.getContentPane().add(new JTextField());
}
public void actionPerformed(ActionEvent vnement) {
// Cre un fil et excute le code "tuer le temps"
// sans bloquer la fentre.
Thread travailleur = new Thread(this);
travailleur.start(); // Ceci appelle la mthode run()
}
public void run() {
// Tue juste un peu le temps pour montrer que
// les contrles de la fentre NE sont PAS verrouills.
47
48
Programmation TCP-IP
Gestion des adresses rseau en Java
Chaque machine de l'Internet est identifie par une adresse ou un nom uniques. Ces deux entits sont
gres sous Java par la classe InetAddress dont voici quelque mthodes :
byte [] getAddress()
Quelques exemples
Identifier la machine locale
import java.net.*;
public class localhost{
public static void main (String arg[]){
try{
InetAddress adresse=InetAddress.getLocalHost();
byte[] IP=adresse.getAddress();
System.out.print("IP=");
int i;
for(i=0;i<IP.length-1;i++) System.out.print(IP[i]+".");
System.out.println(IP[i]);
System.out.println("adresse="+adresse.getHostAddress());
System.out.println("nom="+adresse.getHostName());
System.out.println("identit="+adresse);
} catch (UnknownHostException e){
System.out.println ("Erreur getLocalHost : "+e);
}// fin try
}// fin main
}// fin class
Chaque machine a une adresse IP interne qui est 127.0.0.1. Lorsqu'un programme utilise cette adresse
rseau, il utilise la machine sur laquelle il fonctionne. L'intrt de cette adresse est qu'elle ne ncessite pas
de carte rseau. On peut donc tester des programmes rseau sans tre connect un rseau. Une autre
faon de dsigner la machine locale est d'utiliser le nom localhost.
49
La relation client-serveur
Souvent, la communication sur Internet est dissymtrique : la machine A initie une connexion pour
demander un service la machine B : il prcise qu'il veut ouvrir une connexion avec le service SB1 de la
machine B. Celle-ci accepte ou refuse. Si elle accepte, la machine A peut envoyer ses demandes au service
SB1. Celles-ci doivent se conformer au protocole de dialogue compris par le service SB1. Un dialogue
demande-rponse s'instaure ainsi entre la machine A qu'on appelle machine cliente et la machine B qu'on
appelle machine serveur. L'un des deux partenaires fermera la connexion.
Le programme serveur traite diffremment la demande de connexion initiale d'un client de ses demandes
ultrieures visant obtenir un service. Le programme n'assure pas le service lui-mme. S'il le faisait,
pendant la dure du service il ne serait plus l'coute des demandes de connexion et des clients ne seraient
alors pas servis. Il procde donc autrement : ds qu'une demande de connexion est reue sur le port
d'coute puis accepte, le serveur cre une tche charge de rendre le service demand par le client. Ce
service est rendu sur un autre port de la machine serveur appel port de service. On peut ainsi servir
plusieurs clients en mme temps.
Une tche de service aura la structure suivante :
tant que le service n'a pas t rendu totalement
attendre une demande sur le port de service
lorsqu'il y en a une, laborer la rponse
transmettre la rponse via le port de service
fin tant que
librer le port de service
La classe Socket
L'outil de base utilis par les programmes communiquant sur Internet est la socket. Ce mot anglais signifie
"prise de courant". Il est tendu ici pour signifier "prise de rseau". Pour qu'une application puisse envoyer
et recevoir des informations sur le rseau Internet, il lui faut une prise de rseau, une socket. Cet outil a t
initialement cr dans les versions d'Unix de l'universit de Berkeley. Il a t port depuis sur tous les
systmes Unix ainsi que dans le monde Windows. Il existe galement sur les machines virtuelles Java sous
deux formes : la classe Socket pour les applications clientes et la classe ServerSocket pour les applications
serveur.
Nous explicitons ici quelques-uns des constructeurs et mthodes de la classe Socket :
public Socket(String host, int port)
public InetAddress
getLocalAdress()
public InetAddress
getInetAdress()
public InputStream
getInputStream()
public OutputStream
getOutputStream()
51
cre une socket et la connecte la machine host sur le port port. Ce constructeur gnre une exception
dans diffrents cas :
- mauvaise adresse
- mauvais port
- demande refuse
-
Il nous faut grer cette exception :
Socket sClient=null;
try{
sClient=new Socket(host,port);
} catch(Exception e){
// la connexion a chou - on traite l'erreur
.
}
Si la demande de connexion russit, le client se voit localement attribuer un port pour communiquer avec
la machine B. Une fois la connexion tablie, on peut connatre ce port avec la mthode :
public int getLocalPort();
Si la connexion russit, nous avons vu que, de son ct, le serveur fait assurer le service par une autre
tche travaillant sur un port dit de service. Ce numro de port peut tre connu avec la mthode :
public int getPort();
Tout ce qui sera envoy dans ce flux sera reu sur le port de service de la machine serveur. De nombreuses
applications ont un dialogue sous forme de lignes de texte termines par un passage a ligne. Aussi la
mthode println est-elle bien pratique dans ces cas l. On transforme alors le flux de sortie OutputStream
en flux PrintWriter qui possde la mthode println. L'criture peut gnrer une exception.
Lire des informations venant du rseau
On peut obtenir un flux de lecture des informations arrivant sur la socket avec la mthode :
public InputStream getInputStream();
Tout ce qui sera lu dans ce flux vient du port de service de la machine serveur. Pour les applications ayant
un dialogue sous forme de lignes de texte termines par un passage la ligne on aimera utiliser la mthode
readLine. Pour cela on transforme le flux d'entre InputStream en flux BufferedReader qui possde la
mthode readLine(). La lecture peut gnrer une exception.
Fermeture de la connexion
Elle se fait avec la mthode :
public void close();
La mthode peut gnrer une exception. Les ressources utilises, notamment le port rseau, sont libres.
52
La classe ServerSocket
Cette classe est destine la gestion des sockets cot serveur. Nous explicitons ici quelques-uns des
constructeurs et mthodes de cette classe :
public ServerSocket(int port)
public InetAddress
getInetAdress()
Ouverture du service
Elle se fait avec les deux constructeurs :
public ServerSocket(int port);
public ServerSocket(int port, int count);
port est le port d'coute du service : celui o les clients adressent leurs demandes de connexion. count est
la taille maximale de la file d'attente du service (50 par dfaut), celle-ci stockant les demandes de
connexion des clients auxquelles le serveur n'a pas encore rpondu. Lorsque la file d'attente est pleine, les
demandes de connexion qui arrivent sont rejetes. Les deux constructeurs gnrent une exception.
Acceptation d'une demande de connexion
Lorsq'un client fait une demande de connexion sur le port d'coute du service, celui-ci l'accepte avec la
mthode :
public Socket accept();
Cette mthode rend une instance de Socket : c'est la socket de service, celle travers laquelle le service
sera rendu, le plus souvent par une autre tche. La mthode peut gnrer une exception.
Lecture/Ecriture via la socket de service
La socket de service tant une instance de la classe Socket, on se reportera aux sections prcdentes o ce
sujet a t trait.
Identifier le client
Une fois la socket de service obtenue, le client peut tre identifi avec la mthode
public InetAddress getInetAddress()
Fermer le service
Cela se fait avec la mthode
public void close();
de la classe ServerSocket. Cela libre les ressources occupes, notamment le port d'coute. La mthode
peut gnrer une exception.
Applications
Serveur d'cho
Nous nous proposons d'crire un serveur d'cho qui sera lanc depuis une fentre DOS par la commande :
java serveurEcho port
Le serveur officie sur le port pass en paramtre. Il se contente de renvoyer au client la demande que
celui-ci lui a envoye accompagne de son identit (IP+nom). Il accepte 2 connexions dans sa liste
d'attente. On a l tous les constituants d'un serveur tcp. Le programme est le suivant :
// appel : serveurEcho port
// serveur d'cho
// renvoie au client la ligne que celui-ci lui a envoye
import java.net.*;
import java.io.*;
public class serveurEcho{
public final static String syntaxe="Syntaxe : serveurEcho port";
public final static int nbConnexions=2;
// programme principal
public static void main (String arg[]){
// y-a-t-il un argument
if(arg.length != 1)
erreur(syntaxe,1);
// cet argument doit tre entier >0
int port=0;
boolean erreurPort=false;
Exception E=null;
try{
port=Integer.parseInt(arg[0]);
}catch(Exception e){
E=e;
erreurPort=true;
}
erreurPort=erreurPort || port <=0;
if(erreurPort)
erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2);
// on cre la socket d'coute
ServerSocket ecoute=null;
try{
ecoute=new ServerSocket(port,nbConnexions);
} catch (Exception e){
erreur("Erreur lors de la cration de la socket d'coute ("+e+")",3);
}
// suivi
System.out.println("Serveur d'cho lanc sur le port " + port);
// boucle de service
boolean serviceFini=false;
Socket service=null;
while (! serviceFini){
// attente d'un client
try{
service=ecoute.accept();
} catch (IOException e){
erreur("Erreur lors de l'acceptation d'une connexion ("+e+")",4);
54
}
// on identifie la liaison
try{
System.out.println("Client ["+identifie(service.getInetAddress())+","+
service.getPort()+"] connect au serveur [" + identifie (InetAddress.getLocalHost())
+ "," + service.getLocalPort() + "]");
} catch (Exception e) {
erreur("identification liaison",1);
}
// le service est assur par une autre tche
new traiteClientEcho(service).start();
}// fin while
}// fin main
// affichage des erreurs
public static void erreur(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}
// identifie
private static String identifie(InetAddress Host){
// identification de Host
String ipHost=Host.getHostAddress();
String nomHost=Host.getHostName();
String idHost;
if (nomHost == null) idHost=ipHost;
else idHost=ipHost+","+nomHost;
return idHost;
}
}// fin class
// assure le service un client du serveur d'cho
class traiteClientEcho extends Thread{
private Socket service; // socket de service
private BufferedReader in; // flux d'entre
private PrintWriter out; // flux de sortie
// constructeur
public traiteClientEcho(Socket service){
this.service=service;
}
// mthode run
public void run(){
// cration des flux d'entre et de sortie
try{
in=new BufferedReader(new InputStreamReader(service.getInputStream()));
} catch (IOException e){
erreur("Erreur lors de la cration du flux dentre de la socket de service ("+e+")",1);
}// fin try
try{
out=new PrintWriter(service.getOutputStream(),true);
} catch (IOException e){
erreur("Erreur lors de la cration du flux de sortie de la socket de service ("+e+")",1);
}// fin try
// l'identification de la liaison est envoye au client
try{
out.println("Client ["+identifie(service.getInetAddress())+","+
service.getPort()+"] connect au serveur [" + identifie (InetAddress.getLocalHost())
+ "," + service.getLocalPort() + "]");
} catch (Exception e) {
erreur("identification liaison",1);
}
// boucle lecture demande/criture rponse
String demande,reponse;
try{
// le service s'arrte lorsque le client envoie une marque de fin de fichier
while ((demande=in.readLine())!=null){
// cho de la demande
reponse="["+demande+"]";
out.println(reponse);
// le service s'arrte lorsque le client envoie "fin"
if(demande.trim().toLowerCase().equals("fin")) break;
}// fin while
} catch (IOException e){
55
56
try{
System.out.println("Client : Client ["+identifie(InetAddress.getLocalHost())+","+
sClient.getLocalPort()+"] connect au serveur [" + identifie (sClient.getInetAddress())
+ "," + sClient.getPort() + "]");
} catch (Exception e) {
erreur("identification liaison ("+e+")",5);
}
// cration du flux de lecture des lignes tapes au clavier
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
erreur("Cration du flux d'entre clavier ("+e+")",6);
}
// cration du flux d'entre associe la socket client
BufferedReader in=null;
try{
in=new BufferedReader(new InputStreamReader(sClient.getInputStream()));
} catch (Exception e){
erreur("Cration du flux d'entre de la socket client("+e+")",7);
}
// cration du flux de sortie associe la socket client
PrintWriter out=null;
try{
out=new PrintWriter(sClient.getOutputStream(),true);
} catch (Exception e){
erreur("Cration du flux de sortie de la socket ("+e+")",8);
}
// boucle demandes - rponses
boolean serviceFini=false;
String demande=null;
String reponse=null;
// on lit le message envoy par le serveur juste aprs la connexion
try{
reponse=in.readLine();
} catch (IOException e){
erreur("Lecture rponse ("+e+")",4);
}
// affichage rponse
System.out.println("Serveur : " +reponse);
while (! serviceFini){
// lecture d'une ligne tape au clavier
System.out.print("Client : ");
try{
demande=IN.readLine();
} catch (Exception e){
erreur("Lecture ligne ("+e+")",9);
}
// envoi demande sur le rseau
try{
out.println(demande);
} catch (Exception e){
erreur("Envoi demande ("+e+")",10);
}
// attente/lecture rponse
try{
reponse=in.readLine();
} catch (IOException e){
erreur("Lecture rponse ("+e+")",4);
}
// affichage rponse
System.out.println("Serveur : " +reponse);
// est-ce fini ?
if(demande.trim().toLowerCase().equals("fin")) serviceFini=true;
}
// c'est fini
try{
sClient.close();
} catch(Exception e){
erreur("Fermeture socket ("+e+")",11);
}
57
}// main
// affichage des erreurs
public static void erreur(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}
// identifie
private static String identifie(InetAddress Host){
// identification de Host
String ipHost=Host.getHostAddress();
String nomHost=Host.getHostName();
String idHost;
if (nomHost == null) idHost=ipHost;
else idHost=ipHost+","+nomHost;
return idHost;
}
}// fin class
La structure de ce client est conforme l'architecture gnrale des clients tcp. Ici, on a gr les diffrentes
exceptions possibles, une par une, ce qui alourdit le programme. Voici les rsultats obtenus lorsqu'on teste
ce client :
Client : Client [127.0.0.1,tahe,1045] connect au serveur [127.0.0.1,localhost,187]
Serveur : Client [127.0.0.1,localhost,1045] connect au serveur [127.0.0.1,tahe,187]
Client : 123
Serveur : [123]
Client : abcd
Serveur : [abcd]
Client : je suis l
Serveur : [je suis l]
Client : fin
Serveur : [fin]
Les lignes commenant par Client sont les lignes envoyes par le client et celles commenant par Serveur
sont celles que le serveur a renvoyes en cho.
58
59
Le programme est lanc par : java serveurTCPgenerique portEcoute, o portEcoute est le port sur
lequel les clients doivent se connecter. Le service au client sera assur par deux threads :
un thread se consacrant exclusivement la lecture des lignes de texte envoyes par le client
un thread se consacrant exclusivement la lecture des rponses tapes au clavier par l'utilisateur.
Celui-ci signalera par la commande fin qu'il clt la connexion avec le client.
Le serveur cre deux threads par client. S'il y a n clients, il y aura 2n threads actifs en mme temps. Le
serveur lui ne s'arrte jamais sauf par un Ctrl-C tap au clavier par l'utilisateur.
Le code du serveur tcp gnrique est le suivant :
// paquetages
import java.io.*;
import java.net.*;
public class serveurTCPgenerique{
// programme principal
public static void main (String[] args){
// reoit le port d'coute des demandes des clients
// cre un thread pour lire les demandes du client
// celles-ci seront affiches l'cran
// cre un thread pour lire des commandes tapes au clavier
// celles-ci seront envoyes comme rponse au client
// le tout se termine avec la commande fin tape au clavier
final String syntaxe="Syntaxe : pg port";
// variable d'instance
// y-a-t-il un argument
if(args.length != 1)
erreur(syntaxe,1);
// le port doit tre entier >0
int port=0;
boolean erreurPort=false;
Exception E=null;
try{
port=Integer.parseInt(args[0]);
}catch(Exception e){
E=e;
erreurPort=true;
}
erreurPort=erreurPort || port <=0;
if(erreurPort)
erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2);
// on cre le servive d'coute
ServerSocket ecoute=null;
int nbClients=0; // nbre de clients traits
try{
// on cre le service
ecoute=new ServerSocket(port);
// suivi
System.out.println("Serveur gnrique lanc sur le port " + port);
// boucle de service aux clients
Socket client=null;
while (true){ // boucle infinie - sera arrte par Ctrl-C
// attente d'un client
client=ecoute.accept();
// le service est assur des threads spars
nbClients++;
// on cre les threads de lecture/criture
new ServeurSend(client,nbClients).start();
new ServeurReceive(client,nbClients).start();
// on retourne l'coute des demandes
}// fin while
}catch(Exception ex){
// on signale l'erreur
61
62
// et son n
this.numClient=numClient;
}//constructeur
// mthode Run du thread
public void run(){
// donnes locales
BufferedReader IN=null; // flux lecture rseau
String rponse=null; // rponse serveur
// suivi
System.out.println("Thread de lecture des demandes du client "+ numClient + " lanc");
// gestion des erreurs
try{
// cration du flux lecture rseau
IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
// boucle lecture lignes de texte du flux IN
while(true){
// lecture flux rseau
rponse=IN.readLine();
// flux ferm ?
if(rponse==null) break;
// affichage
System.out.println("<-- "+rponse);
}//while
}catch(Exception ex){
// erreur
System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fin - on ferme les flux
try{
IN.close();client.close();
}catch(Exception ex){}
// on signale la fin du thread
System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]");
}//run
}//classe
63
Dfinir un package
import permet d'importer n'importe quelle classe d'une bibliothque, mais vous pouvez aussi crer votre
propre bibliothque, pour y rassembler par exemple un groupe de classes utilises comme outils dans un
ou plusieurs projets. Ceci se fait trs simplement grce la clause package. Si cette clause est utilise, elle
doit tre dfinie en tte d'un fichier .java , comme suit :
package nomPackage;
Comme expliqu prcdemment, le nom de package doit correspondre au chemin d'accs la classe qui
utilise la clause package.
Classes et Objets
Les classes Java peuvent possder des mthodes et des attributs.
Les mthodes dfinissent les actions quune classe peut effectuer.
Les attributs dcrivent la classe.
Aprs le mot classe, tu dois maintenant thabituer la nouvelle signification du mot objet.
La phrase "crer une instance dun objet" signifie crer une copie de cet objet dans la mmoire de
lordinateur en respectant la dfinition de sa classe.
La dclaration d'une classe peut prendre une des formes suivantes :
// Dclararation d'une classe simple
ModifieurDeClasse class NomDeClasse
{
// Corps de NomDeClasse :
// Dclaration des champs, des mthodes, des constructeurs
// et/ou initialisations static
}
// Dclaration d'une classe drivant d'une super classe
ModifieurDeClasse class NomDeClasseDerivee extends NomDeSuperClasse
{
// Corps de NomDeClasseDerivee :
// Dclaration des champs, des mthodes, des constructeurs
// et/ou initialisations static
}
// Dclaration d'une classe implmentant une interface
ModifieurDeClasse class NomDeClasse2 implements NomInterface //, NomInterface2, ...
{
// Corps de NomDeClasse2 :
// Dclaration des champs, des mthodes, des constructeurs
// et/ou initialisations static
// et implmentation des mthodes de nomInterface
}
// Dclaration d'une classe drivant d'une super classe et implmentant une interface
ModifieurDeClasse class NomDeClasse3 extends NomDeSuperClasse
implements NomInterface //, NomInterface2, ...
{
// Corps de NomDeClasse3 :
// Dclaration des champs, des mthodes, des constructeurs
// et/ou initialisations static
// et implmentation des mthodes de nomInterface
}
Une classe simple drive implicitement de la classe Object (class nomDeClasse est quivalent class
nomDeClasse extends Object). Java ne permet pas l'hritage multiple (une seule classe peut suivre la
clause extends), mais une classe peut implmenter plusieurs interfaces.
64
Le corps d'une classe est une suite quelconque de dclaration de champs, de mthodes, de constructeurs
et/ou d'initialisations static.
ModifieurDeClasse est optionnel et peut prendre une ou plusieurs des valeurs suivantes :
public : Une seule classe ou interface peut tre dclare public par fichier source .java . Par
convention, le fichier porte le nom de la classe dclare public. Si d'autres classes (non public)
sont dclares dans un fichier Classe1.java, elles ne peuvent tre utiliss que dans les fichiers qui
appartiennent au mme package que Classe1.java.
final : Une classe dclare final ne peut tre drive et ne peut donc jamais suivre la clause
extends. Cette clause peut tre utile quand vous considrez qu'une classe ne doit pas ou n'a pas
besoin d'tre drive.
abstract : Il est impossible de crer une instance d'une classe dclare abstract. Cette catgorie de
classe peut comporter une ou plusieurs mthodes dclares abstract. Par contre, si une classe
comporte une mthode abstract, elle doit tre dclare abstract. A quoi sert une classe abstract si
on ne peut crer aucun objet de cette classe ? Ce type de classe est utilis pour fournir des
mthodes et des champs communs toutes les classes qui en drivent. L'intrt des classes
abstract est dmontr plus loin dans ce chapitre. Une classe ne peut tre dclare abstract et final
(elle ne servirait rien puisqu'il serait impossible de crer des classes drives de celle-ci).
Les interfaces
Une interface est une catgorie un peu spciale de classe abstract, dont le corps ne contient que la
dclaration de constantes et de mthodes abstract :
// Dclararation d'une interface simple
ModifieurInterface interface NomInterface
{
// Corps de NomInterface :
// Dclaration des constantes et des mthodes non implmentes
}
// Dclaration d'une interface drivant d'une super interface
ModifieurInterface
interface
NomInterfaceDerivee
extends
NomSuperInterfa
{
// Corps de NomInterfaceDerivee :
// Dclaration des constantes et des mthodes non implmentes
}
NomSuperInterface
//,
II est impossible de crer une instance d'une interface. Une ou plusieurs interfaces peuvent suivre la clause
extends.
65