Vous êtes sur la page 1sur 19

Du C/C++ Java : Cration et utilisation des classes

Page 1

Le langage JavaTM

Cration et utilisation des classes


Dclaration des classes et des interfaces Dclaration des champs Dclaration des mthodes Cration d'objets : oprateur new Outrepasser une mthode Destruction des objets

Dclaration des classes et des interfaces


Les seuls types que le programmeur peut dfinir en Java sont des classes ou des interfaces. Donc, les mots-cls struct et union n'existent pas en Java. Les numrations enum disponibles partir de Java 5.0, sont en fait des catgories de classes spciales. De plus, l'quivalent des template n'existe que depuis Java 5.0 aussi. Identifiants Les identifiants que vous crez en Java (classes, interfaces, champs, mthodes, paramtres, variables locales,...) peuvent tre n'importe quelle suite illimite de lettres ou de chiffres Unicode, de caractres _ ou $. Seul le premier caractre ne doit pas tre un chiffre. Ils doivent bien sr tre diffrents des mots-cls Java. Par consquent, il est possible d'utiliser des caractres accentues pour une meilleure lisibilit de vos programmes. Les identifiants sont cods comme en C/C++, mais en Java vous pouvez utilisez en plus toutes les lettres et tous les chiffres Unicode et le caractre $. Comme en C, le compilateur fait la nuance entre les minuscules et les majuscules. Vous pouvez crer des identifiants avec des lettres accentues, ce qui n'est pas conseill car la plupart des diteurs de texte et des systmes fonctionnant en ligne de commande (comme MS/DOS ou UNIX) n'utilisent pas Unicode pour les lettres accentues (qui ne sont pas ASCII). Les classes La dclaration d'une classe peut prendre une des formes suivantes :
// Dclararation d'une classe simple ModificateurDeClasse 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 ModificateurDeClasse 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 ModificateurDeClasse 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 ModificateurDeClasse class NomDeClasse3 extends NomDeSuperClasse implements NomInterface //, NomInterface2, ... { // Corps de NomDeClasse3 : // Dclaration des champs, des mthodes, des constructeurs // et/ou initialisations static

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes


// et/ou initialisations static // et implmentation des mthodes de nomInterface }

Page 2

Le corps d'une classe est une suite quelconque de dclaration de champs, de mthodes, de constructeurs et/ou d'initialisations static. A partir de Java 1.1, le corps d'une classe peut aussi dclarer des classes internes, des interfaces internes et des initialisations d'instance. 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.
ModificateurDeClasse public

est optionnel et peut prendre une ou plusieurs des valeurs suivantes :

: 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 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 dmontre 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).

figure 4. Symbolisation des modificateurs d'accs aux classes Contrairement au C++, le point-virgule en fin de dclaration d'une classe est optionnel. En Java, on utilise la clause extends pour prciser la super classe d'une classe drive, la place des deux points qui suivent la dclaration d'une classe en C++. L'hritage se fait systmatiquement de manire public en Java. Il n'existe pas d'quivalence la dclaration C++ : class Classe2 : private Classe1 { /* ... */ }. Une classe abstraite doit tre dclare abstract en Java et peut contenir aucune ou plusieurs mthodes abstract (quivalent des mthodes virtuelles pures du C++). Les modificateurs d'accs de classe public et final n'ont pas d'quivalent en C++. En Java une classe et tout ce qu'elle contient devant tre dclare entirement dans un seul fichier, il n'est pas possible comme en C++ de rpartir les mthodes d'une mme classe sur plusieurs fichiers. 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 ModificateurInterface interface NomInterface { // Corps de NomInterface : // Dclaration des constantes et des mthodes non implmentes } // Dclaration d'une interface drivant d'une super interface ModificateurInterface interface NomInterfaceDerivee extends NomSuperInterface //, NomSuperInterface2, ... { // Corps de NomInterfaceDerivee : // Dclaration des constantes et des mthodes non implmentes }

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes


// Dclaration des constantes et des mthodes non implmentes }

Page 3

A partir de Java 1.1, le corps d'une interface peut aussi dclarer des classes internes et des interfaces internes. II est impossible de crer une instance d'une interface. Une ou plusieurs interfaces peuvent suivre la clause extends. Une classe non abstract, qui implmente une interface Interface1 doit implmenter le code de chacune des mthodes de Interface1. L'implmentation d'une mthode est l'ensemble des instructions que doit excuter une mthode. ModificateurInterface est optionnel et peut prendre une ou plusieurs des valeurs suivantes : : Une seule interface ou classe peut tre dclare public par fichier source. Par convention, le fichier porte le nom de l'interface dclare public. Si d'autres interfaces (non public) sont dclares dans un fichier Interface1.java, elles ne peuvent tre utiliss que dans les fichiers qui appartiennent au mme package que Interface1.java. Une interface ne peut porter le mme nom qu'une classe. abstract : Toute interface est implicitement abstract. Ce modificateur est permis mais pas obligatoire.
public

