Jose M. Fernández Ecrivez à l'auteurAuthor
e-mail
|
Résumé:
cette
série d'articles suit le modèle classique des livres sur
la programmation structurée. La première partie introdusait
les caractéristiques du langage Java, nous continuons maintenant
avec les types de données, les variables, les structures de contr^ole,
etc., jusqu'à finalement introduire les classes, sujet principal
et le plus important lorsque l'on sait que les classes sont la base de
ce langage de programmation. Excepté les classes, les autres sujets
traités sont très similaires à de nombreux autres
langages, aussi nous avons choisi de les parcourir rapidement et brièvement.
Les commentaires peuvent s'écrire selon trois syntaxes différentes
en Java:
// commentaire | Les caractères depuis // jusqu'à la fin de la ligne sont ignorés par le compilateur. |
/* commentaire */ | Tous les caractères entre /* et */ sont ignorés. Plusieurs lignes peuvent ^etre comprises ente les marques. |
/** commentaire **/ | Comme précédamment, mais ils devraient ^etre réservés avant les déclarations car l'outil javadoc les utilise pour générer automatiquement la documentation. |
Les identificateurs sont les noms donnés aux variables, classes ou méthodes définies par l'utilisateur . On peut utiliser n'importe quelle ch^aine de caractères (minuscule ou majuscule), y compris les chiffres et les signes dollar et souligné. Les identificateurs ne peuvent cependant pas commencer par un chiffre.
Java réserve certains caractères pour les séparateurs. Le plus rencontré est le point-virgule, mais on trouve aussi:
Symb^ole | Description |
() | Contient la liste des paramètres à la définition et à l'appel des méthodes. Il est aussi utilisé pour changer la précédence des expressions, pour inclure des expressions dans une structure de contr^ole, et pour changer le type d'une expression. |
{} | Définit un bloc de code pour les classes, méthodes, ou pour déclarer localement une visibilité. Aussi utilisé pour initialiser les vecteurs. |
[] | Définit le type matrice, et permet d'accéder à leurs éléments. |
; | Séparateur de phrase. |
, | Sépare différents identificateurs lors des
déclarations de variables, ou lors des appels de méthodes.
Aussi utilisé pour séparé les déclarations dans une boucle "for". |
. | Sépare les différents "package" et nom de classes. Aussi utilisé pour appliquer une méthode à une variable. |
Les mots clés sont des termes réservés du
langage Java. On ne peut les utiliser comme identificateurs. Voici une
liste de mots clés du langage Java:
abstract | double | int | super |
boolean | else | interface | switch |
break | extends | long | synchronized |
byte | false | native | this |
byvalue | final | new | threadsafe |
case | finally | null | throw |
catch | float | package | transient |
char | for | private | true |
class | goto | protected | try |
const | if | public | void |
continue | implements | return | while |
default | import | short | |
do | instanceof | static |
Lors du précédent article, nous avons indiqué que Java est compplètement orienté objet. Néanmoins, pour des raisons d'efficacité, Java définit huit types "simples" qui ne sont pas des objets. Pour des raisons de portabilité, chaque type simple à une plage de variation définie.
Les types simples peuvent ^etre classés en quatre groupes:
GROUPE | TYPE | TAILLE (bits) | PLAGE |
Nombres entiers | long | 64 | -9.223.372.036.854.775.808
à 9.223.372.036.854.775.807 |
int | 32 | -2.147.483.648
à 2.147.483.647 |
|
short | 16 | -32.768 à 37.767 | |
byte | 8 | -128 à 127 | |
Nombres à virgule flottante | float | 32 | 3.4 e-038 à 3.4 e+038 |
double | 64 | 1.7 e-308 à 1.7 e+308 | |
Caractères | char | 16 | Unicode |
Booléens | boolean | Vrai ou faux |
En général, la déclaration d'une variable ressemble
à ceci:
type identificateur1 [=valeur1] [,identificateur2 [=valeur2]......]; |
où "type" peut ^etre un type Java de base, une classe ou m^eme une interface. Si on initialise la variable, l'expression doit ^etre du m^eme type ou un type compatible à celui spécifié à la déclaration de la variable.
Exemples:
int a = 4, b, c=7; char c; myclass d; |
En règle générale, une variable définie à l'intérieur d'une zone de visibilité n'est pas visible par le code extérieur (on définit la zone de visibilité par le code compris entre deux accolades {}). Une variable ne conserve pas sa valeur lorsque l'on sort de sa zone de visibilité.
La plupart des langages de programmation définissent deux catégories de visibilité, global et local. Cependant, cela s'accomode mal de l'orientation objet de Java. Dans ce modèle, les deux visibilités principales sont celles définies par la classe et par la méthode.
(type) value |
où type indique le type cible. Par exemple:
int a; char b; a=(int) b; |
Il faut ^etre rès prudent avec la conversion de type, car elle
peut provoquer une perte d'information. Par exemple:
int a; double d= 125.43; a=(int) d;La variable a vaut 125. byte b; int i=257; b=(byte) i;b vaut 1, résultat de la division de 257 par 256 où 256 est le maximum du type "byte". byte b; double d= 340.123; b=(byte) d;b vaut maintenant 84. |
Toutes ces conversions ne posent aucun problème à la compilation ou à l'exécution.
Opérateur | Description |
+ | Addition |
- | Soustraction |
* | Multiplication |
/ | Division |
% | Modulo (reste de la division) |
++ | Incrémentation |
+= | Addition puis assignation |
-= | Soustraction puis assignation |
*= | Multiplication puis assignation |
/= | Division puis assignation |
%= | Modulo puis assignation |
-- | Décrémentation |
L'opérateur modulo peut ^etre appliqué à la fois
aux entiers et aux nombres en virgule flottante. Par exemple:
int a=38; double d=41.95; int c=a%10; double e=d%10; |
La variable c vaut 8, et a pour valeur 1.95.
Les opérateurs avec assignation sont utiles pour:
a = a + 4; equivaut à a += 4;
a = a % 2; equivaut à a %= 2;
De manière générale, les expressions telles:
var=var op expression;
peuvent ^etre remplacées par
var op= expression;
Opérateur | Description |
~ | Négation |
& | ET |
| | OU |
/\ | OUExclusif |
>> | Décalage à droite |
>>>> | Décalage à droite avec insertion de zéros |
<< | Décalage à gauche |
&= | ET puis assignation |
|= | OU puis assignation |
/\= | OUExclusif puis assignation |
>>= | Décalage à droite puis assignation |
>>>>= | Décalage à droite avec insertion de zéros puis assignation |
<<= | Décalage à gauche puis assignation |
Opérateur | Description |
== | Egal à |
!= | Différent de |
> | Supérieur à |
< | Inférieur à |
>= | Supérieur ou égal |
<= | Inférieur ou égal |
Au contraire d'autres langages (C/C++), les valeurs booléennes sont "true" et "false", c'est à dire qu'elles ne sont pas des valeurs numériques.
Opérateur | Description |
& | ET |
| | OU |
/\ | OUExclusif |
|| | OU raccourci |
&& | ET raccourci |
! | Négation |
&= | ET puis assignation |
|= | Ou puis assignation |
/\= | OUExclusif puis assignation |
== | Egal à |
!= | Différent de |
?: | Ternaire Si-alors-sinon |
Le OU raccourci prend la valeur true quand le premier opérande est vrai, quel que soit le deuxiéme opérande. Le ET raccourci prend la valeur false quand le premier opérande est faux, quel que soit le deuxiéme opérande.
La forme générale de l'opérateur ternaire est:
expession1 ? expession2 : expression3
Si expression1 est vraie, expression2 est exécutée; sinon, expression3 est exécutée.
Précédence des opérateurs:
Plus élevé
( ) | [ ] | . | |
++ | -- | ~ | ! |
* | / | % | |
+ | - | ||
>> | >>>> | << | |
> | >= | < | <= |
= = | != | ||
& | |||
' | |||
| | |||
&& | |||
|| | |||
?: | |||
= | Op= |
Groupe | Expression | Description |
Sélections | if |
if ( condition ) instruction1; else instruction2; |
Plusieurs "if" |
if (condition ) instruction1; else if (condition) instruction2; else if (condition) instruction3; . . else instructionX; |
|
switch |
switch (expression){ case valeur1: expression; break; case valeur2: expression; break; . ... default : expression; } |
|
Boucles | while |
while (condition) { expression; } |
do while |
do { expression; } while (condition) |
|
for |
for (initialisation, condition, réinitialisation) { expression; } |
|
Sauts | break | Pour sortir d'une structure "switch".
Pour sortir d'une boucle. |
continue | Passe immédiatement à l'itération suivante de cette boucle. | |
return | Sortie explicite d'une méthode, retour au programme appelant. |
La classe est un modèle pour un objet, et un objet est une instance (réalisation) d'une classe. Java n'accepte pas les fonctions ou variables globales, donc toutes les actions (méthodes) d'un programme doivent ^etre définies dans une classe.
On définit une classe en utilisant le mot réservé
"class". Par exemple, le fragment de code définit une classe:
Class classe { Type variable1; Type variable2; . . ... type variableN; type methode1(liste_parametre){ // corps de la methode } . . .. type methode2(liste_parametre){ // corps de la methode . } } |
Les variables ou données définies dans une classe sont appelées variables d'instance. Les méthodes contiennent le code, et définissent comment les données d'une classe doivent ^etre utilisées.
Deux étapes sont nécessaires pour obtenir les objets d'une classe:
variable = new nom_de_la_classe(); |
Où "variable" est le nom de l'objet que l'on souhaite créer, et "nom_de_la_classe" est le nom de la classe instanciée. La création d'un objet peut ^etre représentée graphiquement ainsi:
type nom_de_la_methode( liste_de_parametre ) { // corps de la methode } |
"type" est le type de l'objet retourné par la méthode ; il peut s'agir de n'importe quel type valide, y compris des classes, ou encore la méthode peut ne pas renvoyer de valeur (type "void").
La lite des paramètres est composée de paires (type, identificateur), séparées par des virgules. Les paramètres sont des variables qui prennent la valeur des arguments passés à la méthode. Si la méthode n'a pas d'arguments, la liste est vide.
Les méthodes renvoyant une valeur se terminent par l'instruction:
return valeur; |
où "valeur" est la valeur renvoyée.
Les méthodes fournissent à Java sa puissance et sa flexibilité, aussi nous leur consacrerons la suite de cet article.
Cependant, nous allons d'abord revoir à travers un exemple simple les concepts que nous venons d'exposer.
Nous allons créer une classe qui calcule le volume d'un parallèlipède
(comme une piscine):
Code | Commentaires |
class capacite { double longueur; double largeur; double hauteur; void CalcVolume () { double volume ; volume = longueur* largeur* hauteur; System.out.println("Volume: " + volume); } } |
Nous définissons une classe appelée "capacite", qui comporte trois variables numérique (type double): longueur, largeur et hauteur. La classe définit aussi une méthode "CalcVolume" qui permet de calculer le volume de la bo^ite. Le code source est enregistré dans le fichier "capacite.java"; à la compilation, la classe "capacite.class" est créée. |
Cette classe isolée ne produit aucune action, ce n'est pas non
plus une applette. Nous avons réalisé un canevas qui permet
de créer des objets, instances de cette classe. Nous allons maintenant
écrire un programme. Un programme est lui-m^eme une classe
qui dispose d'une méthode spéciale "main", appelée
lors de l'exécution depuis la ligne de commande :
Code | Commentaires |
class exemple { public static void main(String Arg[]){ capacite p1=new capacite(); capacite p2=new capacite(); p1.longueur = 16; p1.largeur=3; p1.hauteur=2; // p2.longueur = 25; p2.largeur=6; p2.hauteur=3; // p1.CalcVolume(); // p2.CalcVolume(); } } |
Deux variables de type capacite sont déclarées;
p1 et p2. L'opérateur "new" permet de créer deux objets de
type "capacite", qui seont référencés par les variables
p1 et p2.
Des valeurs sont ensuite données à ces variables. L'appel de la méthode CalcVolume() de l'objet p1 conduit à l'affichage sur l'écran de: Volume: 80 Le m^eme appel sur l'objet p2 conduit à: "Volume: 450" sur l'écran. |
Lorsque p1.ValcVolume() est appelée, l'interpréteur Java transfère le contr^ole au code de la méthode "CalcVolume", définie dans la classe "capacite". Quand toutes les instructions ont été exécutées, l'exécution reprend dans le programme principal après l'appel de la méthode.
Méthode avec paramètres, valeur retournée.
La majorité des méthodes prennent des paramètres. Souvent aussi, elles renvoient une valeur.
Ainsi notre exemple pourrait ^etre réécrit différemment:
Code | Commentaires |
class capacite { double CalcVolume (double long, double larg, double haut) { double volume=long*larg*haut ; return volume; } } |
La méthode "CalcVolume" a été modifiée pour recevoir trois paramètres, et retourner un nombre de type "double" comme l'indique l'instruction "return". |
class exemple { public static void main(String Arg[]){ capacite p1=new capacity(); capacite p2=new capacity(); double vol; vol=p1.CalcVolume(10,3,2); System.out.println("Volume: " + vol); // vol=p2.CalcVolume(25,5,2); System.out.println("Volume: " + vol); } } |
L'appel à la méthode comporte maintenant les paramètres désirés. La valeur returnée est stockée dans la varialble "vol", qui doit ^etre d'un type compatible avec celui de la méthode. |
Les constructeurs sont un aspect important des classes. Ces fonctions spéciales définissent ce qui arrive lorsqu'un objet d'une classe est créée. La majorité des classes définissent explicitement les actions à réaliser dans la définition de la classe. Sinon, Java fournit lui-m^eme un constructeur par défaut (comme dans notre exemple).
Le constructeur est une méthode qui porte le m^eme nom que la classe. Il est automatiquement exécuté lorsque l'opérateur "new" est rencontré.
Les constructeurs renvoient implicitement le type de la classe créée.
Le constructeur effectue généralement l'initialisation de
l'objet (mise à zéro des membres de la classe...). Ainsi,
le code qui instancie un objet peut l'utiliser immédiatement, son
état est bien déterminé. Les constructeurs peuvent
prendre des paramètres (omme les autres méthodes). Modifions
notre exemple afin d'observer tous ces points:
Code | Commentaires |
Class capacite { double long; double larg; double haut; // capacite(double l, double a, double p){ long=l; larg=a; haut=p; } // void CalcVolume () { double volume ; volume=long*larg*haut; return volume; } } |
On ajoute un constructeur à la classe, qui ressemble à une méthode normale, sauf qu'il n'a pas de type, et qu'il porte le m^eme nom que la classe. Le constructeur initialise les variables de l'objet avec les paramètres qu'il reçoit. |
class exemple { public static void main(String Arg[]) { capacite p1=new capacite(10,5,2); capacite p2=new capacite(25,6,2); double vol; vol=p1.CalcVolume(); System.out.println("Volume: " + vol); // vol=p2.CalcVolume(); System.out.println("Volume: " + vol); } } |
L'opérateur "new" crée deux instances de la classe, en passant les paramètres désirés. |
Lorsqu'il n'existe plus aucune référence à un objet, Java suppose que l'objet n'est plus utilisé, et il est automatiquement détruit, c'est à dire que la mémoire qui lui était allouée est libérée. Il n'est donc pas nécessaire de détruire explicitement les objets créés.
Néanmoins, la méthode "finalize()" est fournie pour ajouter une terminaison aux classes. Cette méthode est appelée juste avant la destruction de l'objet; elle comportera donc les actions à exécuter avant que l'objet ne disparaisse.
Surchargement de méthode.
Le polymorphisme est une des caractéristiques des langages orientés objet. Java l'implémente par le moyen du surchargement (overloading) de mtéhode.
Le principe est que plusieurs méthodes avec un nom commun puissent ^etre définies dans une m^eme classe; elles se distinguent par leur liste d'arguments.
Chaque variante de la méthode surchargée peut effectuer des actions différentes, mais la compréhension du programme devient alors délicate ; il est souhaitable que toutes les variantes réalisent des actions similaires, mais avec des paramètres différents. Les constructeurs étant d'abord des méthodes, ils peuvent aussi ^etre surchargés. Par exemple, on peut construire un carré à partir de son coin supérieur gauche et de son c^oté, ou à partir de deux points définissant les coins supérieur droit et inférieur gauche.
Passage des arguments.
Les langages de programmation prévoient souvent deux manières de passer les arguments à une fonction ou une sous-routine:
Contr^ole d'accès.
Un autre pilier de la programmation orientée objet est l'encapsulation.
Il s'agit de lier fortement les données et les traitements qui leur
sont associés. L'encapsulation apporte aussi un moyen de contr^oler
l'accès aux membres d'une classe.
Les mots clés définissant les propriétés d'accès sont 'public', 'private' et 'protected'.
Lorsqu'un membre ou une méthode de classe est définie comme 'public', il est accessible de toute partie du programme. Au contraire, un membre ou une méthode 'private' n'est accessible qu'à l'intérieur de sa propre classe. Par défaut, tous les membres ou méthodes sont 'public'.
Le mot-clé 'protected' est utilisé avec le concept
d'héritage, expliqué au paragraphe suivant.
La définition d'une classe B héritant des propriétés
de la classe A est réalisée comme suit:
Class B extends A { // class definition } |
La classe B, qui hérite des membres et méthodes de la classe A, est une classe autonome, utilisable indépendamment de A. B peut ^etre utilisée comme classe de base pour définir une nouvelle classe, et ainsi de suite. On obtient ainsi une véritable hiérarchie.
Java interdit l'héritage multiple (contrairement à C++), qui consiste à définir une classe à partir de plusieurs super-classes.
Les membres déclarés "private" dans la super-classe ne peuvent ^etre utilisées par les classes héritées. Une classe peut accéder aux éléments de sa super-classe gr^ace au mot-clé "super". Il est ainsi possible d'accéder m^eme aux éléments de la super-classe cachés par la sous classe.
Lorsqu'une méthode d'une classe a le m^eme nom, le m^eme type et la m^eme liste d'arguments qu'une méthode de la super-classe, celle-ci est dite réécrite (overridden). Cette propriété est la base d'un des aspects les plus puissants de Java, la sélection dynamique de méthode; cela signifie simplement que le choix de la méthode à exécuter est réalisé à l'exécution du programme.
Le prochain article démontrera la puissance du concept d'héritage;
nous verrons aussi des notions telles que les classes abstraites, les interfaces,
etc.
© Jose M. Fernandez 1998 LinuxFocus 1998 Contacter le Webmestre. |