A quoi sert une interface et quelle est la diffrence avec une classe abstract ? Tout d'abord, vous noterez qu'une classe ne peut hriter que d'une super classe, mais par contre peut implmenter plusieurs interfaces. Ensuite, une classe abstract peut dclarer des champs qui ne sont pas des constantes et implmenter certaines mthodes. Soit une classe Classe1 qui implmente toutes les mthodes d'une interface Interface1. Cette classe peut dclarer d'autres mthodes, ce qui compte c'est que chaque instance de cette classe garantit qu'au moins toutes les mthodes d'Interface1 existent et peuvent tre appeles, comme dans l'exemple suivant :
interface CouleurDominante { // Dclaration d'une mthode QuelleCouleurDominante () } class Classe1 extends SuperClasse1 implements CouleurDominante { // Corps de la mthode QuelleCouleurDominante () // Autres mthodes ventuelles } class Classe2 extends SuperClasse2 implements CouleurDominante { // Corps de la mthode QuelleCouleurDominante () // Autres mthodes ventuelles } class ClasseAyantBesoinDeLaCouleurDominante { CouleurDominante objetColore; // On peut affecter objetColore une rfrence // un objet de classe Classe1 ou Classe2 // et ainsi obtenir la couleur dominante d'un objet color en invoquant // la mthode QuelleCouleurDominante () sur la variable objetColore }

Une interface peut tre utilise pour masquer l'implmentation d'une classe. Ce concept est utilis dans plusieurs packages Java dont java.awt.peer : Ce package dclare un ensemble d'interfaces qui offrent les mmes mthodes sur chaque Machine Virtuelle Java mais qui sont implmentes diffremment pour que l'interface utilisateur du systme (bouton, fentre,...) soit utilise. 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, comme dans l'exemple suivant :
interface ConstantesCommunes { // Dclaration des constantes A, B et C } class Classe1 extends SuperClasse1 implements ConstantesCommunes { // Les constantes A, B et C sont utilisables dans la classe Classe1 } class Classe2 extends SuperClasse2 implements ConstantesCommunes { // Les constantes A, B et C sont utilisables dans la classe Classe2 }

Une classe qui implmente une interface InterfaceDerivee drive d'une autre interface Interface1 doit implmenter les mthodes des deux interfaces InterfaceDerivee et Interface1. http://www.eteks.com/coursjava/creationclasses.html 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes Une classe qui implmente une interface InterfaceDerivee drive d'une autre interface Interface1 doit implmenter les mthodes des deux interfaces InterfaceDerivee et Interface1. Java ne permet pas l'hritage multiple. Mais l'utilisation des interfaces peut compenser cet absence, car une classe peut implmenter plusieurs interfaces. Voir aussi le chapitre sur le portage.

Page 4

Si vous avez quelque mal au dpart comprendre le concept d'interface et leur utilit, considrez les simplement comme des classes abstract, dclarant des constantes et des mthodes abstract. Vous en percevrez leur intrt au fur et mesure que vous serez amen vous en servir.

Dclaration des champs


Le corps d'une classe est un ensemble de dclarations de champs (fields) et de mthodes implmentes ou non, dclares dans n'importe quel ordre. Syntaxe Les dclarations de champs se font comme en C/C++ :
class Classe1 { // Dclaration de champs TypeChamp champ1; TypeChamp champ2, champ3; ModificateurDeChamp TypeChamp champ4; TypeChamp champ5 = valeurOuExpression;

// Initialisation d'un champ

// Cration d'une rfrence sur un tableau TypeChamp tableau1 [ ]; // Allocation d'un tableau de taille n initialis avec les n valeurs TypeChamp tableau2 [ ] = {valeur1, valeur2, /*..., */ valeurn}; // ... } TypeChamp est soit un type primitif, soit le nom d'une classe, soit le nom d'une interface. Dans les deux derniers cas, le champ est une rfrence sur un objet. Les tableaux sont cits ici en exemple de champ et sont traits dans la partie sur les tableaux. ModificateurDeChamp est

optionnel et peut tre un ou plusieurs des mots-cls suivants :

public, protected ou private : Un champ public est accessible partout o est accessible la classe Classe1 dans laquelle il est dclar. Un champ protected est accessible par les autres classes du mme package que Classe1, et par les classes drives de Classe1. Un champ private n'est accessible qu' l'intrieur du corps de Classe1. static : Si un champ est static, il est cre en un unique exemplaire quelque soit le nombre d'instance de Classe1 : c'est un champ de classe. L'accs la valeur de ce champ se fait grce l'oprateur point (.) en indiquant le nom de la classe ou une rfrence un objet (Classe1.champ ou objetClasse1.champ). A l'oppos, si un champ n'est pas static, chaque nouvelle instance objetClasse1 de Classe1 crera un champ pour objetClasse1 : c'est une champ d'instance. L'accs la valeur de ce champ se fait grce l'oprateur point (.) , de la manire objetClasse1.champ. final : Un champ final n'est pas modifiable une fois initialis : c'est une constante qui peut prendre une valeur initiale diffrente

d'un objet l'autre d'une mme classe. Si ce champ a toujours la mme valeur d'initialisation, il vaut mieux optimiser votre code en y ajoutant static pour en faire une constante de classe. Les champs dclares dans le corps d'une interface sont des constantes implicitement public, final et static, et doivent tre initialiss avec une expression constante. transient : Un champ transient sert indiquer aux mthodes grant la persistance qu'elle ne fait pas partie de la persistance de l'objet. Cette fonctionnalit n'a t mise en oeuvre qu' partir de Java 1.1, et sert viter de sauvegarder des champs ne servant qu' des calculs intermdiaires (indices par exemple). volatile : Un champ volatile permet d'tre sr que deux threads (tches) auront accs de manire ordonne ce champ (modificateur implment uniquement partir de Java 1.1). Voir aussi le chapitre sur les threads. Un champ volatile ne peut tre aussi final.

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes

Page 5

figure 5. Symbolisation des modificateurs d'accs aux champs Le modificateur d'accs un champ est soit public, soit protected, soit private, soit par dfaut, si aucun de ces modificateurs n'est prcis, amical (friendly en anglais) : le champ est alors accessible uniquement par les autres classes du mme package. Les liens de la figure prcdente indique les endroits o il est possible d'utiliser un champ. Comme vous pouvez le voir, l'utilisation d'un champ se fait directement par son nom l'intrieur d'une classe et de ses classes drives, sans besoin d'utiliser l'oprateur point (.). L'initialisation d'un champ se comporte exactement comme l'affectation. Si le champ est static, alors l'initialisation est effectue au chargement de la classe. Les champs non initialiss prennent obligatoirement une valeur par dfaut (voir le tableau sur les types primitifs). Si ce champ est une rfrence un objet, la valeur par dfaut est null. Une classe Classe1 peut dclarer un champ qui est une rfrence une classe Classe2 dclare aprs Classe1 (pas besoin de dclarer les types avant de les utiliser comme en C). En Java, le modificateur final est utilis pour dclarer une constante (pas de #define, ni de const). Contrairement au C/C++, Java permet d'initialiser la dclaration les champs de classe ainsi que les champs d'instance. Les champs d'instance et de classe sont tous initialiss une valeur par dfaut. En C++, il est obligatoire d'initialiser les champs de classe part ; en Java, soit ces champs prennent une valeur par dfaut, soit ils sont initialiss leur dclaration, soit ils sont initialiss dans un bloc d'initialisation static. L'accs aux champs static se fait grce l'oprateur point (.) et pas l'oprateur ::, comme en C++. De plus, si vous voulez donner une valeur par dfaut aux champs static, vous le faites directement la dclaration du champ, comme par exemple static int var = 2;. Le modificateur d'accs aux champs (et aux mthodes) se fait pour chacune d'eux individuellement, et pas en bloc comme en C++ (avec par exemple public :). Les champs (et les mthodes) d'une classe Classe1 dont le modificateur d'accs est protected sont accessibles par les classes drives de Classe1 comme en C++, mais aussi par les classes du mme package que Classe1. En Java, les champs (et les mthodes) d'une classe Classe1 ont un modificateur d'accs par dfaut qui est amical (friendly), c'est dire qu'elles sont accessibles uniquement par les autres classes du mme package que Classe1. En C ++, cette notion n'existe pas et par dfaut le modificateur d'accs est private. Le modificateur d'accs par dfaut de Java est trs pratique car il donne accs tous les champs et toutes les mthodes des classes d'un mme package. Mais attention, si aprs avoir dvelopp certaines classes, vous pensez qu'elles peuvent vous tre utiles pour d'autres programmes et qu'ainsi vous les mettez dans un nouveau package outils, il vous faudra ajouter les modificateurs d'accs public pour accder en dehors du package outils aux mthodes et champs dont vous avez besoin. Donc, prenez l'habitude de prciser ds le dpart les modificateurs d'accs des champs et des mthodes. Initialisations static Le corps d'une classe peut comporter un ou plusieurs blocs d'initialisation static. Ces blocs sont excuts au chargement d'une classe, et permettent d'excuter des oprations sur les champs static. Ils sont excuts dans l'ordre de dclaration et peuvent ne manipuler que les champs static dclars avant le bloc.
class Classe1 { // Dclaration de champs static static int champ1 = 10; static int champ2; static //

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes


{ } // ... } // Bloc static champ2 = champ1 * 2;

Page 6

Sur une mme Machine Virtuelle Java, vous pouvez trs bien excuter diffrentes applets ou applications l'une aprs l'autre ou en mme temps grce au multi-threading. Par contre, chaque classe ClasseX n'existe qu'en un seul exemplaire pour une Machine Virtuelle, mme si ClasseX est utilise par diffrentes applets. Ceci implique que les champs static de ces classes sont uniques pour une Machine Virtuelle, et partags entre les diffrentes applets. Donc, attention aux effets de bord ! Si vous modifiez la valeur d'un champ static dans une applet, il sera modifi pour toutes les applets amenes utiliser ce champ. Ceci est opposer au C, o les champs static sont uniques pour chaque contexte d'excution d'un programme. Initialisations d'instance A partir de Java 1.1, le corps d'une classe peut comporter un ou plusieurs blocs d'initialisation d'instance. Comme pour les constructeurs, ces blocs sont excuts la cration d'un nouvel objet dans l'ordre de dclaration.
class Classe1 { // Dclaration d'un champ comptant le nombre d'instances cres static int nombreInstances = 0; // Dclaration d'un champ d'instance int champ1; { // Bloc d'instance champ1 = 10; nombreInstances++;

} // ... }

Dclaration des mthodes


Syntaxe Les dclarations des mthodes en Java ont une syntaxe trs proche de celles du C/C++ :
class Classe1 { // Dclarations de mthodes ModificateurDeMethode TypeRetour methode1 (TypeParam1 param1Name /*,... , TypeParamN paramNName*/) { // Corps de methode1 () } // Dclaration d'une mthode sans paramtre TypeRetour methode2 () { // Corps de methode2 () } ModificateurDeMethode TypeRetour methode3 (/* ... */) throws TypeThrowable /*, TypeThrowable2 */ { // Corps de methode3 () } // Dclaration d'une mthode abstract // Dans ce cas, Classe1 doit tre aussi abstract abstract ModificateurDeMethode TypeRetour methode4 (/* ... */); // Dclaration d'une mthode native native ModificateurDeMethode TypeRetour methode4 (/* ... */); // ... } TypeRetour

peut tre :

soit un type primitif, une classe ou une interface : dans ce cas, la mthode doit utiliser l'instruction return suivie d'une valeur du type TypeRetour, pour renvoyer une valeur. Le type peut tre une rfrence un tableau en utilisant [ ] (par exemple, int [ ] methode () ). http://www.eteks.com/coursjava/creationclasses.html 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes soit un type primitif, une classe ou une interface : dans ce cas, la mthode doit utiliser l'instruction return suivie d'une valeur du type TypeRetour, pour renvoyer une valeur. Le type peut tre une rfrence un tableau en utilisant [ ] (par exemple, int [ ] methode () ). soit void quand la mthode ne renvoie pas de valeur. Les paramtres d'une mthode sont cits entre parenthses et spars par des virgules. Chaque paramtre est prcd par son typeTypeParami qui peut tre un type primitif, une classe ou une interface.
TypeThrowable doit

Page 7

tre une classe drive de la classe Throwable. Les exceptions qui sont dclenches via l'instruction throw doivent avoir leur classe dclare aprs la clause throws. Voir le chapitre traitant des exceptions. est optionnel et peut tre un ou plusieurs des mots-cls suivants :

ModificateurDeMethode

public, protected ou private : Une mthode public est accessible partout o est accessible la classe Classe1 dans laquelle elle est dclare. Ce sont les mthodes public que l'utilisateur d'une classe peut appeler. Une mthode protected est accessible par les autres classes du mme package que Classe1, et par les classes drives de Classe1. Une mthode private n'est accessible qu' l'intrieur du corps de Classe1. Les mthodes private sont typiquement des

routines internes de calcul pour lesquels il n'y a pas de raison de donner un accs l'utilisateur d'une classe. : Si une mthode est static, c'est une mthode de classe qui ne peut utiliser que les champs et les mthodes de Classe1, qui sont dclares static. L'appel cette mthode se fait grce l'oprateur point (.) en indiquant le nom de la classe ou une rfrence un objet (Classe1.methode () ou objetClasse1.methode ()). A l'oppos, si une mthode n'est pas static, c'est une mthode d'instance, accessible pour chaque instance objetClasse1 de Classe1 grce l'oprateur point (.) , de la manire objetClasse1.methode () . Les mthodes dclares dans le corps d'une interface ne peuvent tre static. final : Une mthode final ne peut pas tre outrepasse par les classes drivant de Classe1. abstract : Une mthode abstract permet de dclarer une mthode d'instance sans en donner l'implmentation, et ne peut apparatre qu'au sein d'une classe abstract. Toute classe non abstract drive de cette classe, doit implmenter cette mthode, en l'outrepassant. Les mthodes dclares dans le corps d'une interface sont implicitement abstract et public. native : Une mthode native est implmente dans une bibliothque annexe propre la plateforme de dveloppement qui peut tre dveloppe en C ou en C++ par exemple. Ceci permet de faire appel certaines fonctionnalits propres la plateforme cible, qui ne seraient pas disponibles en Java. Mais une mthode native n'est pas portable... synchronized : Une mthode synchronized permet d'obtenir un verrou sur l'objet sur lequel elle est appele (ou sur la classe si la mthode est aussi static). Ce verrou empche qu'en cas de programmation multi-threads (multitches), diffrents threads aient accs de manire simultane un mme objet. Voir aussi la synchronisation des threads.
static

Le modificateur d'accs une mthode est soit public, soit protected, soit private. Leur utilisation est la mme que pour les champs. Dans la plupart des cas, il est conseill de ne rendre public que les mthodes et les constantes (champs final static), dont a besoin l'utilisateur d'une classe. Les autres champs sont dclars private voir friendly ou protected et sont rendus accessibles si besoin est, par des mthodes public permettant de les interroger et de les modifier (get... () et set... ()). Ceci permet de cacher aux utilisateurs d'une classe ses champs et de vrifier les conditions requises pour modifier la valeur d'un champ. Ce style de programmation est largement utilis dans la bibliothque Java. Pour les mthodes non abstract et non native, le corps de la mthode est un bloc, comportant une suite d'instructions dfinissant son implmentation. A l'intrieur de la dclaration d'une classe Classe1, l'appel toute mthode methode () de Classe1 ou de ses super classes, peut se faire directement sans l'oprateur point (.) ; l'utilisation de cet oprateur n'est obligatoire que pour accder aux mthodes des autres classes, comme dans l'exemple suivant :
class Classe1 { static public int Factorielle (int i) { if (i == 0) return 1; else return i * Factorielle (i - 1); // Factorielle () est directement accessible l'intrieur de Classe1 } } class Classe2 { // Pour accder la mthode Factorielle () de Classe1 // vous devez utilisez l'oprateur point. int factorielle10 = Classe1.Factorielle (10); }

Avant Java 5.0, Java ne permettait pas l'utilisation des listes d'arguments variables du C (dfini avec ...). Cette absence peut tre partiellement dtourne grce l'utilisation de la surcharge des mthodes. En Java chaque paramtre doit tre dclarer avec son type et un nom En C++ quand un paramtre est requis mais n'est http://www.eteks.com/coursjava/creationclasses.html 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes Contrairement au C/C++, dans une classe Classe1, vous pouvez utiliser tous les champs et les mthodes de Classe1 dans le corps de ses mthodes qu'ils soient dclars avant ou aprs dans Classe1, comme dans l'exemple suivant : class Classe1 { void methode1 () { x = 1; // x est dclar aprs methode2 (); // methode2 () est dclare aprs } void methode2 () { } int x; } Java ne permet pas de dclarer de variables ou de fonctions globales. Mais, si vous tenez absolument garder le style de programmation procdurale du C, vous pouvez crer et utiliser des champs et des mthodes static, dans ce but. La notion de fonction "amie" du C++ (friend) n'existe pas en Java : aucune mthode ne peut tre dclare en dehors d'une classe. Contrairement au C++, toutes les mthodes d'instance non private sont virtuelles en Java. Donc le mot-cl virtual est inutile, ce qui peut viter certains bugs difficiles dceler en C++. Les mthodes abstract sont l'quivalent des mthodes virtuelles pures du C++ (qui se dclarent en faisant suivre la dclaration de la mthode de = 0). Java introduit le mot-cl final. Ce modificateur empche d'outrepasser une mthode dans les classes drives. Cette notion est absente du C++. Toutes les mthodes Java sont dclares et implmentes l'intrieur de la classe dont elles dpendent. Mais, cela n'a pas pour consquence de crer comme en C++ toutes les mthodes de Java inline ! Avec l'option d'optimisation (-O), le compilateur lui-mme value les mthodes final qui peuvent tre traites inline (remplacement de l'appel la mthode par le code implmentant la mthode) : Donc, il est important d'utiliser ce modificateur quand cela est ncessaire (pour les mthodes d'accs aux champs par exemple). La surcharge des oprateurs n'existe pas en Java. Seule la classe String autorise l'oprateur + pour la concatnation. Java ne permet pas de donner aux paramtres des valeurs par dfaut comme en C++ (void f (int x, int y = 0, int z = 0); ). Vous tes obligs de surcharger une mthode pour obtenir les mmes effets, en crant une mthode avec moins de paramtres qui rappellera la mthode avec les valeurs par dfaut. L'appel aux mthodes static se fait grce l'oprateur point (.) et pas l'oprateur ::, comme en C++.

Page 8

Une mthode reoit la valeur de chacun des paramtres qui lui sont passs, et ces paramtres se comportent comme des variables locales : 1. Si un paramtre param est une rfrence sur un objet objet1, alors vous pouvez modifier le contenu de objet1 ; par contre, si vous affectez param une rfrence sur un autre objet, cette modification n'aura d'effet qu' l'intrieur du corps de la mthode. Si vous voulez mimer le passage par valeur, vous pouvez utiliser la mthode clone () de la classe Object pour crer une copie de l'objet objet1. 2. Si un paramtre est de type primitif, la modification de sa valeur n'a de porte qu' l'intrieur du corps de la mthode. Si vous voulez prendre en compte en dehors de la mthode la modification du paramtre, vous serez oblig de crer un objet dont la classe comporte un champ mmorisant cette valeur. Vous pourrez alors modifier la valeur comme indiqu en 1. (Voir aussi le chapitre traitant du portage de programmes C/C++ en Java). Surcharge des mthodes Une mthode methodeSurchargee (), est surcharge (overloaded) quand elle est dclare plusieurs fois dans une mme classe ou ses classes drives, avec le mme nom mais des paramtres de types diffrents, ou de mme type mais dans un ordre diffrent, comme dans l'exemple suivant :
class Classe1 { void methodeSurchargee (int entier) { // Corps de methodeSurchargee () } void methodeSurchargee (float nombre) {

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes


// Corps de methodeSurchargee () } } class Classe2 extends Classe1 { // Classe2 hrite de Classe1 donc elle dclare // implicitement toutes les mthodes de Classe1 void methodeSurchargee (float nombre, short param) { // Corps de methodeSurchargee () } }

Page 9

Il est autoris de surcharger une mthode en utilisant des paramtres de types diffrents pour chaque mthode. Les valeurs de retours peuvent tre aussi diffrentes, mais il est interdit de crer deux mthodes avec les mmes paramtres et un type de valeur de retour diffrent (par exemple, int methode () et float methode ()). En Java, une classe hrite de toutes les mthodes de la super classe dont elle drive, mme si elle surcharge une ou plusieurs des mthodes de sa super classe. Dans l'exemple prcdent, contrairement au C++, les mthodes que l'on peut invoquer sur un objet de classe Classe2 sont les 3 mthodes methodeSurchargee (int entier), methodeSurchargee (float nombre) et methodeSurchargee (float nombre, short param). En C++, le fait de surcharger la mthode methodeSurchargee () dans Classe2, interdit d'appeler directement sur un objet de classe Classe2 les mthodes surcharges de Classe1. Constructeur Chaque champ d'une classe peut tre initialis une valeur par dfaut sa dclaration. Mais si vous voulez initialiser certains de ces champs avec une valeur donne la cration d'un nouvel objet, il vous faut dclarer une mthode spciale appele un constructeur. Un constructeur est appele automatiquement la cration d'un objet, et les instructions du corps d'un constructeur sont gnralement destines initialiser les champs de l'objet nouvellement cr avec les valeurs rcupres en paramtre. Il a une syntaxe un peu diffrente de celle des mthodes :
class Classe1 { // Dclaration du constructeur sans paramtre remplaant le constructeur par dfaut public Classe1 () { // Corps du constructeur } ModificateurDeConstruceur Classe1 (TypeParam1 param1Name /* ... */) { // Corps du constructeur } ModificateurDeConstruceur Classe1 (/* ... */) throws TypeThrowable /*, TypeThrowable2 */ { // Corps du constructeur } }

Un constructeur porte le mme nom que la classe o il est dclar, et n'a pas de type de retour. A l'usage vous verrez que c'est une des mthodes qui est le plus souvent surcharge. Toute classe qui ne dclare pas de constructeur a un constructeur par dfaut sans paramtre qui ne fait rien. Ce contructeur a le mme modificateur d'accs que sa classe (contructeur par dfaut public si la classe est public). Aussitt qu'un constructeur est dclar avec ou sans paramtre, le constructeur par dfaut n'existe plus. Si vous avez dclar dans une classe Classe1 un constructeur avec un ou plusieurs paramtres, ceci oblige prciser les valeurs de ces paramtres la cration d'un objet de la classe Classe1.
TypeThrowable est

une classe drive de la classe Throwable. Les exceptions qui sont dclenches via l'instruction throw doivent avoir leur classe dclare aprs la clause throws. Voir le chapitre traitant des exceptions. est optionnel et peut tre un des mots-cls suivants : public, protected ou private. Ils sont utiliss de la mme manire que pour les dclarations de mthodes.

ModificateurDeConstruceur

Voici par exemple, une classe Classe1 n'utilisant pas de constructeur transforme pour qu'elle utilise un constructeur : class Classe1 class Classe1 { { int var1 = 10; int var1; int var2; int var2; } http://www.eteks.com/coursjava/creationclasses.html 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes } }

Page 10

Le constructeur Classe1 (int valeur) sera appel avec la valeur donne par l'instruction de cration d'un objet de classe Classe1. Ce constructeur permet ainsi de crer un objet de classe Classe1 dont le champ var1 est initialis avec une valeur diffrente pour chaque nouvel objet. Mais quel est l'intrt d'un constructeur puisqu'il est toujours possible de modifier la valeur d'un champ d'un objet aprs sa cration ? Un constructeur permet d'initialiser certains champs d'un objet ds sa cration, ce qui permet de garantir la cohrence d'un objet. En effet, mme si vous prcisez aux utilisateurs d'une classe qu'ils doivent modifier tel ou tel champ d'un nouvel objet avant d'effectuer certaines oprations sur celui-ci, rien ne garantit qu'ils le feront effectivement, ce qui peut tre source de bugs. Un constructeur permet justement d'viter ce genre de problme car tous les champs d'un objet seront correctement initialiss au moment de sa cration, ce qui garantit que les utilisateurs d'une classe pourront effectuer n'importe quelle opration sur un objet juste aprs sa cration. La plupart des classes de la bibliothque Java utilisant un ou plusieurs constructeurs, vous serez souvent amener les utiliser en crant des objets et ceci vous permettra de comprendre comment en dclarer vous-mme dans vos propres classes.

Les mthodes peuvent elles aussi porter le mme nom que la classe o elles sont dclares. Comme la distinction ne se fait alors que par la prsence d'un type devant le nom de la mthode, l'utilisation de cette caractristique est dconseille pour viter toute confusion avec un constructeur. class Classe1 { // Ceci est une mthode pas un constructeur ! public void Classe1 (int valeur) { // ... } } Le corps d'un constructeur peut ventuellement commenc par une des deux instructions suivantes :
this (argument1 /*, argument2, ...*/); super (argument1 /*, argument2, ...*/);

La premire instruction permet d'invoquer un autre constructeur de la mme classe : il est souvent utilis par un constructeur pour passer des valeurs pas dfaut aux paramtres d'un autre constructeur. La seconde instruction permet d'appeler un constructeur de la super classe pour lui repasser des valeurs ncessaires l'initialisation de la partie de l'objet dpendant de la super classe, comme dans l'exemple suivant :
class Classe1 { int var; Classe1 (int val) { var = val; } } class Classe2 extends Classe1 { int var2; Classe2 (int val) { // Appel du constructeur de Classe1 avec la valeur 3 super (3); var2 = val; } Classe2 () { // Appel du premier constructeur avec la valeur 2 this (2); } }

Si aucune des instructions prcdentes n'est cite, Java considre qu'il y a implicitement un appel super ();. Ceci implique que la super classe doit avoir un constructeur sans paramtre (dclar explicitement ou fourni par Java par dfaut), et que par enchanement, la cration de tout nouvel objet de classe invoquera le constructeur de sa classe et tous les constructeurs de des super classes. Donc si comme dans l'exemple prcdent vous crez une classe Classe2 qui drive d'une classe Classe1 n'ayant pas de constructeur par dfaut ou sans paramtre, vous serez obliger de dclarer au moins un constructeur dans Classe2 qui rappelle un constructeur de la classe Classe1 avec l'instruction super (...);.

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes

Page 11

A partir de Java 1.1, le corps d'une classe peut comporter aussi un ou plusieurs blocs d'initialisation d'instance, qui sont comparables au constructeur par dfaut. A la cration d'un objet, un objet d'une classe Classe1 est initialis dans l'ordre suivant : Si Classe1 hrite d'une super classe Classe0, appel d'un constructeur de Classe0 soit par un appel explicite super (...), ou implicitement si Classe0 possde une constructeur par dfaut. Excution d'ventuels blocs d'initialisation d'instance dclars dans Classe1. Excution du constructeur de Classe1. Java introduit le mot-cl super : il permet de passer des valeurs d'un constructeur d'une classe au constructeur de sa super classe grce l'appel super (arguments). En C++, il faut donner les paramtres passer au(x) constructeur(s) des supers classes la suite de la dclaration d'un constructeur. Contrairement au C++, les constructeurs d'une mme classe peuvent s'appeler entre eux en Java grce this (...). Cette fonctionnalit est trs pratique pour remplacer l'absence de valeur par dfaut des paramtres des constructeurs. Java ne permet de passer les objets en paramtre que par rfrence. Le constructeur par recopie du C++, appel pour construire les objets passs par valeur, n'est pas utile.

Cration d'objets : oprateur new


La cration d'objet (on dit aussi l'instanciation d'une classe) se fait grce l'oprateur new suivi d'un nom de classe et des arguments envoys au constructeur :
new Classe1 (/* argument1, argument2, ...*/)

Un nouvel objet de classe Classe1 est cr, l'espace mmoire ncessaire pour les champs d'instance est allou, ces champs sont ensuite initialiss puis finalement le constructeur correspondant aux types des arguments est appel. La valeur renvoye par l'oprateur peut tre affecte une rfrence de classe Classe1 ou de super classe de Classe1 (voir les casts). Si Classe1 n'a pas encore t utilise, l'interprteur charge la classe, alloue l'espace mmoire ncessaire pour mmoriser les champs static de la classe et excutent les initialisations static. A partir de Java 1.1, il est possible de crer des objets ayant une classe anonyme. La mthode newInstance () de la classe Class permet aussi de crer un nouvel objet. Cette mthode est quivalente utiliser new sans argument, et donc si vous voulez utiliser newInstance () pour crer un objet de classe Classe1, Classe1 doit avoir un constructeur sans paramtre (celui fourni par dfaut ou dclar dans la classe), sinon une exception NoSuchMethodError est dclenche. Voir aussi l'application InstantiationAvecNom. A partir de Java 1.1, les mthodes newInstance () des classes java.lang.reflect.Constructor et java.lang.reflect.Array permettent de crer un objet de n'importe quelle classe ayant un constructeur avec ou sans paramtres. Une exception OutOfMemoryError peut tre dclenche en cas de mmoire insuffisante pour allouer l'espace mmoire ncessaire au nouvel objet. La seule manire de crer des objets en Java se fait grce l'oprateur new. Vous ne pouvez pas comme en C++, crer des objets sur la pile d'excution. Maintenant que vous connaissez comment crer une classe, un constructeur et un objet en Java, comparons un programme simple C avec un programme Java : #include <stdlib.h> /* Dclaration du type Classe1 */ typedef struct { int var1; int var2; } Classe1;

// Dclaration de la classe Classe1 class Classe1 { int var1; int var2; // Constructeur de Classe1 // permettant d'initialiser // les champs var1 et var2 public Classe1 (int valeur1, int valeur2) { var1 = valeur1; var2 = valeur2; } // Mthode renvoyant la division // entre les champs de cet objet public int division () { return var1 / var2; } 08/01/2012 08:58:07

/* Fonction renvoyant la division */ /* entre les champs de objet */ int division (Classe1 *objet) { return objet->var1 / objet->var2; } http://www.eteks.com/coursjava/creationclasses.html

Du C/C++ Java : Cration et utilisation des classes /* Allocation puis initialisation */ /* d'une instance de Classe1 */ Classe1 *objet1 = (Classe1 *) calloc (1, sizeof (Classe1)) ; objet1->var1 = 10; objet1->var2 = 20; int quotient = division (objet1); } ; } } // Cration d'une instance de // Classe1 directement initialise Classe1 objet1 = new Classe1 (10, 20);

Page 12

int quotient = objet1.division ()

Outrepasser une mthode


Une mthode d'instance methodeOutrepassee () non private, est outrepasse (overridden) si elle est dclare dans une super classe et une classe drive, avec le mme nom, le mme nombre de paramtres, et le mme type pour chacun des paramtres. Les exemples qui suivent montrent l'intrt de ce concept : L'application suivante dcrit une gestion de comptes en banque simplifie et correspond au graphe d'hritage dcrit au chapitre prcdent (sans la classe PEL). Recopiez la dans un fichier Banque.java, que vous compilez avec l'instruction javac Banque.java pour ensuite l'excuter avec java ou Java Runner, grce l'instruction java Banque :
class Compte { private int numero; protected float soldeInitial; // Champ protected accessible // par les classes drives // Constructeur Compte (int nouveauNumero, float sommeDeposee) { // Mise jour des champs de la classe numero = nouveauNumero; soldeInitial = sommeDeposee; } int numeroCompte () { return numero; } float calculerSolde () { return soldeInitial; } } // La classe CompteDepot drive de la classe Compte class CompteDepot extends Compte { // Cration d'un tableau de 1000 float pour les oprations private float operations [] = new float [1000]; private int nbreOperations; // Initialise 0 // Constructeur CompteDepot (int nouveauNumero) { // Appel du constructeur de la super classe super (nouveauNumero, 0); } void ajouterOperation (float debitCredit) { // Mmorisation de l'opration et augmentation de nbreOperation operations [nbreOperations++] = debitCredit; } float calculerSolde () // outrepasse la mthode de la classe Compte { float solde = soldeInitial; // Somme de toutes les oprations for (int i = 0; i < nbreOperations; i++) solde += operations [i]; return solde; } }

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes


// La classe CompteEpargne drive de la classe Compte class CompteEpargne extends Compte { private float tauxInteretPourcentage; // Constructeur (tauxInteret en %) CompteEpargne (int nouveauNumero, float depot, float tauxInteret) { super (nouveauNumero, depot); tauxInteretPourcentage = tauxInteret; } float calculerSolde () // outrepasse la mthode de la classe Compte { return soldeInitial * (1f + tauxInteretPourcentage / 100f); } } // Classe d'exemple public class Banque { // Mthode lance l'appel de l'instruction java Banque public static void main (String [ ] args) { // Cration de 3 comptes de classe diffrente Compte compte101 = new Compte (101, 201.1f); CompteDepot compte105 = new CompteDepot (105); compte105.ajouterOperation (200); compte105.ajouterOperation (-50.5f); CompteEpargne compte1003 = new CompteEpargne (1003, 500, 5.2f); // Appel de la mthode editerSoldeCompte () sur chacun // des comptes. Cette mthode prend en paramtre une // rfrence de classe Compte : Les objets dsigns par // compte105 et compte1003 sont d'une classe qui drive // de la classe Compte, c'est pourquoi ils peuvent tre // accepts en paramtre comme des objets de classe Compte editerSoldeCompte (compte101); editerSoldeCompte (compte105); editerSoldeCompte (compte1003); } // Mthode ditant le numro et le solde d'un compte static void editerSoldeCompte (Compte compte) { // Rcupration du numro et du solde du compte // La mthode calculerSolde () qui est appele // est celle de la classe de l'objet dsign // par le champ compte int numero = compte.numeroCompte (); float solde = compte.calculerSolde (); System.out.println ( "Compte : " + numero + " Solde = " + solde); } }

Page 13

Le rsultat de ce programme donne ceci :


Compte : 101 Solde = 201.1 Compte : 105 Solde = 149.5 Compte : 1003 Solde = 526.0

La mthode editerSoldeCompte () reoit en paramtre la variable compte. compte est une rfrence dsignant une instance de la classe Compte, ou d'une des classes drives de Compte, ici CompteDepot ou CompteEpargne. Que se passe-t-il l'appel de la mthode calculerSolde () sur cette rfrence ? La Machine Virtuelle connait l'excution la classe de l'objet dsign par la rfrence compte : en plus, des champs d'instance qui sont alloues la cration d'une nouvelle instance des classes Compte, CompteDepot ou CompteEpargne, un champ cach qui reprsente la classe du nouvel objet lui est ajout. A l'appel compte.calculerSolde (), la Machine Virtuelle consulte ce champ pour connatre la classe de l'objet dsign par compte. Une fois qu'elle a cette classe elle appelle l'implmentation de la mthode calculerSolde () de cette classe, ce qui fait que la mthode calculerSolde () de la classe Compte ne sera effectivement appele que si l'objet dsign par compte est de classe Compte. Globalement en Java, la manire d'appeler une mthode d'instance quelle qu'elle soit, respecte ce schma : c'est la ligature dynamique (la bonne mthode appeler n'est pas dtermine statiquement la compilation, mais dynamiquement l'excution en fonction de la classe de l'objet dsign). A premire vue, son intrt parat pourtant limit aux mthodes outrepasses, mais souvenez-vous que toute classe qui

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes

Page 14

n'est pas final peut tre appele tre drive un jour, et que ses mthodes seront peut-tre outrepasses dans la classe drive. Il faut donc "prparer le terrain" pour ces mthodes... Une mthode outrepassant une autre ne peut avoir un modificateur d'accs plus restrictif que la mthode outrepasse (pas possible d'avoir un accs protected ou private si la mthode outrepasse est public). L'ordre de priorit des modificateurs d'accs est du plus restrictif au moins restrictif : private, friendly, protected et public. La notion de mthode outrepasse est fondamentale et contribue pour une grande part la puissance d'un langage objet. Elle est trs souvent utilise en Java, car il vous faut souvent outrepasser les mthodes des classes de la bibliothque Java pour modifier leur comportement par dfaut. On parle souvent aussi de polymorphisme. En Java, toutes les mthodes d'instance utilisent la ligature dynamique. Contrairement au C++, toutes les mthodes sont virtual. Faites trs attention bien respecter l'orthographe du nom des mthodes que vous outrepassez et les types de leurs paramtres. Si la nouvelle mthode cre a un nom diffrent, elle n'outrepassera plus celle de la super classe, le compilateur ne vous signalera rien et finalement la mthode appele pourra tre celle de la super classe au lieu de celle que vous avez dclare. Par contre, les noms des paramtres n'ont pas d'importance, et peuvent tre diffrents de ceux de la mthode outrepasse. Quand une mthode private est dclare nouveau dans une sous-classe, elle n'est pas spcialise. Contrairement ce qui se passe avec les mthodes outrepasses, il n'existe pas en Java de ligature dynamique sur les champs qu'ils soient static ou non, comme le montre l'exemple suivant : class Classe1 { final static int CONSTANTE = 0; } class Classe2 extends Classe1 { // Dclaration d'un champ (constante) qui cache celle de Classe1 final static int CONSTANTE = 1; void methode1 () { Classe2 objet2 = new Classe2 (); // cration d'un objet de classe Classe2 // var vaut 1 int var = objet2.CONSTANTE; Classe1 objet1 = objet2; // cast de Classe2 vers Classe1 var = objet1.CONSTANTE; // var vaut 0 pourtant objet1 est une rfrence // sur un objet de classe Classe2 ! } } Dans cet exemple, Classe2 a besoin de donner une valeur diffrente CONSTANTE pour les objets de cette classe : si on redclare cette constante dans Classe2 avec une valeur diffrente, on pourrait s'attendre ce que objet1.CONSTANTE vaille 1 puisque objet1 dsigne un objet de classe Classe2. En fait, objet1.CONSTANTE renvoie la valeur de CONSTANTE de la classe Classe1 car objet1 est de type Classe1... Si vous voulez que var vaille 1 dans les deux cas de cet exemple, vous devez crer une mthode dans chaque classe qui renvoie la valeur de CONSTANTE, comme par exemple : class Classe1 { public int valeur1 () { return 0; } } class Classe2 extends Classe1 { public int valeur1 () // valeur1 () outrepasse la mthode de Classe1 { return 1; } void methode1 () { 2 j 2 http://www.eteks.com/coursjava/creationclasses.html

//

j 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes // valeur1 () qui est appele (objet1 // est une rfrence sur un objet de // classe Classe2) } }

Page 15

Utilisation de classes abstract Les classes abstract sont une catgorie spciale de classe : il est impossible de crer une instance d'une classe abstract classeAbstract, mais par contre il est possible de dclarer un champ var1 qui est une rfrence de classe classeAbstract. var1 peut tre gal null ou dsigner un objet d'une des classes drives de la classe classeAbstract la condition suivante : Si la classe classeAbstract dclare une ou plusieurs mthodes d'instance abstract, la classe drive doit outrepasser ces mthodes et donner leur implmentation. Si cette classe ne donne pas l'implmentation de toutes les mthodes abstract, elle est elle-mme abstract. Rappelez-vous qu'en fait, pour crer une instance d'une classe Classe1, il faut que toutes les mthodes de cette classe soient implmentes pour pouvoir les appeler, que ces mthodes soient dclares dans Classe1 ou hrites des super classes de Classe1. Si une super classe dclare des mthodes abstract il faut donc que ces mthodes soient implmentes. De mme, une interface est une sorte de classe abstract dont toutes les mthodes sont implicitement abstract. C'est pourquoi toute classe qui implmente une interface, doit implmenter toutes les mthodes de l'interface pour ne pas tre abstract. L'exemple suivant vous montre l'intrt de l'utilisation d'une classe abstract :
abstract class Vehicule { abstract int nombreDeRoues (); } class Velo extends Vehicule { int nombreDeRoues () // outrepasse nombreDeRoues () de la classe Vehicule { return 2; } } class Voiture extends Vehicule { int nombreDeRoues () // outrepasse nombreDeRoues () de la classe Vehicule { return 4; } } class VoitureAvecRemorque extends Voiture { int nombreDeRoues () // outrepasse nombreDeRoues () de la classe Voiture { // super.nombreDeRoues () fait appel la mthode outrepasse return 2 + super.nombreDeRoues (); } } class Classe1 { // Cration de deux objets avec l'oprateur new Velo unVelo = new Velo (); Voiture uneVoiture = new Voiture (); // Dclaration d'une rfrence sur la super classe Vehicule // Comme la classe Vehicule est abstract, il est impossible de crer un // objet de cette classe, mais on peut affecter cette rfrence // de classe Vehicule, un objet d'une classe drive de Vehicule Vehicule unVehicule; void methode () { int a = unVelo.nombreDeRoues (); int b = uneVoiture.nombreDeRoues (); unVehicule = unVelo; int c = unVehicule.nombreDeRoues (); unVehicule = uneVoiture; int d = unVehicule.nombreDeRoues (); } }

// a est gal 2 // b est gal 4 // cast // c est // cast // d est de Velo vers Vehicule gal 2 de Voiture vers Vehicule gal 4

Dans cet exemple, unVehicule est une rfrence permettant de dsigner un objet de classe Vehicule ou toute autre classe drive de Vehicule. Quand nombreDeRoues () est invoque sur la rfrence unVehicule, l'interprteur va consulter la classe relle d'appartenance de l'objet rfrenc par unVehicule ; une fois, qu'il a dtermin cette classe, il va appeler la mthode nombreDeRoues () de cette classe.

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes Classe0::methode1 (). Mais ceci n est pas souvent utilis... Java ne permet pas d'utiliser des pointeurs sur fonctions. Dans certains cas, l'utilisation des mthodes outrepasses est une alternative cette absence. Voici un programme C et un programme Java mis en parallle pour illustrer ce propos (l'exemple utilise une interface mais il est aussi possible d'utiliser une classe abstract) : /* Dclaration d'un type pointeur sur */ /* fonction prenant en paramtre un int */ typedef void (* methodeX) (int i); // Dclaration d'une interface dclarant // une mthode prenant en paramtre un int interface MethodeX { void methodeX (int i); }

Page 16

// Dclaration de deux classes /* Dclaration de deux fonctions du */ implmentant /* mme type que methodeX () */ // la mthode methodeX () de cette interface class Classe1 implements MethodeX void methodeX_1 (int i) { { /* Corps de methodeX_1 () */ } public void methodeX (int i) { /* Corps de methodeX () */ } } class Classe2 implements MethodeX { public void methodeX (int i) { /* Corps de methodeX () */ } } // Dclaration d'une classe utilisant // methodeX () de diffrentes classes class ClasseUtilisantMethodeX { // Mthode appelant la mthode methodeX () // d'une classe implmentant MethodeX void appelMethodeX (MethodeX objet, int i) { objet.methodeX (i); } void appelMethodeXClasse1 () { // Appel de methodeX () de Classe1 // La rfrence dsignant l'objet cr // avec new Classe1 () peut tre // cast en MethodeX car // Classe1 implmente MethodeX appelMethodeX (new Classe1 (), 5); } void appelMethodeXClasse2 () { // Appel de methodeX () de Classe2 appelMethodeX (new Classe2 (), 10); } }

void methodeX_2 (int i) { /* Corps de methodeX_2 () */ }

/* Mthode appelant la mthode */ /* de type methodeX */ void appelMethodeX (methodeX methode, int i) { methode (i); } void appelMethodeXClasse1 () { /* Appel de methodeX_1 () */ appelMethodeX (methodeX_1, 5); }

void appelMethodeXClasse2 () { /* Appel de methodeX_2 () */ appelMethodeX (methodeX_2, 10); }

Destruction des objets


Java gre de manire automatique pour le programmeur l'allocation dynamique de mmoire. La mmoire ncessaire la mmorisation de tout nouvel objet est alloue dynamiquement sa cration, et la mmoire qu'il occupe est automatiquement libre quand celui-ci n'est plus rfrenc par aucune variable du programme. Cette libration est ralise grce au Garbage Collector (littralement Ramasseur d'Ordure) fourni avec la Machine Virtuelle Java. Cette fonctionnalit trs pratique de Java simplifie normment la programmation, d'autant plus qu'elle implique que la notion de

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes

Page 17

destructeur (mthode appele la destruction d'un objet en C++, trs souvent utilise pour librer la mmoire utilise par un objet) est beaucoup moins utile en Java. Toutefois, Java fournit une mthode outrepasser dans vos classes si vous avez besoin d'effectuer certains traitements spcifiques la destruction d'un objet : void finalize (). Cette mthode est invoque juste avant que le Garbage Collector ne rcupre la mmoire occupe par l'objet. Normalement, vous ne l'utiliserez que rarement mais elle peut tre utile pour librer certaines ressources dont Java ne greraient pas directement la destruction (contextes graphiques, ressources ou mmoire allous par des mthodes native crites en C ou C++). Vous pouvez ventuellement indiquer la Machine Virtuelle qu'une rfrence var1 dsignant un objet n'est plus utile en la mettant null (var1 = null;), pour que le Garbage Collector puisse dtruire l'objet dsign par var1 si celui-ci n'est plus dsign par aucune rfrence. En java, la destruction des objets se fait automatiquement quand ils ne sont plus utiliss (rfrencs). L'oprateur delete du C++ servant dtruire explicitement les objets crs dynamiquement est donc inutile. En java, il n'existe pas de syntaxe prdfinie pour les destructeurs. Vous pouvez outrepasser la mthode finalize () pour "nettoyer" vos objets mais contrairement au destructeur du C++ o le destructeur est invoqu l'appel de delete (), finalize () est invoque automatiquement par le Garbage Collector quand un objet n'a plus aucune rfrence le dsignant et qu'il peut donc tre dtruit. Le moment prcis o va intervenir le Garbage Collector n'est pas prvisible, donc s'il vous faut effectuer des oprations obligatoires quand un objet devient inutile (effacement d'un dessin l'cran par exemple), c'est vous de crer une mthode que vous invoquerez au moment voulue (vous pouvez l'appeler delete () si vous voulez). Comme en C++, les objets Java sont allous dynamiquement leur cration via l'oprateur new. En Java, c'est le seul moyen d'allouer de la mmoire, donc il n'existe plus de fonctions telles que malloc (), realloc () ou free (). L'oprateur sizeof () servant surtout pour valuer la taille d'un objet allouer n'existe plus non plus. En C, sizeof () est utile aussi pour la portabilit d'un programme, car tous les types primitifs n'ont pas la mme taille suivant les systmes (int peut avoir une taille de 16 ou 32 bits, par exemple) : en Java, tous les types primitifs ont la mme taille. Comment a marche ? Pour mieux comprendre comment Java manipule les objets de leur cration leur destruction, voici une figure dcrivant la vie d'un objet :

figure 7. La vie d'un objet Java de sa cration sa destruction Ce programme trs simple vous montre la nuance trs importante entre une rfrence et un objet : un mme objet peut avoir n'importe quel nombre de rfrences le dsignant, mais une rfrence ne peut dsigner qu'un seul objet la fois. A tout moment, la Machine Virtuelle connat le nombre de rfrences (ou de variables) qui dsignent chacun des objets d'un programme : quand pour un objet, ce nombre devient nul, ceci signifie que plus aucune variable du programme ne dsigne cet objet. S'il n'existe plus de variable dsignant cet objet, le programme n'a donc plus de moyen de le manipuler, il est logique de le considrer comme inutile et de le supprimer. Pour vous montrer toute la puissance et l'intrt du Garbage Collector, voici un programme C et un programme Java mettant en oeuvre l'utilisation de listes chanes : #include <stdlib.h> /* Dclaration d'un type de liste http://www.eteks.com/coursjava/creationclasses.html

// Dclaration d'une classe de liste 08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes struct _eltListe *suivant; } EltListe, *ListeChainee; /* Cre une liste d'lments ayant // Construit une liste */ ayant /* leur nombre compris entre min et max // leur nombre compris */ max ListeChainee creerListe (int min, int ListeChainee (int min, max) { { ListeChainee elt = (ListeChainee) malloc (sizeof (EltListe)); nombre = min; elt->nombre = min; if (min < max) if (min < max) suivant = elt->suivant = new ListeChainee creerListe (min +1, max); max); else else elt->suivant = NULL; suivant = null; return elt; } } /* Enlve un lment individuel */ ListeChainee enleverElement (ListeChainee liste, int nombre) { ListeChainee eltCherche; ListeChainee eltPrecedent = NULL; /* Recherche de l'lment contenant */ /* le nombre */ for (eltCherche = liste; eltCherche != NULL; eltCherche = eltCherche->suivant) if (eltCherche->nombre != nombre) eltPrecedent = eltCherche; else { /* Suppression de l'element */ /* de la liste chane */ if (eltCherche == liste) liste = liste->suivant; else eltPrecedent->suivant = eltCherche->suivant; free (eltCherche); } return liste; } /* Libre la mmoire prise par tous */ /* les lments de la liste */ void viderListe (ListeChainee liste) { while (liste != NULL) { ListeChainee eltPrecedent = liste; liste = liste->suivant; free (eltPrecedent); } } void main () { ListeChainee liste = creerListe (1, 10); li t l El t (li t http://www.eteks.com/coursjava/creationclasses.html public static void main 8) d'lments entre min et int max) ListeChainee suivant;

Page 18

(min + 1,

// Enlve un lment individuel ListeChainee enleverElement (int nombre) { ListeChainee eltCherche; ListeChainee eltPrecedent = null; // Recherche de l'lment contenant // le nombre (this dsigne la tte // de liste elle-mme) for (eltCherche = this; eltCherche != null; eltCherche = eltCherche.suivant) if (eltCherche.nombre != nombre) eltPrecedent = eltCherche; else // Suppression de la rfrence sur // de l'element recherche, l'objet // peut donc tre supprim if (eltCherche == this) return this.suivant; else eltPrecedent.suivant = eltCherche.suivant; return this; } // void viderListe () // est inutile

08/01/2012 08:58:07

Du C/C++ Java : Cration et utilisation des classes liste = liste.enleverElement (8); liste = null; } }

Page 19

L'instruction liste = null entrane que l'unique rfrence sur l'objet de tte de liste est perdue, donc le Garbage Collector peut supprimer cet objet. Quand il le supprime, le champ suivant de cet objet est supprime et il n'existe plus de rfrence sur l'lment suivant. Ce dernier peut tre supprim son tour, ainsi de suite jusqu' qu'au dernier lment de la liste. Dans cet exemple, liste = null n'est mme pas obligatoire car la variable locale liste est supprime la sortie de la mthode main (), ce qui provoque les mmes effets. Une fois compris l'exemple prcdent, vous pouvez essayer de crer partir de celui-ci une classe de liste doublement chane (avec liens suivant et precedent). Si vous ne voulez pas croire en la magie, il vous faudra srement un certain temps pour faire confiance au Garbage Collector sans arrire pense. Ce type de gestion de la mmoire tant trs pratique, le rflexe de ne plus librer la mmoire explicitement comme en C/C++ (avec free () ou delete) s'acquire d'office, mais vous prendrez plus de temps comprendre comment vos objets sont dtruits dans telle ou telle situation. La meilleure piste pour rpondre vos interrogations, est de vous demander par combien de variables sont rfrencs le ou les objets sur lesquels vous avez des doutes. Si par enchanement, ce nombre tombe 0, vous pouvez oublier vos doutes. Comme en Java, vous ne dtruisez pas explicitement les objets, toute rfrence est gale soit null soit elle dsigne un objet TOUJOURS valide. Vous ne pouvez pas avoir de risque de manipuler un objet qui n'existe plus comme dans le programme C suivant : void fonction1 () { char *chaine = malloc (20); strcpy (chaine, "bonjour\n"); /* ... */ free (chaine); /* ... */ printf (chaine); } En C, si dans un programme vous utilisez par erreur un pointeur aprs avoir libr l'espace mmoire qu'il dsigne, le compilateur ne vous indiquera aucune erreur. De plus, ce genre d'erreur est souvent difficile trouver. En Java, si vous essayez d'accder un objet par une rfrence gale null, une exception NullPointerException est dclenche.
Copyrights 1997-2007 Emmanuel PUYBARET / eTeks - Tous droits rservs -

http://www.eteks.com/coursjava/creationclasses.html

08/01/2012 08:58:07