Vous êtes sur la page 1sur 223

JAVA6

Les fondamentaux du langage Java

ThierryGROUSSARD

Rsum
Ce livre sadresse tout informaticien dsirant dvelopper sous Java. Que le lecteur soit dbutant ou quil ait dj une premire exprience avec un autre langage il trouvera dans cet ouvrage toutes les bases ncessaires pour se familiariser rapidement avec un des langages les plus utiliss au monde. Les trois premiers chapitres prsentent les bases du langage et de la programmation objet. Les chapitres suivants tudient le dveloppement dapplications graphiques avec la bibliothque Swing et la cration dapplets permettant denrichir facilement le contenu de pages web. Le dveloppement dapplications client/serveur est galement prsent avec lAPI JDBC assurant laccs aux bases de donnes. Le dploiement tant une tape importante du succs dune application, le dernier chapitre prsente la distribution dune application avec la solution classique des fichiers darchives ou lutilisation plus souple de la technologie Java Web Start. Le livre ne ncessite pas doutils de dveloppement spcifiques. Un diteur de texte et les outils disponibles gratuitement sur le site de Sun sont suffisants pour mener bien lapprentissage de ce langage passionnant et en plein essor. Les exemples cits dans louvrage sont en tlchargement sur cette page.

L'auteur
Analyste et dveloppeur pendant plus de 10 ans, Thierry Groussard s'est ensuite orient vers la formation et plus particulirement dans le domaine du dveloppement. Sa connaissance approfondie des besoins de l'entreprise et ses qualits pdagogiques rendent ses ouvrages particulirement adapts l'apprentissage et la mise en pratique d'un langage de dveloppement.

Ce livre numrique a t conu et est diffus dans le respect des droits dauteur. Toutes les marques cites ont t dposes par leur diteur respectif. La loi du 11 Mars 1957 nautorisant aux termes des alinas 2 et 3 de larticle 41, dune part, que les copies ou reproductions strictement rserves lusage priv du copiste et non destines une utilisation collective, et, dautre part, que les analyses et les courtes citations dans un but dexemple et dillustration, toute reprsentation ou reproduction intgrale, ou partielle, faite sans le consentement de lauteur ou de ses ayants droit ou ayant cause, est illicite (alina 1er de larticle 40). Cette reprsentation ou reproduction, par quelque procd que ce soit, constituerait donc une contrefaon sanctionne par les articles 425 et suivants du Code Pnal. Copyright Editions ENI

ENI Editions - All rigths reserved

- 1-

Historique
1.PourquoiJava?
Bill Joy, ingnieur chez SUN MICROSYSTEM, et son quipe de chercheurs travaillaient sur le projet "Green" qui consistait dvelopper des applications destines une large varit de priphriques et systmes embarqus (notammenttlphonescellulairesettlviseursinteractifs). Convaincus par les avantages de la programmation oriente objet (POO), ils choisissaient de dvelopper avec le langageC++prouvpoursesperformances. Mais,parrapportcegenredeprojet,C++arapidementmontrseslacunesetseslimites.Eneffet,denombreux problmes dincompatibilit se sont poss par rapport aux diffrentes architectures matrielles (processeurs, taille mmoire)etauxsystmesdexploitationrencontrs,ainsiquauniveaudeladaptation de linterfacegraphiquedes applicationsetdelinterconnexionentrelesdiffrentsappareils. EnraisondesdifficultsrencontresavecC++,iltaitprfrabledecrerunnouveaulangageautourdunenouvelle plateformededveloppement.DeuxdveloppeursdechezSUN,JamesGoslingetPatrickNaughtonsesontattels cettetche. La cration de ce langage et de cette plateforme sest inspire des fonctionnalits intressantes offertes par dautreslangagestelsqueC++,Eiffel,SmallTalk,ObjectiveC,Cedar/Mesa,Ada,Perl.Lersultatestuneplateforme et un langage idaux pour le dveloppement dapplications scurises, distribues et portables sur de nombreux priphriquesetsystmesembarqusinterconnectsenrseaumaisgalementsurInternet(clientslgers),etsur desstationsdetravail(clientslourds). DabordsurnommC++(C++sanssesdfauts)puisOAK,maisilsagissaitdunnomdjutilisdansledomaine informatique,ilfutfinalementbaptisJava,motdargotvoulantdirecaf,enraisondesquantitsdecafingurgit parlesprogrammeursetnotammentparsesconcepteurs.Etainsi,en1991,estnlelangageJava.

2.ObjectifsdelaconceptiondeJava
Par rapport aux besoins exprims, il fallait un langage et une plateforme simples et performants, destins au dveloppementetaudploiementdapplicationsscurises,surdessystmeshtrognesdansunenvironnement distribu,devantconsommerunminimumderessourcesetfonctionnersurnimportequelleplateformematrielleet logicielle. LaconceptiondeJavaaapportunerponseefficacecesbesoins:
q

Langage dune syntaxe simple, orient objet et interprt, permettant doptimiser le temps et le cycle de dveloppement(compilationetexcution). Lesapplicationssontportablessansmodificationsurdenombreusesplatesformesmatriellesetsystmes dexploitation. Lesapplicationssontrobustescarlagestiondelammoireestpriseenchargeparlemoteurdexcutionde Java(JavaRuntimeEnvironment),etilestplusfaciledcriredesprogrammessanserreurparrapportauC++, enraisondunmcanismedegestiondeserreursplusvoluetplusstrict. Lesapplicationsetnotammentlesapplicationsgraphiquessontperformantesenraisondelamiseen uvre etdelapriseenchargedufonctionnementdemultiplesprocessuslgers(Threadetmultithreading). Le fonctionnement des applications est scuris, notamment dans le cas dApplet Java o le moteur dexcution de Java veille ce quaucune manipulation ou opration dangereuse ne soit effectue par lApplet.

3.EssordeJava
Malgr la cration de Java, les dveloppements du projet "Green" nont pas eu les retombes commerciales escomptesetleprojetfutmisdect. cettepoque,lmergencedInternetetdesarchitecturesclient/serveurhtrognesetdistribuesaapportune certainecomplexitaudveloppementdesapplications.

ENI Editions - All rigths reserved

- 1-

LescaractristiquesdeJavasetrouventalorsgalementfortintressantespourcetypedapplications. Eneffet:
q

un programme Java tant peu encombrant, son tlchargement partir dun site Internet prend peu de temps. unprogrammeJavaestportableetpeutdonctreutilissansmodificationsousnimportequelleplateforme (Windows,Macintosh,Unix,Linux...).

Java se trouve alors un nouveau domaine dapplication sur le rseau mondial Internet, ainsi que sur les rseaux locauxdansunearchitectureIntranetetclient/serveurdistribue. PourprsenteraumondelespossibilitsdeJava,deuxprogrammeursdeSUN,PatrickNaughtonetJonathanPeayne ontcretprsentausalonSunWorldenmai1995unnavigateurWebentirementprogrammenJavadunomde HOTJAVA.CeluicipermetlexcutiondeprogrammesJava,nommsApplets,danslespagesauformatHTML. En aot 1995, la socit Netscape, trs intresse par les possibilits de Java, signe un accord avec SUN lui permettant dintgrer Java et limplmentation des Applets dans son navigateur Web (Netscape Navigator). En janvier1996,Netscapeversion2arrivesurlemarchenintgrantlaplateformeJava. CestdoncInternetquiaassurlapromotiondeJava. Fort de cette russite, SUN dcide de promouvoir Java auprs des programmeurs en mettant disposition gratuitement sur son site Web ds novembre 1995, une plateforme de dveloppement dans une version bta du nomdeJDK1.0(JavaDevelopmentKit). Peu aprs, SUN cre une filiale du nom de JAVASOFT (http://java.sun.com), dont lobjectif est de continuer dvelopperlelangage. Depuis, Java na fait quvoluer trs rgulirement pour donner un langage et une plateforme trs polyvalents et sophistiqus,etdegrandescompagniestellesqueBorland/Inprise,IBM,Oracle,pourneciterqueux,ontmistrs fortementsurJava. Javaestaujourdhuilepremierlangageobjetenseigndanslescolesetuniversitsenraisondesarigueuretde sarichessefonctionnelle. LacommunautdesdveloppeursJavareprsenteplusieursmillionsdepersonnesetestplusimportanteennombre quelacommunautdesdveloppeursC++(pourtantunerfrence).

- 2-

ENI Editions - All rigths reserved

CaractristiquesdeJava
Javaestlafoisunlangageetuneplateformededveloppement. Cettepartievousprsentecesdeuxaspects,ellevousdonneraunaperudescaractristiquesdeJavaetvousaidera valuerlimportancedelintrtportJava.

1.LelangagedeprogrammationJava
SUNcaractriseJavaparlefaitquilestsimple,orientobjet,distribu,interprt,robuste,scuris,indpendantdes architectures,portable,performant,multithreadetdynamique. Cescaractristiquessontissuesdulivreblanccritenmai1996parJamesGoslingetHenryMcGiltonetdisponible ladressesuivante:http://java.sun.com/docs/white/langenv Nousallonsdtaillerchacunedecescaractristiques:

a.Simple
LasyntaxedeJavaestsimilairecelledulangageCetC++,maiselleometdescaractristiquessmantiquesqui rendentCetC++complexes,confusetnonscuriss:
q

EnJava,ilyaseulementtroistypesprimitifs:lesnumriques(entiersetrels),letypecaractreetletype boolen.Lesnumriquessonttoussigns. En Java, les tableaux et les chanes de caractres sont des objets, ce qui en facilite la cration et la manipulation. EnJava,leprogrammeurnapassoccuperdelagestiondelammoire.Unsystmenommle"ramasse miettes"(garbagecollector), soccupedallouerlammoirencessairelorsdelacrationdesobjetsetdela librer lorsque les objets ne sont plus rfrencs dans le contexte courant du programme (quand aucune variablenyfaitrfrence). EnJava,pasdeprprocesseuretpasdefichierdentte.LesinstructionsdefineduCsontremplacespas desconstantesenJavaetlesinstructionstypedefduCsontremplacespardesclassesenJava. EnCetC++,ondfinitdesstructuresetdesunionspourreprsenterdestypesdedonnescomplexes.En Java,oncredesclassesavecdesvariablesdinstancepourreprsenterdestypesdedonnescomplexes. EnC++,uneclassepeuthriterdeplusieursautresclasses,cequipeutposerdesproblmesdambigut. Afindvitercesproblmes,Javanautorise que lhritagesimplemaisapporteunmcanismedesimulation dhritagemultipleparlimplmentationduneoudeplusieursinterfaces. EnJava,ilnexistepaslaclbreinstructiongoto,toutsimplementparcequelleapporteunecomplexitla lecturedesprogrammesetquebiensouvent,onpeutsepasserdecetteinstructionencrivantducodeplus propre.Deplus,enCetC++,legotoestgnralementutilispoursortirdebouclesimbriques.EnJava, nous utiliserons les instructions break et continue qui permettent de sortir dun ou plusieurs niveaux dimbrication. En Java, il nest pas possible de surcharger les oprateurs, tout simplement pour viter des problmes dincomprhension du programme. On prfrera crer des classes avec des mthodes et des variables dinstance. Etpourfinir,enJava,ilnyapasdepointeursmaispluttdesrfrencessurdesobjetsoudescasesdun tableau (rfrences par leur indice), tout simplement parce quil sest avr que la manipulation des pointeursestunegrossesourcedebugsdanslesprogrammesCetC++.

b.Orientobjet
Mispartlestypesdedonnesprimitifs,toutestobjetenJava.Etdeplus,sibesoinest,ilestpossibledencapsuler lestypesprimitifsdansdesobjets,desclassesprfabriquessontdjprvuesceteffet.

ENI Editions - All rigths reserved

- 1-

Java est donc un langage de programmation orient objet conu sur le modle dautres langages (C++, Eiffel, SmallTalk,ObjectiveC,Cedar/Mesa,Ada,Perl),maissansleursdfauts. Les avantages de la programmation objet sont : une meilleure matrise de la complexit (diviser un problme complexe en une suite de petits problmes), un remploi plus facile, une meilleure facilit de correction et dvolution. Javaestfournidebaseavecunensembledeclassesquipermettentdecreretmanipulertoutessortesdobjets (interfacegraphique,accsaurseau,gestiondesentres/sorties...).

c.Distribu
Java implmente les protocoles rseau standards, ce qui permet de dvelopper des applications client/serveur en architecturedistribue,afindinvoquerdestraitementset/oudercuprerdesdonnessurdesmachinesdistantes. Pourcela,JavafournitdebasedeuxAPIspermettantdecrerdesapplicationsclient/serveurdistribues:
q

RMI(RemoteMethodInvocation),quipermetdefairecommuniquerdesobjetsJavasexcutantsurdiffrentes machinesvirtuellesJavaetmmesurdiffrentesmachinesphysiques. CORBA(CommonObjectRequestBrokerArchitecture),bassurletravaildelOMG(http://www.omg.org),qui permet de faire communiquer des objets Java, C++ , Lisp, Python, Smalltalk, COBOL, Ada, sexcutant sur diffrentesmachinesphysiques.

d.Interprt
UnprogrammeJavanestpasexcut,ilestinterprtparlamachinevirtuelleouJVM(JavaVirtualMachine),cequile rend un peu plus lent. Mais cela apporte des avantages, notamment celui de ne pas tre oblig de recompiler un programme Java dun systme un autre car il suffit, pour chacun des systmes, de possder sa propre machine virtuelleJava. Du fait que Java est un langage interprt, vous navez pas faire ldition des liens (obligatoire en C++) avant dexcuter un programme. En Java, il ny a donc que deux tapes, la compilation puis lexcution. Lopration dditiondesliensestraliseparlamachinevirtuelleaumomentdelexcutionduprogramme.

e.Robuste
Javaestunlangagefortementtypettrsstrict.Parexempleladclarationdesvariablesdoitobligatoirementtre expliciteenJava. Lecodeestvrifi(syntaxe,types)lacompilationetgalementaumomentdelexcution,cequipermetderduire lesbugsetlesproblmesdincompatibilitdeversions. Deplus,lagestiondespointeursestentirementpriseenchargeparJavaetleprogrammeurnaaucunmoyendy accder, ce qui vite des crasements inopportuns de donnes en mmoire et la manipulation de donnes corrompues.

f.Scuris
Vu les domaines dapplication de Java, il est trs important quil y ait un mcanisme qui veille la scurit des applicationsetdessystmes.CestlemoteurdexcutiondeJava(JRE)quisoccupeentreautresdecettetche. Le JRE sappuie notamment sur le fichier texte java.policy qui contient des informations sur le paramtrage de la scurit. EnJava,cestleJREquigrelaplanificationmmoiredesobjetsetnonlecompilateurcommecestlecasenC++. CommeenJavailnyapasdepointeursmaisdesrfrencessurdesobjets,lecodecompilcontientdesidentifiants sur les objets qui sont ensuite traduits en adresses mmoire par le JRE, cette partie tant compltement opaque pourlesdveloppeurs. Aumomentdelexcution dunprogrammeJava,leJREutiliseunprocessusnommleClassLoaderquisoccupedu chargementdubytecode(oulangagebinaireintermdiaire)contenudanslesclassesJava.Lebytecodeestensuite analysafindecontrlerquilnapasfaitdecrationoudemanipulationdepointeursenmmoireetgalementquil nyapasdeviolationdaccs. Comme Java est un langage distribu, les principaux protocoles daccs au rseau sont implments (FTP, HTTP, Telnet...).LeJREpeutdonctreparamtrafindecontrlerlaccsaurseaudevosapplications:

- 2-

ENI Editions - All rigths reserved

Interdiretouslesaccs. Autoriserlaccsseulementlamachinehtedoprovientlecodedelapplication. Cestlecaspardfaut pourlesAppletsJava. Autoriser laccs des machines sur le rseau externe (audel du firewall), dans le cas o le code de lapplicationprovientgalementdunhtesurlerseauexterne. Autorisertouslesaccs.Cestlecaspardfautpourlesapplicationsdetypeclientlourd.

g.Indpendantdesarchitectures
LecompilateurJavaneproduitpasducodespcifiquepouruntypedarchitecture. Enfait,lecompilateurproduitdubytecode(langagebinaireintermdiaire)quiestindpendantdetoutearchitecture matrielle,detoutsystmedexploitationetdetoutdispositifdegestiondelinterfaceutilisateurgraphique(GUI). Lavantagedecebytecodeestquilpeutfacilementtreinterprtoutransformdynamiquementencodenatifpour desbesoinsdeperformance. IlsuffitdedisposerdelamachinevirtuelleddiesaplateformepourfairefonctionnerunprogrammeJava.Cest ellequisoccupedetraduirelebytecodeencodenatif.

h.Portable
CequifaittoutdabordqueJavaestportable,cestquilsagitdunlangageinterprt. Deplus,contrairementaulangageCetC++,lestypesdedonnesprimaires(numriques,caractreetboolen)de Javaontlammetaille,quellequesoitlaplateformesurlaquellelecodesexcute. Les bibliothques de classes standards de Java facilitent lcriture du code qui peut ensuite tre dploy sur diffrentesplatesformessansadaptation.

i.Performant
Mme si un programme Java est interprt, ce qui est plus lent quun programme natif, Java met en uvre un processusdoptimisationdelinterprtationducode,appelJIT(JustInTime)ouHotSpot,quipermetdecompiler lavolelebytecodeJavaencodenatif,cequipermetdatteindrelesmmesperformancesquunprogrammecriten langageCouC++.

j.Multitche
Java permet de dvelopper des applications mettant en uvre lexcution simultane de plusieurs Threads (ou processus lgers). Ceci permet deffectuer plusieurs traitements simultanment, afin daccrotre la rapidit des applications,soitenpartageantletempsCPU,soitenpartageantlestraitementsentreplusieursprocesseurs.

k.Dynamique
En Java, nous lavons dit, le programmeur na pas faire ldition des liens (obligatoire en C et C++). Il est donc possible de modifier une ou plusieurs classes sans avoir effectuer une mise jour de ces modifications pour lensembleduprogramme.Lavrificationdelexistencedesclassessefaitaumomentdelacompilationetlappeldu code de ces classes ne se fait quau moment de lexcution du programme. Ce procd permet de disposer dapplicationsallgesentaillemmoire.

2.LaplateformeJava
Pardfinition,uneplateformeestunenvironnementmatrieloulogicielsurlequelpeutsexcuterunprogramme.La plupart des platesformes actuelles sont la combinaison dune machine et dun systme dexploitation (ex : PC + Windows). La plateforme Java diffre par le fait quelle ne se compose que dune partie logicielle qui sexcute sur de nombreusesplatesformesmatriellesetdiffrentssystmesdexploitation. LeschmasuivantestissudusiteWebdeSUNsurlelangageJavaetprsentelesdiffrentscomposantsdelaplate
ENI Editions - All rigths reserved - 3-

formeJava:

Commelemontreleschma,elleestcomposedeslmentssuivants:
q

lamachinevirtuelleJava(JVM), linterface de programmation dapplication Java (API Java), qui est dcompose en trois catgories (APIs de bases, APIs daccs aux donnes et dintgration avec lexistant, APIs de gestion de linterface avec lutilisateur), lesoutilsdedploiementdesapplications, lesoutilsdaideaudveloppement.

Voyonsendtailcesdiffrentslments.

a.LamachinevirtuelleJava(JVM)
LamachinevirtuelleestlabasedelaplateformeJava,elleestncessairepourlexcutiondesprogrammesJava.La JVMestdisponiblepourdenombreuxtypesdordinateursetsystmesdexploitation. LamachinevirtuelleJavasoccupe:
q

duchargementdesclassesetdubytecodequellescontiennent:quandunprogrammeinvoquelacration dobjetsouinvoquedesmembresduneclasse,cestlaJVMquisoccupeduchargementdubytecodequidoit treinterprt. de la gestion de la mmoire : la JVM soccupe entirement de la gestion des pointeurs et donc de chaque rfrencefaiteunobjet.CeprocdpermetgalementlaJVMdesoccuperdelalibrationautomatique delammoire(ramassemiettes)dsquunobjetnestplusrfrencdansleprogramme,cestdirequand aucunevariablenyfaitrfrence. de la scurit : cest lune des oprations les plus complexes effectues par la JVM. Au chargement du programme,ellevrifiequilnestpasfaitappeldelammoirenoninitialise,quedesconversionsdetypes illgalesnesontpaseffectues,queleprogrammenemanipulepasdespointeursenmmoire.Danslecas dApplets Java, la JVM interdit au programme laccs aux priphriques de la machine sur laquelle lApplet sexcuteetautoriselaccsaurseauuniquementverslhtequidiffuselApplet. delinterfaageavecducodenatif(parexemple,codecritenlangageC):laplupartdesAPIsdebasede JavafontappelducodenatifquiestfourniavecleJRE,afindinteragiraveclesystmehte.Vouspouvez galementutiliserceprocdpourdesaccsdespriphriquesoudesfonctionnalitsquinesontpas implmentsdirectementouvoirpasdutoutenJava.

Le fait que Java soit interprt apporte des avantages et des inconvnients. Depuis toujours, on reproche Java dtre moins performant que des langages natifs, ce qui tait surtout le cas pour les applications avec interface utilisateurgraphique.Afindecomblercettelacuneetdeperdrecettemauvaiseimageinjustifie,lesdveloppeurs dechezSUNontnormmenttravaillsurloptimisationdelaJVM. Aveclaversion1.2,onavaituncompilateurJIT(JustInTime)quipermettaitdoptimiserlinterprtationdubytecode enmodifiantsastructurepourlerapprocherducodenatif.Depuislaversion1.3,laJVMintgreunprocessusnomm
- 4 ENI Editions - All rigths reserved

HotSpot (client et serveur) qui optimise davantage linterprtation du code et dune manire gnrale les performancesdelaJVM.HotSpotapporteungaindeperformanceallantde30%40%selonletypedapplication (on le remarque normment au niveau des interfaces graphiques). La dernire version, la version 6, a encore optimisleJavaHotSpot.

b.LAPIJava
LAPI Java contient une collection de composants logiciels prfabriqus qui fournissent un grand nombre de fonctionnalits. LAPIJavadanssaversion6estorganiseenplusde200packages,lquivalentdeslibrairiesenlangageC.Chaque package contient les classes et interfaces prfabriques et directement rutilisables. Vous avez donc votre dispositionenviron3800classesetinterfaces. LaplateformeJavafournitdesAPIsdebase.Denombreusesextensionspeuventtreajoutesetsontdisponibles surlesiteJavadeSUN:gestiondesimagesen3D,desportsdecommunicationdelordinateur,delatlphonie, descourrierslectroniques... LAPIJavapeuttredcomposeentroiscatgories: LesAPIsdebase LesAPIsdebasepermettentdegrer:
q

les lments essentiels comme les objets, les chanes de caractres, les nombres, les entres/sorties, les structuresetcollectionsdedonnes,lespropritssystme,ladateetlheure,etplusencore... lesAppletsJavadanslenvironnementdunavigateurWeb. lerseau,aveclesprotocolesstandardstelsqueFTP,HTTP,UDP,TCP/IPpluslesURLsetlamanipulationdes sockets. linternationalisation et ladaptation des programmes Java, en externalisant les chanes de caractres contenues dans le code dans des fichiers de proprits (.properties). Ce procd permet dadapter le fonctionnementdesapplicationsparrapportdesparamtreschangeants(nomserveur,nomdutilisateur, motdepasse...)etdadapterlalangueutilisedanslesinterfacesgraphiquesparrapportauxparamtres rgionauxdelamachine. linterfaageavecducodenatif,enpermettantdedclarerquelimplmentationdunemthodeestfaiteau seindunefonctionduneDLLparexemple. lascurit,enpermettant:
q

decrypter/dcrypterlesdonnes(JCEJavaCryptographyExtension), de mettre en uvre une communication scurise via SSL et TLS (JSSE Java Secure Socket Extension), dauthentifier et de grer les autorisations des utilisateurs dans les applications (JAAS Java AuthenticationandAutorizationService), dchanger des messages en toute scurit entre des applications communiquant via un service commeKerberos(GSSAPIGenericSecurityServiceApplicationProgramInterface), decreretvaliderdeslistesdecertificatsnommesCertificationPaths(JavaCertificationPathAPI).

la cration de composants logiciels du nom de JavaBeans rutilisables et capables de communiquer avec dautresarchitecturesdecomposantstelsqueActiveX,OpenDoc,LiveConnect. lamanipulationdedonnesXML(extensibleMarkupLanguage)laidedesAPIsDOM(DocumentObjectModel) et SAX (Simple API for XML). Les APIs de base permettent aussi dappliquer des transformations XSLT (extensibleStyleSheetTransformation)partirdefeuillesdestylesXSLsurdesdonnesXML. lagnrationdefichiersdejournalisation(logs)permettantdavoiruncompterendudufonctionnementdes
ENI Editions - All rigths reserved - 5-

applications(activit,erreurs,bugs...).
q

lamanipulationdechanesdecaractresavecdesexpressionsrgulires. leserreurssystmeetapplicativeaveclemcanismedesexceptionschanes. lesprfrencesutilisateurousystme,enpermettantauxapplicationsdestockeretrcuprerdesdonnes deconfigurationdansdiffrentsformats.

LesAPIsdaccsauxdonnesetdintgrationaveclexistant LesAPIsdintgrationpermettentdegrer:
q

desapplicationsclient/serveurdansunearchitecturedistribue,enpermettantlacommunicationenlocalou par le rseau entre des objets Java fonctionnant dans des contextes de JVM diffrents, grce lAPI RMI (RemoteMethodInvocation). desapplicationsclient/serveurdansunearchitecturedistribue,enpermettantlacommunicationenlocalou parlerseauentredesobjetsJavaetdesobjetscompatiblesCORBAtelsqueC++,Lisp,Python,Smalltalk, COBOL, Ada, grce au support de lAPI CORBA (Common Object Request Broker Architecture), bas sur le travaildelOMG(http://www.omg.org). laccspratiquement100%desbasesdedonnes,vialAPIJDBC(JavaDataBaseConnectivity). laccsauxdonnesstockesdansdesservicesdannuaireauprotocoleLDAP(LightweightDirectoryAccess Protocol) comme par exemple lActive Directory de Windows 2000, via lAPI JNDI (Java Naming and Directory Interface).

LesAPIsdegestiondelinterfacedesapplicationsaveclutilisateur LesAPIsdegestiondelinterfaceutilisateurpermettentdegrer:
q

laconceptiondesinterfacesgraphiquesaveclAPI AWT (AbstractWindowToolkit)dancienne gnration, ou lAPISWINGdenouvellegnration. leson,aveclamanipulation,lalectureetlacrationdefichierssondediffrentsformats(.wavou.midi). lasaisiededonnestextuellespardautresmoyensqueleclavier,commeparexempledesmcanismesde reconnaissancevocaleoudereconnaissancedcriture,aveclAPIInputMethodFramework. lesoprationsgraphiquesdedessinaveclAPI Java 2D et de manipulation dimagesaveclAPI Java Image I/O. laccessibilit des applications aux personnes handicapes avec lAPI Java Accessibility qui permet de sinterfacerparexempleavecdessystmesdereconnaissancevocaleoudesterminauxenbraille. ledplacementoutransfertdedonneslorsduneoprationglisser/dposer(DragandDrop). destravauxdimpressiondedonnessurtoutpriphriquedimpression.

c.Lesoutilsdedploiementdesapplications
LaplateformeJavafournitdeuxoutilspermettantdaideraudploiementdesapplications :
q

Java Web Start : destin simplifier le dploiement et linstallation des applications Java autonomes. Les applicationssontdisponiblessurunserveur,lesutilisateurspeuventenlancerlinstallationsurleurmachine vialaconsoleJavaWebStartettoutsefaitalorsautomatiquement.Cequiestintressant,cestquensuite chaquelancementduneapplication,JavaWebStartvrifiesiunemisejourestdisponiblesurleserveur etprocdeautomatiquementsoninstallation.

- 6-

ENI Editions - All rigths reserved

JavaPlugin:destinpermettrelefonctionnementdesAppletsJavaaveclamachinevirtuelle6.Eneffet, lorsquevousaccdez,viavotrenavigateurWeb,unepagehtmlquicontientuneApplet,cestlamachine virtuelledunavigateurquiestchargedelafairefonctionner.Leproblme,cestquelesmachinesvirtuelles des navigateurs supportent danciennes versions de Java. Afin de ne pas tre limit au niveau des fonctionnalits et donc de ne pas rencontrer des problmes dincompatibilit entre les navigateurs, vous pouvez installer le Java Plugin sur les postes clients. Le Java Plugin consiste installer un moteur dexcutionJava6(leJREtantcomposduneJVMetdelensembledesAPIs)etfaireensortequeles navigateursWebutilisentcetteJREetnonlaleur.

d.Lesoutilsdaideaudveloppement
La plupart des outils daide au dveloppement sont contenus dans le rpertoire bin sous le rpertoire racine de linstallationduJ2SE. Lesprincipauxoutilsdaideaudveloppementpermettentde:
q

compiler(javac.exe)voscodessource.javaenfichier.class. de gnrer la documentation (javadoc.exe) automatique de vos codes source (nom de classe, package, hirarchie dhritage, liste des variables et mthodes) avec le mme style de prsentation que la documentationofficielledesAPIsstandardsfourniesparSUN. delancerlexcution(java.exe)desapplicationsautonomesJava. de visualiser, laide dune visionneuse (appletviewer.exe), lexcution dune Applet Java dans une page HTML. Deuxautrestechnologiessontgalementintressantes.Ellessontdestinesdesoutilsdedveloppement tiersafinquilspuissentlesintgrer: JPDA(JavaPlatformDebuggerArchitecture),quipermetdintgrerunoutildedboguageauseindesonIDE dedveloppement,apportantdesfonctionnalitstellesquelespointsdarrts,lepaspas,linspectiondes variablesetexpressions... JVMPI(JavaVirtualMachineProfilerInterface),quipermetdeffectuerdesanalysesetdegnrerdestatssur le fonctionnement des applications (mmoire utilise, objets crs, nombre et frquence dinvocation des mthodes,tempsdetraitement...)afindobserverlebonfonctionnementdesapplicationsetdereprero sontles"gouletsdtranglement".

3.CycledeconceptiondunprogrammeJava
Pour dvelopper une application Java, il faut dabord se procurer la plateforme J2SE de dveloppement (SDK SoftwareDevelopmentKit)ddiesamachineetsonsystmedexploitation,dontvoustrouverezlalistesurlesite JavadeSUN. http://java.sun.com/javase/downloads/index.jsp Ensuite,vouspouvezutiliserlesAPIsstandardsdeJavapourcrirevoscodessources.EnJava,lastructuredebase dunprogrammeestlaclasseetchaqueclassedoittrecontenuedansunfichierportantlextensionjava.Plusieurs classes peuvent tre contenues dans un mme fichier .java, mais une seule de ces classes peut tre dclare publique.Etcestlenomdecetteclassedclarepubliquequidonnesonnomaufichier.java. Au cours du dveloppement, vous pouvez procder la phase de compilation en utilisant loutil javac.exe. Vous obtenezcommersultataumoinsunfichierportantlemmenommaisaveclextension.class.Lefichier.classcompil restetoutdemmeindpendantdetouteplateformeousystmedexploitation. Ensuite, cest linterprteur (java.exe) qui excute les programmes Java. Pour lexcution des Applets, linterprteur est incorpor au navigateur Internet compatible Java (HotJava, Netscape Navigator, Internet Explorer...). Pour lexcution dapplications Java autonomes, il est ncessaire de lancer lexcution de la machine virtuelle fournie soit avec la plateforme de dveloppement Java (SDK), soit avec le kit de dploiement dapplications Java (JRE Java RuntimeEnvironment).

ENI Editions - All rigths reserved

- 7-

InstallationduSDKversionWin32pourlenvironnementWindows
1.Tlchargement
Dansunpremiertemps,ilvousfauttlchargerladernireversionduSDKpourlenvironnementWindows(Win32) partirdusiteWebdeJavaSoft:http://java.sun.com/j2se/downloads.html Actuellement, le fichier tlcharger se nomme jdk6u11windowsi586.exe et fait 75 Mo. Dans tous les cas, tlchargeztoujoursladernireversiondisponible. PuisquevoustessurlesiteWebJavaSoft,profitezenpourtlchargerunautrelmentquisavreindispensable pourprogrammerenJava:ladocumentationdesAPIsstandards. Actuellement, le fichier tlcharger se nomme jdk6u10docs.zip et fait 58 Mo. Pour pouvoir le dcompresser sur votremachine,ilvousfaut265Modespacedisquedisponible.Celafaitbeaucoupdelecture !

2.Installation
Avant dinstaller le SDK sur votre ordinateur, assurezvous quil ny a aucun autre outil de dveloppement Java dinstall,ceciafindviterlesproblmesdeconflitsdeconfiguration.
s

Pour commencer linstallation, double cliquez sur le fichier dinstallation prcdemment tlcharg : jdk6u11 windowsi586.exe.

ToutdabordunebotedemessageWelcomeapparatvousindiquantquevoustessurlepointdinstallerleSDKet vousdemandesivousvoulezpoursuivrelinstallation.
s

CliquezsurNext.

Labotedemessagequisuit,SoftwareLicenseAgreement,vousprsentelalicencedutilisationduSDK.
s

CliquezsurAccept.

Unenouvellefentreapparat,CustomSetupquivouspermetdeslectionnerleslmentsduSDKinstalleretle rpertoirededestinationdelinstallation.

ENI Editions - All rigths reserved

- 1-

Aprsavoirfaitvoschoixouavoirlaisslaslectionpardfaut,cliquezsurNext.Leprogrammeinstallealorsles fichierssurvotreordinateur.Aprsquelquesinstants,labotededialoguesuivantevousinformesurlesuccsde linstallation.

3.Configuration
Ilresteconfigurerlesystme,enindiquantdansquelrpertoiresontstockslesoutilstelsquejava.exe(machine virtuelle)appletviewer.exe(visionneusedApplets)ouencorejavac.exe(compilateur).Pourcefaire,ilfautmodifierla variabledenvironnementPATHpourajouterlechemindaccsverslerpertoirebindujdk.Sivousavezconservles optionspardfautlorsdelinstallationcechemindoittreC:\ProgramFiles\Java\jdk1.6.0_11\bin

4.TestdelaconfigurationduSDK
VousalleztestersilordinateurabienprisencomptelesmodificationsquevousvenezdapporterlavariablePATH etdoncvrifiersiltrouvelecheminosontsituslesoutilsduSDK. PourtesterlaconfigurationduSDK,utilisezunefentreInvitedecommandes.
s

linvitedecommande,saisissezlacommandesuivantequivapermettrededterminersilinstallationduSDKest correcteounon: java -version Vousdevezvoirlemessagesuivantapparatreenrponselalignequevousavezsaisie:

- 2-

ENI Editions - All rigths reserved

CettecommandeaffichedesinformationsconcernantlaversiondelamachinevirtuelleJava. Sivousobtenezunmessagedustyle :java nest pas reconnu en tant que commande interne ou externe, un programme excutable ou un fichier de commandes. CelasignifiequelerpertoireosontstockslesoutilsduSDKnapasttrouvparvotresystme. Danscecas,vrifiezsilavariablePATHcontientbienlesmodificationsquevousavezapportesetquevousnavez pasfaitderreurdesyntaxeenspcifiantlechemindurpertoirebin.

5.InstallationdeladocumentationduSDKetdesAPIsstandards
laidedun utilitaire tel que WinZip, ouvrez le fichier jdk6u10doc.zip que vous avez prcdemment tlcharg. Extrayez tous les fichiers quil contient vers la racine dinstallation du SDK, cestdirepardfautsous C:\Program Files\Java\jdk1.6.0_11 IIfautprvoir270Modespacedisquedisponiblepourinstallerladocumentation. Une fois tous les fichiers extraits, fermez lutilitaire. Sous lexplorateur Windows, dans le rpertoire C:\Program Files\Java\jdk1.6.0_11,vousdevezavoirunnouveaurpertoiredocs.Cestlerpertoirequicontientlensemblede ladocumentationduSDKauformatHTML. Dans ce rpertoire docs, double cliquez sur le fichier lndex.html. Ce fichier contient des liens hypertextes vers lensembledeladocumentationJava,quiestsoitinstallesurvotreordinateur,soitaccessiblesurunsiteWeb. Le plus important de la documentation se trouve dans le sousrpertoire api, en double cliquant sur le fichier lndex.html.CefichiercontientlesspcificationsdelAPIJava,ouplusprcismentladescriptiondelensembledes classesdelalibrairieJava.Sanscettedocumentation,vousnepourrezpasdvelopperenJava. Ilestrecommanddeplacersurvotrebureauunraccourciverscedocument.

ENI Editions - All rigths reserved

- 3-

Cettepageestorganiseentroisfentres:
q

lafentreenhautgauchecontientlalistedespackages(plusde200). la fentre en bas gauche contient la liste des classes contenues dans le package slectionn dans la fentreprcdente. la plus grande fentre contient la description dune interface ou dune classe slectionne dans la fentre prcdente.Ladescriptionduneclasseestorganisedelamaniresuivante:
q

unschmadelahirarchiedessuperclassesdelinterfaceoudelaclasseencours. uneexplicationsurlutilisationdelaclasseoudelinterface. FieldSummary:listedesattributs. ConstructorSummary:listedesconstructeursdelaclasse. MethodSummary:listedesmthodes. FieldDetails:descriptiondtailledesattributs. ConstructorDetails:descriptiondtailledesconstructeursdelaclasse. MethodDetails:descriptiondtailledesmthodesdelaclasse.

- 4-

ENI Editions - All rigths reserved

LesdiffrentestapesdecrationdunprogrammeJava
1.Crationdesfichierssource
Dans un premier temps, il vous faut crer un ou plusieurs fichiers de code source, selon limportance de votre programme. Toutcodejavaestcontenulintrieurduneclassequiestellemmecontenuedansunfichierportantlextension java. Plusieurs classes peuvent exister dans un mme fichier .java mais une seule peut tre dclare publique, et cest cetteclassequidonnesonnomaufichier. Commebeaucoupdautreslangagesdeprogrammation,lesfichierssourceJavasontdesfichiersdetextesansmise enforme. UnsimplediteurdetextecapabledenregistrerauformattexteASCII,telqueleBlocnotesdeWindowsouVIsous Unix,estsuffisantpourcriredessourcesJava. Unefoislecodedevotrefichiersourcecrit,ilfautlenregistreraveclextensionjavaquiestlextensiondesfichiers source. SivousutilisezleBlocnotesdeWindows,faitesattentionlorsdelenregistrementdevotrefichierqueleBlocnotes najoute pas une extension .txt au nom de votre fichier. Pour viter ce problme, nommez votre fichier avec lextensionjava,letoutplacentreguillemets. IIyatoutefoismieuxquunsimplediteurdetextepourdvelopper.Vouspouvez,moyennantlecotdunelicence, utiliserdesoutilscommerciauxouencoremieuxutiliserdesproduitsopensourcecommelexcellentEclipse.Ilsagit audpartdunprojetIBMmaisdenombreusessocitssesontjointesceprojet(Borland,Oracle,Merant...).Cest unoutildedveloppementJavaexcellentetgratuitauquelonpeutlierdautresapplicationstiersviaunsystmede plugin.SunproposegalementNetBeansunoutiltrsefficaceetsimpledutilisation.

2.Compilerunfichiersource
Unefoisvotrefichiersourceralisetenregistraveclextension.java,ilfautcompilervotrefichier. PourcompilerunfichiersourceJava,ilfaututiliserloutilenlignedecommandejavacfourniavecleSDK.
s

OuvrezunefentreInvitedecommandes. linvite de commandes, placezvous dans le dossier contenant votre fichier source (.java), laide de la commandecdsuiviedunespacepuisdunomdudossierquicontientvotrefichiersource. Une fois que vous tes dans le bon dossier, vous pouvez lancer la compilation de votre fichier laide de la commandesuivantelinvitedecommandes:

javac <nomFichier>.java javac:compilateurJavaenlignedecommande,fourniavecleJDK. <nomFichier>:nomdufichiersourceJava. .java:extensionquiindiquequelefichierestunesourceJava. Si vous voulez compiler plusieurs fichiers source en mme temps, il suffit de saisir la commande prcdente, puis dajouterlesautresfichierscompilerenlessparantparunespace. javac <nomFichierl>.java <nomFichier2>.java SiauboutdequelquessecondesvousvoyezapparatredenouveaulinvitedecommandesMSDOS,cestquevotre fichier ne contient pas derreur et quil a t compil. En effet le compilateur naffiche pas de message quand la compilationsedroulecorrectement. LersultatdelacompilationdunfichiersourceJavaestlacrationdunfichierbinaireportantlemmenomquele fichiersourcemaisaveclextension.class.

ENI Editions - All rigths reserved

- 1-

Un fichier binaire .class contient le pseudocode Java qui peut tre interprt par la machine virtuelle Java. Si par contre, vous voyez apparatre une suite de messages dont le dernier vous indique un nombre derreurs, cestque votrefichiersourcecontientdeserreursetquejavacnadoncpasrussilecompiler.

Danscecas,ilvousfautcorrigervotresource. Pourvousaidertrouverleserreursdecodedevotreoudevosfichierssource,javacvousfournitdesinformations trsutiles: <nomFichier.java> : <numLigne> : <message> <ligne de code> <nomFichier> NomdufichiersourceJavaquicontientuneerreur. <numLigne> Numrodelalignedevotrefichiersourceojavacadceluneerreur. <message> Messageindiquantletypedelerreur. <ligne> Lignedecodecontenantuneerreur,javacindiqueparuneflcheoestsituelerreurdanslaligne. Aprs avoir corrig votre code, recompilez votre fichier. Si javac vous indique toujours des erreurs, renouvelez loprationdecorrectionpuisderecompilationdufichierjusquobtenirlacrationdufichierbinaire.class. Pardfautlesfichierscompilssontcrsdanslemmerpertoirequevosfichierssource.Vouspouvezindiquer loutiljavacdelescrerdansunautrerpertoirelaidedeloptiond"directory".

3.Excuteruneapplication
UneapplicationJavaestunprogrammeautonome,semblableauxprogrammesquevousconnaissez,maisqui,pour treexcut,ncessitelemploiduninterprteurJava(lamachinevirtuelleJava)quichargelamthodemain()dela classeprincipaledelapplication. PourlancerlexcutionduneapplicationJava,ilfaututiliserloutilenlignedecommandejavafourniavecleJDK.
s

Ouvrez une fentre Invite de commandes.Placezvous dans le rpertoire qui contient le ou les fichiers binaires (.class)devotreapplication,puissaisissezlacommandeaveclasyntaxesuivante: java <fichierMain> <argumentN> <argumentN+l>

- 2-

ENI Editions - All rigths reserved

java:outilenlignedecommandequilancelexcutiondelamachinevirtuelleJava. <fichierMain>:estobligatoirementlenomdufichierbinaire(.class)quicontientlepointdentredelapplication, la mthode main(). Important : ne mettez pas lextension .class aprs le nom du fichier car ceci est fait implicitementparlamachinevirtuelleJava. <argumentN> <argumentN+1>:ventuelsargumentsdelignedecommandepasserlapplicationlexcutionde celleci. Si vous avez lanc lexcution correctement (syntaxe correcte, avec le fichier contenant la mthode main(), vous devez voir apparatre les ventuels messages que vous avez insrs dans votre code. Si par contre vous voyez apparatre un message derreur semblable Exception in thread "main" java.lang.NoClassDefFoundError :... cestquevotreprogrammenepeutpastreexcut. Plusieursraisonspeuvententrelacause:
q

Le nom du fichier excuter ne porte pas le mme nom que la classe (diffrence entre majuscules et minuscules). Vousavezsaisilextension.classaprslenomdufichierexcutersurlalignedecommande. Lefichierquevousexcuteznecontientpasdemthodemain(). Vousessayezdexcuterunfichierbinaire(.class)quiestsitudansunautrerpertoirequeceluidovous lancezlexcution.

ENI Editions - All rigths reserved

- 3-

VotrepremireapplicationJava
1.Squeletteduneapplication
UneapplicationJavaestunprogrammeautonomequipeuttreexcutsurnimportequelleplateformedisposant dunemachinevirtuelleJava. TouttypedapplicationpeuttredveloppenJava:interfacegraphique,accsauxbasesdedonnes,applications client/serveur,multithreading... Uneapplicationestcomposeauminimumdunfichier.classquidoitluimmecontenirauminimumlepointdentre delapplication,lamthodemain(). Exempledelastructureminimumduneapplication public class MonApplication { public static void main(String arguments[]) { /* corps de la mthode principale */ } } Si lapplication est importante, il est possible de crer autant de classes que ncessaire. Les classes qui ne contiennentpaslamthodemain()sontnommesclassesauxiliaires. Lamthodemain()estlepremierlmentappelparlamachinevirtuelleJavaaulancementdelapplication. Lecorpsdecettemthodedoitcontenirlesinstructionsncessairespourlelancementdelapplication,cestdirela crationdinstancesdeclasse,linitialisationdevariablesetlappeldemthodes. Idalement,lamthodemain()peutnecontenirquuneseuleinstruction. Ladclarationdelamthodemain()sefaittoujourssuivantlasyntaxesuivante: public static void main(String <identificateur>[ ] ) {...} public Modificateur daccs utilis pour rendre la mthode accessible lensemble des autres classes et objets de lapplication,etgalementpourquelinterprteurJavapuisseyaccderdelextrieuraulancementdelapplication. static Modificateurdaccsutilispourdfinirlamthodemain()commetantunemthodedeclasse.Lamachinevirtuelle Javapeutdoncappelercettemthodesansavoircreruneinstancedelaclassedanslaquelleelleestdfinie. void Motclutilispourindiquerquelamthodeestuneprocdurequineretournepasdevaleur. main Identificateurdelamthode. String <identificateur>[ ] : Paramtre de la mthode, cest un tableau de chanes de caractres. Ce paramtre est utilis pour passer des argumentsenlignedecommandeaulancementdelapplication.Danslaplupartdesprogrammes,lenomutilispour <identificateur>estargumentouargs,pourindiquerquelavariablecontientdesargumentspourlapplication.

2.Argumentsenlignedecommande
a.Principesetutilisation

ENI Editions - All rigths reserved

- 1-

UneapplicationJavatantunprogrammeautonome,ilpeuttreintressantdeluifournirdesparamtresoudes optionsquivontdterminerlecomportementoulaconfigurationduprogrammeaulancementdeceluici. Les arguments en ligne de commande sont stocks dans un tableau de chanes de caractres. Si vous voulezutilisercesargumentssousunautreformat,vousdevezfaireuneconversiondetype,dutypeString versletypedsirlorsdelutilisationdelargument. Dansquelscasfautilutiliserlesargumentsenlignedecommande? Les arguments en ligne de commande sont utiliser au lancement dune application ds quuneoudesdonnes utiliseslinitialisationdevotreprogrammepeuventprendredesvaleursvariablesenfonctiondelenvironnement. Parexemple:
q

nomduportdecommunicationutilisdanslecasdunecommunicationavecunpriphriquematriel. adresseIPdunemachinesurlerseaudanslecasduneapplicationclient/serveur. nomdutilisateur et mot de passe dans le cas dune connexion une base de donnes avec gestion des permissionsdaccs.

Par exemple, dans le cas dune application qui accde une base de donnes, il faut en gnral fournir un nom dutilisateur et un mot de passe pour ouvrir une session daccs la base. Des utilisateurs diffrents peuvent accder la base de donnes, mais avec des permissions diffrentes. Il peut donc exister plusieurs sessions diffrentes.Ilnestpasenvisageabledecreruneversiondelapplicationpourchaqueutilisateur. Deplus,cesinformationssontsusceptiblesdtremodifies.Ilnestdoncpasjudicieuxdelesintgrerdansvotre code,cartoutchangementvousobligeraitmodifiervotrecodesourceetlerecompileretdteniruneversion pourchaqueutilisateur. Lasolutionceproblmersidedanslesargumentsenlignedecommande. Ilsuffitdansvotrecodedutiliserletableaudargumentsdelamthodemainquicontientlesvariables(nometmot depasse)devotreapplication. Ensuite, selon lutilisateurduprogramme,ilfautaulancementdelapplication par linstructionjava,fairesuivrele nomdelaclasseprincipaleparlavaleurdesargumentsdelignedecommandedelapplication.

b.PassagedargumentsuneapplicationJavaaumomentdelexcution
LepassagedargumentsuneapplicationJavasefaitaulancementdelapplicationparlintermdiairedelaligne de commande. Lexemple de programme suivant montre comment utiliser le passage darguments en ligne de commandedansuneapplicationJava. /* Dclaration de la classe principale de lapplication */ public class MaClasse { /* Dclaration de la mthode point dentre de lapplication*/ public static void main(String args[]) { /* Affichage des arguments de la ligne de commande */ for (int i = 0 ; i < args.length; i++)

System.out.printIn("Argument " +i + " = " + args[i]) ; } /* Conversion de deux arguments de la ligne de commande de String vers int, puis addition des valeurs entires, et affichage du rsultat */ int somme; somme=(Integer.parselnt(args[3]))+(Integer.parselnt(args[4])); System.out.println("Argument 3 + Argument 4 = " + somme); }

- 2-

ENI Editions - All rigths reserved

} | Aprscompilation,leprogrammesexcuteaveclalignedecommandesuivante: java MaClasse ditions ENI "ditions ENI" 2 5 Lexcutionduprogrammeaffichelesinformationssuivantes: Argument Argument Argument Argument Argument Argument 0 1 2 3 4 3 = = = = = + ditions ENI ditions ENI 2 5 Argument 4 = 7

ENI Editions - All rigths reserved

- 3-

Lesvariables,constantesetnumrations
1.Lesvariables
Les variables vont vous permettre de mmoriser pendant lexcution de votre application diffrentes valeurs utiles pour le fonctionnement de votre application. Une variable doit obligatoirement tre dclare avant son utilisation dans le code. Lors de la dclaration dune variable nous allons fixer ses caractristiques. En fonction de lemplacementdesadclarationunevariableappartiendraunedescatgoriessuivantes :
q

Dclarelintrieurduneclasselavariableestunevariabledinstance.Ellenexisteraquesiuneinstance delaclasseestdisponible.Chaqueinstancedeclasseaurasonpropreexemplairedelavariable. Dclare avec le mot cl static lintrieur dune classe la variable est une variable de classe. Elle est accessibledirectementparlenomdelaclasseetnexistequenunseulexemplaire. Dclarelintrieur dunefonctionlavariableestunevariablelocale.Ellenexistequependantlexcution delafonctionetnestaccessiblequeparlecodedecelleci. Les paramtres des fonctions peuvent tre considrs comme des variables locales. La seule diffrence rsidedanslinitialisationdelavariablequiesteffectuelorsdelappeldelafonction.

a.Nomdesvariables
Voyonslesrglesrespecterpournommerlesvariables.
q

Lenomdunevariablecommenceobligatoirementparunelettre. Ilpeuttreconstitudelettres,dechiffresouducaractresoulign(_). Il peut contenir un nombre quelconque de caractres (pratiquement il vaut mieux se limiter une taille raisonnable). Il y a une distinction entre minuscules et majuscules (la variable AGEDUCAPITAINE est diffrente de la variableageducapitaine). Lesmotsclsdulangagenedoiventpastreutilisscommenomdevariable. Par convention les noms de variable sont orthographis en lettres minuscules sauf la premire lettre de chaquemotsilenomdelavariableencomporteplusieurs(ageDuCapitaine).

b.Typedesvariables
Enspcifiantuntypepourunevariablenousindiquonsquellesinformationsnousallonspouvoirstockerdanscette variableetlesoprationsquenousallonspouvoireffectueravec. Deuxcatgoriesdetypesdevariablessontdisponibles:
q

Lestypesvaleur :lavariablecontientrellementlesinformations. Lestypesrfrence :lavariablecontientladressemmoireosetrouventlesinformations.

LelangageJavadisposedesepttypesdebasequipeuventtreclasssentroiscatgories. Lestypesnumriquesentiers Typesentierssigns

ENI Editions - All rigths reserved

- 1-

byte short int long

128 32768 2147483648 9223372036854775808

127 32767 2147483647 9223372036854775807

8bits 16bits 32bits 64bits

Lorsquevouschoisissezuntypepourvosvariablesentiresvousdevezprendreencomptelesvaleursminimaleet maximalequevousenvisagezdestockerdanslavariableafindoptimiserlammoireutiliseparlavariable.Ilest eneffetinutiledutiliseruntypelongpourunevariabledontlavaleurnexcderapas50,untypebyteestdansce cas suffisant. Lconomie de mmoire semble drisoire pour une variable unique mais devient apprciable lors de lutilisationdetableauxdegrandedimension. Lestypesdcimaux float double 1.4E45 4.9E324 3.4028235E38 1.7976931348623157E308 4octets 8octets

Touslestypesnumriquessontsignsetpeuventdonccontenirdesvaleurspositivesoungatives. Letypecaractre Letypecharestutilispourstockeruncaractreunique.Unevariabledetypecharutilisedeuxoctetspourstocker lecodeUnicodeducaractre.DansjeudecaractreUnicodeles128premierscaractressontidentiquesaujeude caractre ASCII, les caractres suivants, jusqu 255, correspondent aux caractres spciaux de lalphabet latin (parexemplelescaractresaccentus),leresteestutilispourlessymbolesoulescaractresdautresalphabets. Les caractres spcifiques ou ceux ayant une signification particulire pour le langage Java sont reprsents par unesquencedchappement.Elleestconstitueducaractre\suividunautrecaractreindiquantlasignification de la squence dchappement. Le tableau suivant prsente la liste des squences dchappement et leurs significations. squence \t \b \n \r \f \ \" \\ Tabulation BackSpace Sautdeligne Retourchariot Sautdepage Simplequote Doublequote Antislash signification

Les caractres unicode non accessibles au clavier sont eux aussi reprsents par une squence dchappement constituedescaractres\usuivisdelavaleurhexadcimaleducodeunicodeducaractre.Lesymboleeuroest parexemplereprsentparlasquence\u20AC. PourpouvoirstockerdeschanesdecaractresilfaututiliserletypeStringquireprsenteunesuitedezron caractres. Ce type nest pas un type de base mais une classe. Cependant pour faciliter son emploi, il peut tre utiliscommeuntypedebasedulangage.Leschanesdecaractressontinvariables,carlorsdelaffectationdune valeur une variable de type chane de caractres de lespace est rserv en mmoire pour le stockage de la chane.Siparlasuitecettevariablereoitunenouvellevaleurunnouvelemplacementluiestassignenmmoire. Heureusementcemcanismeesttransparentpournousetlavariableferatoujoursautomatiquementrfrencela valeur qui lui a t assigne. Avec ce mcanisme les chanes de caractres peuvent avoir une taille variable. Lespace occup en mmoire est automatiquement ajust en fonction de la longueur de la chane de caractres.

- 2-

ENI Editions - All rigths reserved

Pouraffecterunechanedecaractresunevariableilfautsaisirlecontenudelachaneentre"et"commedans lexemplecidessous. Exemple nomDuCapitaine = "Crochet"; De nombreuses fonctions de la classe String permettent la manipulation des chanes de caractres et seront dtaillesplusloindanscechapitre. Letypeboolean Letypebooleanpermetdavoirunevariablequipeutprendredeuxtatsvrai/faux,oui/non,on/off. Laffectationsefaitdirectementaveclesvaleurstrueoufalsecommedanslexemplesuivant: boolean disponible,modifiable; disponible=true; modifiable=false; Ilestimpossibledaffecteruneautrevaleurunevariabledetypeboolean.

c.Valeurspardfaut
Linitialisationdesvariablesnestpastoujoursobligatoire.Cestparexemplelecaspourlesvariablesdinstancequi sontinitialisesaveclesvaleurspardfautsuivantes. Type byte short int long float double char boolean String 0 0 0 0 0.0 0.0 \u0000 false null Valeurpardfaut

Parcontrelesvariableslocalesdoiventtreinitialisesavantdtreutilises.Lecompilateureffectuedailleursune vrificationlorsquilrencontreunevariablelocaleetdclencheuneerreursilavariablenapastinitialise.

d.Valeurslittrales
Lesvaleursnumriquesentirespeuventtreutilisesavecleurreprsentationdcimale,octaleouhexadcimale. Lestroislignesdecodesuivantesontlemmeeffet. i=243; i=0363; i=0xF3; Lesvaleursnumriquesrellespeuventtreexprimesaveclanotationdcimaleoulanotationscientifique. surface=2356.8f; surface=2.3568e3f;

ENI Editions - All rigths reserved

- 3-

Lesvaleurslittralessontgalementtypes.Lesvaleursnumriquesentiressontpardfautconsidrescomme destypesint.Lesvaleursnumriquesrellessont,elles,considrescommedestypesdouble.Cetteassimilation est parfois source derreurs de compilation lors de lutilisation du type float. Les lignes suivantes gnrent une erreur de compilation car le compilateur considre que vous tentez daffecter une variable de type float une valeurdetypedoubleetquilyadanscecasunrisquedepertedinformation. float surface; surface=2356.8; Pourrsoudreceproblmeilfautforcerlecompilateurconsidrerlavaleurlittralerellecommeuntypefloaten lafaisantsuivreparlecaractrefouF. float surface; surface=2356.8f;

e.Conversionsdetypes
Les conversions de types consistent transformer une variable dun type dans un autre type. Les conversions peuvent se faire vers un type suprieur ou vers un type infrieur. Si une conversion vers un type infrieur est utilise, il risque dy avoir une perte dinformation.Parexemplelaconversiondun typedouble vers un typelong feraperdrelapartiedcimaledelavaleur.Cestpourcetteraisonquelecompilateurexigedanscecasquevous indiquiez explicitement que vous souhaitez effectuer cette opration. Pour cela vous devez prfixer llmentque voussouhaitezconvertiravecletypequevousvoulezobtenirenplaantceluicientreparenthses. float surface; surface=2356.8f; int approximation; approximation=(int)surface; Vousperdezdanscecaslapartiedcimale,maiscestparfoislebutdecegenredeconversion. Les conversions vers un type suprieur sont sans risque de perte dinformation et peuvent donc se faire directementparunesimpleaffectation. Letableausuivantrsumelesconversionspossiblesetsiellesdoiventtreexplicites(L )ousiellessontimplicites (J ). Typededonnesobtenir Typededonnesdorigine byte short int long float double char L L L L L L L L L L J L L L J L L J L J J byte short J int J J long J J J float J J J J double J J J J J char J J J L L L

Lesconversionspartirdechanesdecaractresetversdeschanesdecaractressontplusspcifiques. Conversionversunechanedecaractres Les fonctions de conversion vers le type chane de caractres sont accessibles par lintermdiaire de la classe String. La mthode de classe valueOf assure la conversion dune valeur dun type de base vers une chane de caractres.

- 4-

ENI Editions - All rigths reserved

Danscertainessituationslutilisationdecesfonctionsestoptionnellecarlaconversionesteffectueimplicitement. Cestlecasparexemplelorsquunevariableduntypedebaseestconcatneavecunechanedecaractres.Les deuxversionsdecodesuivantesontlemmeeffet. Version1 double prixHt; prixHt=152; String recap; recap="le montant de la commande est : " + prixHt*1.196; Version2 double prixHt; prixHt=152; String recap; recap="le montant de la commande est : " +String.valueOf(prixHt*1.196); Conversiondepuisunechanedecaractre Il arrive frquemment quune valeur numrique soit disponible dans une application sous forme dune chane de caractres(saisiedelutilisateur,lecturedunfichier). Pourpouvoirtremanipuleparlapplication,elledoittreconvertieenuntypenumrique.Cetypedeconversion estaccessibleparlintermdiairedesclassesquivalentesauxtypesdebase.Ellespermettentlamanipulationde valeursnumriquessousformedobjets.Chaquetypedebasepossdesaclasseassocie. Typedebase byte short int long float double Byte Short Integer Long Float Double Classecorrespondante

ENI Editions - All rigths reserved

- 5-

boolean char

Boolean Character

Cesclassesfournissentunemthodeparseacceptantcommeparamtreunechanedecaractresetpermettant denobtenirlaconversiondansletypedebaseassocilaclasse. Classe Byte Short Integer Long Float Double Boolean mthode publicstaticbyteparseByte(Strings) publicstaticshortparseShort(Strings) publicstaticintparseInt(Strings) publicstaticlongparseLong(Strings) publicstaticfloatparseFloat(Strings) publicstaticdoubleparseDouble(Strings) publicstaticbooleanparseBoolean(Strings)

Pourretenircommentprocderpoureffectueruneconversion,ilfautappliquerleprincipetrssimple :lamthode utilisersetrouvedanslaclassecorrespondanteautypededonnesquelonsouhaiteobtenir.

f.Dclarationdesvariables
Ladclarationdunevariableestconstituedutypedelavariablesuividunomdelavariable.Lasyntaxedebase estdonclasuivante : int compteur ; double prix ; String nom ; Desmodificateursdaccsetunevaleurinitialepeuventgalementtreprcisslorsdeladclaration. private int compteur=0 ; protected double prix=123.56 ; public nom=null ; La dclaration dune variable peut apparatre nimporte o dans le code. Il suffit simplement que la dclaration prcdelutilisationdelavariable.Ilestconseillderegrouperlesdclarationsdevariablesendbutdeclasseou endbutdefonctionafindefaciliterlarelectureducode. Ladclarationdeplusieursvariablesdemmetypepeuttreregroupesuruneseuleligneensparantlesnoms desvariablesparunevirgule. protected double prixHt=123.56, prixTtc,fraisPort ;

g.Portedesvariables
La porte dune variable est la portion de code partir de laquelle on peut manipuler cette variable. Elle est fonctiondelemplacementoestsitueladclaration. Cette dclaration peut tre faite dans le bloc de code dune classe, le bloc de code dune fonction ou un bloc de codelintrieurdunefonction.Seullecodedublocoestdclarelavariablepeutlutiliser.Silemmeblocde codeestexcutplusieursfoispendantlexcutiondelafonction,casdunebouclewhileparexemple,lavariable seracrechaquepassagedanslaboucle.Linitialisationdelavariableestdanscecasobligatoire.Ilnepeutpas yavoirdeuxvariablesportantlemmenomaveclammeporte.Vousavezcependantlapossibilitdedclarer unevariableinterneunefonction,ouunparamtredunefonctionaveclemmenomquunevariabledclareau niveaudelaclasse.Lavariabledclareauniveaudelaclasseestdanscecasmasqueparlavariableinternela fonction.

- 6-

ENI Editions - All rigths reserved

h.Niveaudaccsdesvariables
Leniveaudaccsdunevariablesecombineaveclaportedelavariableetdterminequelleportiondecodeale droit de lire et dcrire dans la variable. Un ensemble de mots cls permettent de contrler le niveau daccs. Ils sutilisent lors de la dclaration de la variable et doivent tre placs devant le type de la variable. Ils sont uniquementutilisablespourladclarationdunevariablelintrieurduneclasse.Leurutilisationlintrieurdune fonctionestinterdite. private :lavariableestutilisableuniquementparlecodedelaclasseoelleestdfinie. protected :lavariableestutilisabledanslaclasseoelleestdfinie,danslessousclassesdecetteclasseetdans lesclassesquifontpartiedummepackage. public :lavariableestaccessiblepartirdenimportequelleclasseindpendammentdupackage. aucunmodificateur :lavariableestaccessiblepartirdetouteslesclassesfaisantpartiedummepackage. static :cemotclestassociundesmotsclprcdentspourtransformerunedclarationdevariabledinstance endclarationdevariabledeclasse(utilisablesansquuneinstancedelaclasseexiste).

i.Duredeviedesvariables
La dure de vie dune variable nous permet de spcifier pendant combien de temps durant lexcution de lapplicationlecontenudunevariableseradisponible. Pourunevariabledclaredansunefonctionladuredeviecorrespondladuredexcutiondelafonction.Ds la fin de lexcution de la procdure ou fonction, la variable est limine de la mmoire. Elle est recre lors du prochainappeldelafonction.Unevariabledclarelintrieurduneclasseestutilisabletantquuneinstancede laclasseestdisponible.Lesvariablesdclaresaveclemotclstaticsontaccessiblespendanttouteladurede fonctionnementdelapplication.

2.Lesconstantes
Dansuneapplicationilarrivefrquemmentquelonutilisedesvaleursnumriquesouchanesdecaractresquine serontpasmodifiespendantlefonctionnementdelapplication.Ilestconseill,pourfaciliterlalectureducode,de dfinircesvaleurssousformedeconstantes. La dfinition dune constante se fait en ajoutant le mot cl final devant la dclaration dune variable. Il est obligatoiredinitialiserlaconstanteaumomentdesadclaration(cestleseulendroitoilestpossibledefaireune affectationlaconstante). final double TAUXTVA=1.196; Laconstantepeuttrealorsutilisedanslecodelaplacedelavaleurlittralequellereprsente. prixTtc=prixHt*TAUXTVA; Lesrglesconcernantladuredevieetlaportedesconstantessontidentiquescellesconcernantlesvariables. Lavaleurduneconstantepeutgalementtrecalculepartirduneautreconstante. final double TOTAL=100; final double DEMI=TOTAL/2; DenombreusesconstantessontdjdfiniesauniveaudulangageJava.Ellessontdfiniescommemembresstatic des nombreuses classes du langage. Par convention les noms des constantes sont orthographis entirement en majuscules.

3.Lesnumrations
Unenumrationvanouspermettrededfinirunensembledeconstantesquisontliesentreelles.Ladclaration sefaitdelamaniresuivante: public enum Jours { DIMANCHE,

ENI Editions - All rigths reserved

- 7-

LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI } Lapremirevaleurdelnumrationestinitialisezro.Lesconstantessuivantessontensuiteinitialisesavecun incrmentdeun.Ladclarationprcdenteauraitdoncpuscrire: public class Jours { public static final public static final public static final public static final public static final public static final public static final }

int int int int int int int

DIMANCHE=0; LUNDI=1; MARDI=2; MERCREDI=3; JEUDI=4; VENDREDI=5; SAMEDI=6;

Cestapproximativementcequefaitlecompilateurlorsquilanalyselecodedelnumration. Unefoisdfinie,unenumrationpeuttreutilisecommeunnouveautypededonnes.Vouspouvezdoncdclarer unevariableavecpourtypevotrenumration. Jours repere; Ilestalorspossibledutiliserlavariableenluiaffectantunedesvaleursdfiniesdanslnumration. repre=Jours.LUNDI; Lorsque vous faites rfrence un lment de votre numration, vous devez le faire prcder du nom de lnumration comme dans lexemple prcdent. Laffectation la variable dautre chose quune des valeurs contenuesdanslnumrationestinterditeetprovoqueuneerreurdecompilation. Ladclarationdunenumrationnepeutpassefairedansuneprocdureouunefonction.Ellepeutparcontretre dclaredansuneclassemaisilfaudradanscecasprfixerlenomdelnumrationparlenomdelaclassedans laquelleelleestdfinielorsdesonutilisation.Pourquelnumrationsoitautonomeilsuffitsimplementdeladclarer danssonproprefichier. Laportedunenumrationsuitlesmmesrglesquecelledesvariables(utilisationdesmotsclspublic,private, protected). Unevariabledetypenumrationpeutfacilementtreutilisedansunestructureswitch case,ilnestdanscecas pasncessairedefaireprcderlesmembresdelnumrationdunomdelnumration. public static void testJour(Jours j) { switch (j) { case LUNDI: case MARDI: case MERCREDI: case JEUDI: System.out.println("c\est dur de travailler"); break; case VENDREDI: System.out.println("bientot le week end !"); break; case SAMEDI: System.out.println("enfin !"); break; case DIMANCHE: System.out.println("et ca recommence !"); break; } }

- 8-

ENI Editions - All rigths reserved

4.Lestableaux
Lestableauxvontnouspermettredefairerfrenceunensembledevariablesdemmetypeparlemmenomet dutiliserunindexpourlesdiffrencier.Untableaupeutavoiruneouplusieursdimensions.Lepremierlmentdun tableauatoujourspourindexzro.Lenombredecasesdutableauestspcifiaumomentdelacrationdutableau. Leplusgrandindexduntableauestdoncgalaunombredecasesmoinsun.Aprssacrationlescaractristiques dun tableau ne peuvent plus tre modifies (nombre de cases, type dlments stocks dans le tableau). La manipulationduntableaudoittredcomposeentroistapes:
q

Dclarationdunevariablepermettantdemanipulerletableau. Crationdutableau(allocationmmoire). Stockageetmanipulationdeslmentsdutableau.

Dclarationdutableau Ladclarationsefaitcommeunevariableclassiquesaufquelondoitajouterlasuitedutypededonnesoudu nomdelavariablelescaractres[et].Ilestprfrable,pourunemeilleurelisibilitducode,dassocierlescaractres [et]autypededonnes.Lalignesuivantedclareunevariabledetypetableaudentiers. int[] chiffreAffaire;

Crationdutableau Aprsladclarationdelavariableilfautcrerletableauenobtenantdelammoirepourstockerceslments.Cest cemomentquenousindiquonslatailledutableau.Lestableauxtantassimilsdesobjetscestdoncloprateur newquivatreutilispourcreruneinstancedutableau.Lavaleurfournieparloprateurneweststockedansla variabledclareaupralable. chiffreAffaire=new int[12]; Cettedclarationvacreruntableauavecdouzecasesnumrotesde011.Latailledutableauestdfinitive,il nestdoncpaspossibledagrandiroudertrciruntableaudjcr. Une autre solution est disponible pour la cration dun tableau. Elle permet simultanment la dclaration de la variable,lacrationdutableauetlinitialisationdesoncontenu.Lasyntaxeestlasuivante : int[] chiffreAffaire={1234,563,657,453,986,678,564,234,786,123,534,975}; Ilnyadanscecaspasbesoindeprciserdetaillepourletableau.Ledimensionnementseferaautomatiquementen fonctiondunombredevaleursplacesentrelesaccolades. Utilisationdutableau Les lments des tableaux sont accessibles de la mme manire quune variable classique. Il suffit juste dajouter lindexdellmentquelonveutmanipuler. chiffreAffaire[0]=12456; Lecontenudunecasedetableaupeuttreutilisexactementdelammefaonquunevariabledummetype.Il fauttrevigilantenmanipulantuntableauetnepastenterdaccderunecasedutableauquinexistepassous peinedobteniruneexceptiondutypeArrayIndexOutOfBoundException. Tableauxplusieursdimensions Lestableauxplusieursdimensionssontenfaitdestableauxcontenantdautrestableaux.Lasyntaxededclaration estsemblablecelleduntableaumispartquelondoitspcifierautantdepairesdecrochetsquevoussouhaitez avoirdedimensions. int[][] matrice; Lacrationestgalementsemblablecelleduntableauunedimensionhormisquevousdevezindiquerunetaille pourchacunedesdimensions.

ENI Editions - All rigths reserved

- 9-

matrice=new int[2][3]; Laccsunlmentdutableausefaitdemanireidentiqueenindiquantlesindexpermettantdidentifierlacasedu tableauconcerne. matrice[0][0]=99; La syntaxe permettant linitialisation dun tableau plusieurs dimensions au moment de sa dclaration et un petit peupluscomplexe. int[][] grille={{11,12,13},{21,22,23},{31,32,33}}; Cetexemplecreuntableaudeuxdimensionsdetroiscasessurtroiscases. Lacrationaveccettetechniquedetableauxdegrandetailleplusieursdimensionsrisquedtreprilleuse. Manipulationscourantesavecdestableaux Lorsque lon travaille avec les tableaux, certaines oprations doivent tre frquemment ralises. Ce paragraphe dcritlesoprationslespluscourantesralisessurlestableaux.Laplupartdentreellessontdisponiblesgrcela classejava.util.Arraysfournissantdenombreusesmthodesstaticdemanipulationdetableaux. Obtenirlatailledun tableau : il suffit dutiliser la propritlength du tableau pour connatre le nombre dlments quilpeutcontenir.Danslecasduntableaumultidimensionnel,ilfautsesouvenirquilsagitenfaitdetableauxde tableaux. La proprit lengthindiquealorslenombredlments sur la premire dimension. Pour obtenir la mme information sur les autres dimensions, il faut utiliser la proprit length de chaque case du tableau de niveau infrieur. matrice=new int[8][3]; System.out.println("le tableau comporte " + matrice.length + " cases sur " + matrice[0].length + " cases"); Rechercherunlmentdansuntableau :lafonctionbinarySearchpermetdeffectuerunerecherchedansuntableau. Elleacceptecommeparamtresletableaudanslequelsefaitlarechercheetllmentrecherchdansletableau.La valeurretournecorrespondlindexollmentattrouvdansletableauouunevaleurngativesillment nesetrouvepasdansletableau.Pourquecettefonctionfonctionnecorrectementletableaudoittreaupralable tri. int[] chiffreAffaire={1234,563,657,453,986,678,564,234,786,123,534,975}; Arrays.sort(chiffreAffaire); System.out.println(Arrays.binarySearch(chiffreAffaire, 123)); Trier un tableau : la fonction sort assure le tri du tableau quelle reoit en paramtre. Le tri se fait par ordre alphabtique pour les tableaux de chane de caractres et par ordre croissant pour les tableaux de valeurs numriques. int[] chiffreAffaire={1234,563,657,453,986,678,564,234,786,123,534,975}; Arrays.sort(chiffreAffaire); for (int i=0;i<chiffreAffaire.length;i++) { System.out.print(chiffreAffaire[i] + "\t"); } Affichelersultatsuivant : 123 234 453 534 563 564 657 678 786 975 986 1234

Afficheruntableau :lafonctiontoStringpermetdobtenirunereprsentationsousformedunechanedecaractres dutableaupassenparamtre. System.out.println(Arrays.toString(chiffreAffaire)); Affichelersultatsuivant : [123, 234, 453, 534, 563, 564, 657, 678, 786, 975, 986, 1234] LafonctiondeepToStringeffectuelammeoprationmaispouruntableauplusieursdimensions.

- 10 -

ENI Editions - All rigths reserved

int[][] grille={{11,12,13},{21,22,23},{31,32,33}}; System.out.println(Arrays.deepToString(grille)); Affichelersultatsuivant : [[11, 12, 13], [21, 22, 23], [31, 32, 33]] Copieruntableau :deuxfonctionssontdisponiblespourlacopiedetableaux. LafonctioncopyOfcopieuntableauentieraveclapossibilitdemodifierlatailledutableau.LafonctioncopyOfRange effectueunecopiedunepartieduntableau. int[] copieChiffreAffaire; copieChiffreAffaire=Arrays.copyOf(chiffreAffaire, 24); System.out.println(Arrays.toString(copieChiffreAffaire)); Affichelersultatsuivant : [1234, 563, 657, 453, 986, 678, 564, 234, 786, 123, 534, 975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

int[] premierTrimestre; premierTrimestre=Arrays.copyOfRange(chiffreAffaire, 0, 3); System.out.println(Arrays.toString(premierTrimestre)); Affichelersultatsuivant : [1234, 563, 657] Rempliruntableau :lafonctionfillestutilisablepourremplirtouteslescasesduntableauaveclammevaleur.

5.Leschanesdecaractres
LesvariablesdetypeStringpermettentlamanipulationdechanesdecaractresparvotreapplication. Nousallonsregardercommentraliserlesoprationslespluscourantessurleschanesdecaractres. Crationdunechanedecaractres LamthodelaplussimplepourcrerunechanedecaractresconsisteconsidrerletypeStringcommeuntype de base du langage et non comme un type objet. Cest dans ce cas laffectation dune valeur la variable qui va provoquerlacrationduneinstancedelaclasseString.Lacrationdunechanedecaractrescommeunobjetest biensrgalementpossibleenutilisantloprateurnewetundesnombreuxconstructeursdisponiblesdanslaclasse String.Lexempledecodesuivantprsentelesdeuxsolutions. String chaine1="eni"; String chaine2=new String("eni"); Aprssacrationunechanedecaractresnepeutplustremodifie.Laffectationduneautrevaleurlavariable provoquelacrationdunenouvelleinstancedelaclasseString.LaclasseStringcontientdenombreusesmthodes permettantlamodificationdechanesdecaractres.lutilisation,nousavonslimpressionquelafonctionmodifiele contenu de la chane initiale mais en fait cest une nouvelle instance contenant le rsultat qui est renvoye par la fonction. Affectationdunevaleurunechane Nousavonsvuquepouraffecterunevaleurunechaneilfautlaspcifierentrelescaractres"et",unproblmese posesinousvoulonsquelecaractre"fassepartiedelachane.Pourquilnesoitpasinterprtcommecaractre dedbutoudefindechaneilfautleprotgerparunesquencedchappementcommedanslexemplecidessous: String Chaine; Chaine=" il a dit : \" a suffit ! \""; System.out.println(Chaine); Nousobtenonslaffichage:iladit:"asuffit!"

ENI Editions - All rigths reserved

- 11 -

Pourlesexemplessuivants,nousallonstravailleravecdeuxchanes: chaine1 = "lhiver sera pluvieux"; chaine2 = "lhiver sera froid"; Extractionduncaractreparticulier Pourobtenirlecaractreprsentunepositiondonnedunechanedecaractres,ilfaututiliserlafonctioncharAt en fournissant comme argument lindex du caractre que lon souhaite obtenir. Le premier caractre a lindex zro commepouruntableau.Cettefonctionretourneuncaractre(char). System.out.println("le troisieme caractere de la chaine1 est " + chaine1.charAt(2));

Obtenirlalongueurdunechane Pourdterminerlalongueurdunechane,lafonctionlengthdelaclasseStringestdisponible. System.out.println("la chaine1 contient " + chaine1.length() + " caracteres");

Dcoupagedechane LafonctionsubstringdelaclasseStringretourneuneportiondechaneenfonctiondelapositiondedpartetdela position de fin qui lui sont passes comme paramtres. La chane obtenue commence par le caractre situ la positiondedpartetsetermineaucaractreprcdantlapositiondefin. System.out.println("un morceau de la chaine1 : " + chaine1.substring(2,8)); Nousobtenonslaffichage : un morceau de la chaine1 : hiver

Comparaisondechanes Lorsquon fait une comparaison de deux chanes, on est tent dutiliser le double gal (==), comme cidessus. Cet oprateur fonctionne correctement sur les types de base mais il ne faut pas perdre de vue que les chanes de caractres sont des types objet. Il faut donc utiliser les mthodes de la classe String pour effectuer des comparaisonsdechanesdecaractres.Lamthodeequalseffectueunecomparaisondelachaneaveccellequiest passecommeparamtre.Elleretourneun booleangal truesilesdeuxchanessontidentiquesetbiensrun booleangalfalsedanslecascontraire.Cettefonctionfaitunedistinctionentreminusculesetmajusculeslorsde la comparaison. La fonction equalsIgnoreCase effectue un traitement identique mais sans tenir compte de cette distinction. if (chaine1.equals(chaine2)) { System.out.println("les deux chaines sont identiques"); } else { System.out.println("les deux chaines sont diffrentes"); } Pourraliserunclassement,vousdevezparcontreutiliserlamthodecompareTodelaclasseStringoulafonction compareToIgnoreCase.Aveccesdeuxsolutionsilfautpassercommeparamtreslachanecomparer.Lersultatde la comparaison est retourn sous forme dun entier infrieur zro si la chane est infrieure celle reue comme paramtre, gal zro si les deux chanes sont identiques, et suprieur zro si la chane est suprieure celle reuecommeparamtre. if (chaine1.compareTo(chaine2)>0) { System.out.println("chaine1 est superieure a chaine2"); } else if (chaine1.compareTo(chaine2)<0) {

- 12 -

ENI Editions - All rigths reserved

System.out.println("chaine1 est inferieure a chaine2"); } else { System.out.println("les deux chaines sont identiques"); } LesfonctionsstartsWithetendsWithpermettentdetestersilachanedbuteparlachanereueenparamtreousi la chane se termine par la chane reue en paramtre. La fonction endsWith peut par exemple tre utilise pour testerlextensiondunnomdefichier. String nom="Code.java"; if (nom.endsWith(".java")) { System.out.println("c\est un fichier source java"); } Suppressiondesespaces La fonction trim permet de supprimer les espaces situs avant le premier caractre significatif et aprs le dernier caractresignificatifdunechane. String chaine=" eni "; System.out.println("longueur de la chaine : " + chaine.length()); System.out.println("longueur de la chaine nettoyee : " + chaine.trim() .length()); Changerlacasse Toutenmajuscules System.out.println(chaine1.toUpperCase()); Toutenminuscules System.out.println(chaine1.toLowerCase());

Recherchedansunechane La mthode indexOf de la classe String permet la recherche dune chane lintrieur dune autre. Le paramtre correspond la chane recherche. La fonction retourne un entier indiquant la position laquelle la chane a t trouveou1silachanenapasttrouve.Pardfautlarecherchecommenceaudbutdelachane,saufsivous utilisez une autre version de la fonctionindexOfquielleattenddeuxparamtres,lepremierparamtretantpour cetteversion,lachanerechercheetledeuximelapositiondedpartdelarecherche. String recherche; int position; recherche = "e"; position = chaine1.indexOf(recherche); while (position > 0) { System.out.println("chaine trouve la position " + position); position = chaine1.indexOf(recherche,position+1); } System.out.println("fin de la recherche");

Nousobtenonslaffichage : chaine chaine chaine fin de trouve la position 5 trouve la position 9 trouve la position 18 la recherche

Remplacementdansunechane

ENI Editions - All rigths reserved

- 13 -

Il est parfois souhaitable de pouvoir rechercher la prsence dune chane lintrieur dune autre, comme dans lexemple prcdent, mais galement remplacer les portions de chanes trouves. La fonction replace permet de spcifierunechanedesubstitutionpourlachanerecherche.Elleattenddeuxparamtres:
q

lachanerecherche lachanederemplacement.

String chaine3; chaine3= chaine1.replace("hiver", "ete"); System.out.println(chaine3); Nousobtenonslaffichage : lete sera pluvieux

- 14 -

ENI Editions - All rigths reserved

Lesoprateurs
Les oprateurs sont des mots cls du langage permettant lexcution doprations sur le contenu de certains lments,engnraldesvariables,desconstantes,desvaleurslittrales,oudesretoursdefonctions.Lacombinaison dunoudeplusieursoprateursetdlmentssurlesquelslesoprateursvontsappuyersenommeuneexpression. Ces expressions sont values au moment de lexcution en fonction des oprateurs et des valeurs qui sont associes. Deuxtypesdoprateurssontdisponibles :
q

Lesoprateursunairesquinetravaillentquesurunseuloprande. Lesoprateursbinairesquincessitentdeuxoprandes.

Les oprateurs unaires peuvent tre utiliss avec la notation prfixe, dans ce cas loprateur est plac avant loprande, et la notation postfixe avec dans ce cas loprateur plac aprs loprande. La position de loprateur dterminelemomentoceluiciestappliqusurlavariable.Siloprateurestprfixilsappliquesurloprandeavant que celuici ne soit utilis dans lexpression. Avec la notation postfixe loprateur nest appliqu sur la variable quaprs utilisation de celleci dans lexpression. Cette distinction peut avoir une influence sur le rsultat dune expression. int i; i=3; System.out.println(i++); Affiche3carlincrmentationestexcuteaprsutilisationdelavariableparlinstructionprintln. int i; i=3; System.out.println(++i); Affiche4carlincrmentationestexcuteavantlutilisationdelavariableparlinstructionprintln. Silavariablenestpasutilisedansuneexpressionlesdeuxversionsconduisentaummersultat. Lalignedecode i++ ; estquivalentlalignedecode ++i ; Lesoprateurspeuventtrerpartisenseptcatgories.

1.Lesoprateursunaires
Oprateur ~ ++ ! Valeurngative Complmentun Incrmentation Dcrmentation Ngation Action

Loprateur ! nest utilisable que sur des variables de type boolean ou sur des expressions produisant un type boolean(comparaison).

ENI Editions - All rigths reserved

- 1-

2.Lesoprateursdaffectation
Leseuloprateurdisponibledanscettecatgorieestloprateur=.Ilpermetdaffecterunevariableunevaleur.Le mmeoprateurestutilisquelquesoitletypedelavariable(numrique,chanedecaractres). Cetoprateurpeuttrecombinavecunoprateurarithmtique,logiqueoubinaire. Lasyntaxesuivante x+=2 ; estquivalente x=x+2 ;

3.Lesoprateursarithmtiques
Lesoprateursarithmtiquespermettentdeffectuerdescalculssurlecontenudesvariables. Oprateur + * / % Addition Soustraction Multiplication Division Modulo(restedeladivisionentire) Oprationralise Exemple 6+4 126 3*4 25/3 25mod3 10 6 12 8.3333333333 1 Rsultat

4.Lesoprateursbitbit
Cesoprateurseffectuentdesoprationssurdesentiersuniquement(Byte,Short,Integer,Long).Ilstravaillentau niveaudubitsurlesvariablesquilsmanipulent. Oprateur & | ^ >> << Oprationralise EtBinaire OuBinaire Ouexclusif Dcalageversladroite(divisionpar2) Dcalageverslagauche(multiplication par2) Exemple 45&255 99|46 99^46 26>>1 26<<1 45 111 77 13 52 Rsultat

5.Lesoprateursdecomparaison
Les oprateurs de comparaison sont utiliss dans les structures de contrle dune application (if, while). Ils renvoientunevaleurdetypebooleanenfonctiondursultatdelacomparaisoneffectue.Cettevaleurseraensuite utiliseparlastructuredecontrle. Oprateur Oprationralise Exemple Rsultat

- 2-

ENI Editions - All rigths reserved

== != < > <= >= instanceof

Egalit Ingalit Infrieur Suprieur Infrieurougal Suprieurougal Comparaisondutypedela variableavecletypeindiqu

2==5 2 !=5 2<5 2>5 2<=5 2>=5 O1instanceof Client

false true true false true false TruesilavariableO1 rfrenceunobjetcr partirdelaclasseclientou dunesousclasse

6.Loprateurdeconcatnation
Loprateur + dj utilis pour laddition est galement utilis pour la concatnation de chanes de caractres. Le fonctionnement de loprateur est dtermin par le type des oprandes. Si un des oprandes est du type String alorsloprateur+effectueuneconcatnationavecventuellementuneconversionimplicitedelautreoprandeen chanedecaractres. Petit inconvnient de loprateur +, il ne brille pas par sa rapidit pour les concatnations. En fait ce nest pas rellementloprateurquiestencausemaislatechniqueutiliseparJavapourgrerleschanesdecaractres(elles ne peuvent pas tre modifies aprs cration). Si vous avez de nombreuses concatnations excuter sur une chane,ilestprfrabledutiliserlaclasseStringBuffer. Exemple long duree; String lievre; String tortue=""; long debut, fin; debut = System.currentTimeMillis(); for (int i = 0; i <= 10000; i++) { tortue = tortue + " " + i; } fin = System.currentTimeMillis(); duree = fin-debut; System.out.println("dure pour la tortue : " + duree + "ms"); debut = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); for (int i = 0; i <= 10000; i++) { sb.append(" "); sb.append(i); } lievre = sb.toString(); fin = System.currentTimeMillis(); duree = fin-debut; System.out.println("dure pour le livre : " + duree + "ms"); if (lievre.equals(tortue)) { System.out.println("les deux chaines sont identiques"); } Rsultatdelacourse : dure pour la tortue : 953ms dure pour le lievre : 0ms les deux chaines sont identiques

ENI Editions - All rigths reserved

- 3-

Cersultatsepassedecommentaire !

7.Lesoprateurslogiques
Les oprateurs logiques permettent de combiner les expressions dans des structures conditionnelles ou des structuresdeboucle. Oprateur & Opration Etlogique Exemple If((test1)& (test2)) If((test1)| (test2)) If((test1)^ (test2)) If(!Test) If((test1)&& (test2)) If((test1)|| (test2)) Rsultat vraisitest1ettest2estvrai

Oulogique

vraisitest1outest2estvrai

Ouexclusif

vraisitest1outest2estvraimaispas silesdeuxsontvraissimultanment Inverselersultatdutest Idemetlogiquemaistest2nesera valuquesitest1estvrai Idemoulogiquemaistest2nesera valuquesitest1estfaux

! &&

Ngation Etlogique

||

Oulogique

Ilfaudratreprudentaveclesoprateurs&&et||carlexpressionquevoustesterezensecond(test2dansnotre cas)pourraparfoisnepastreexcute.Sicettedeuximeexpressionmodifieunevariable,cellecineseramodifie quedanslescassuivants:


q

premiertestvraidanslecasdu&& premiertestfauxdanslecasdu||

8.Ordredvaluationdesoprateurs
Lorsque plusieurs oprateurs sont combins dans une expression, ils sont valus dans un ordre bien prcis. Les incrmentations et dcrmentations prfixes sont excutes en premier puis les oprations arithmtiques, les oprationsdecomparaison,lesoprateurslogiquesetenfinlesaffectations. Les oprateurs arithmtiques ont entre eux galement un ordre dvaluation dans une expression. Lordre dvaluationestlesuivant:
q

Ngation() Multiplicationetdivision(*,/) Divisionentire(\) Modulo(Mod) Additionetsoustraction(+,),concatnationdechanes(+)

Siunordredvaluationdiffrentestncessairedansvotreexpression,ilfautplacerlesportionsvaluerenpriorit entreparenthsescommedanslexpressionsuivante: X= (z * 4) ^ (y * (a + 2)) ; Vous pouvez utiliser autant de niveaux de parenthses que vous le souhaitez dans une expression. Il importe

- 4-

ENI Editions - All rigths reserved

cependant que lexpression contienne autant de parenthses fermantes que de parenthses ouvrantes sinon le compilateurgnrerauneerreur.

ENI Editions - All rigths reserved

- 5-

Lesstructuresdecontrle
Lesstructuresdecontrlepermettentdemodifierlordredexcutiondesinstructionsdansvotrecode.Deuxtypesde structuressontdisponibles:
q

Lesstructuresdedcision:ellesaiguillerontlexcutionducodeenfonctiondesvaleursquepourraprendre uneexpressiondetest. Les structures de boucle : elles feront excuter une portion de code un certain nombre de fois, jusqu ce quuneconditionsoitremplieoutantquuneconditionestremplie.

1.Structuresdedcision
Deuxsolutionssontpossibles.

a.StructureIf
QuatresyntaxessontutilisablespourlinstructionIf. if (condition)instruction; Silaconditionestvraiealorslinstructionestexcute.Laconditiondoittreuneexpressionqui,unefoisvalue, doitfournirunboolean trueoufalse.Aveccettesyntaxe,seulelinstructionsitueaprsleifseraexcutesila condition est vraie. Pour pouvoir faire excuter plusieurs instructions en fonction dune condition il faut utiliser la syntaxeciaprs. if (condition) { Instruction 1; .. Instruction n; } Danscecaslegroupedinstructionssituentrelesaccoladesseraexcutsilaconditionestvraie. Vouspouvezgalementspcifieruneouplusieursinstructionsquiellesserontexcutessilaconditionestfausse. if (condition) { Instruction Instruction } else { Instruction Instruction }

1; n;

1; n;

Vouspouvezgalementimbriquerlesconditionsaveclasyntaxe. if (condition1) { Instruction 1 Instruction n } else if (Condition 2) { Instruction 1 Instruction n

ENI Editions - All rigths reserved

- 1-

} else if (Condition 3) { Instruction 1 Instruction n } else { Instruction 1 Instruction n } Danscecas,ontestelapremirecondition.Sielleestvraiealorsleblocdecodecorrespondantestexcutsinon ontestelasuivanteetainsidesuite.Siaucuneconditionnestvrifie,leblocdecodespcifiaprsleelseest excut.Linstructionelsenestpasobligatoiredanscettestructure.Danscecas,ilsepeutquaucuneinstruction nesoitexcutesiaucunedesconditionsnestvraie. Ilexistegalementunoprateurconditionnelpermettantdeffectuerunif elseenuneseuleinstruction. condition?expression1 :expression2 ; Cettesyntaxeestquivalentecelleci: If (condition) expression1 ; else expression2 ;

b.Structureswitch
Lastructureswitchpermetunfonctionnementquivalentmaisoffreunemeilleurelisibilitducode.Lasyntaxeest lasuivante: Switch (expression) { Case valeur1 : Instruction Instruction Break ; Case valeur2 : Instruction Instruction Break ; Default : Instruction Instruction }

1 n

1 n

1 n

Lavaleurdelexpressionestvalueaudbutdelastructure(parleswitch)puislavaleurobtenueestcompare aveclavaleurspcifiedanslepremiercase. Silesdeuxvaleurssontgales,alorsleblocdecode1estexcut. Sinon,lavaleurobtenueestcompareaveclavaleurducasesuivant,silyacorrespondance,leblocdecodeest excutetainsidesuitejusquauderniercase. Siaucunevaleurconcordantenesttrouvedanslesdiffrents casealorsleblocdecodespcifidansledefault estexcut.Chacundesblocsdecodedoitseterminerparlinstructionbreak.Sicenestpaslecaslexcutionse poursuivra par le bloc de code suivant jusqu ce quune instruction break soit rencontre ou jusqu la fin de la structure switch. Cette solution peut tre utilise pour pouvoir excuter un mme bloc de code pour diffrentes valeurstestes. Lavaleurtesterpeuttrecontenuedansunevariablemaisellepeutgalementtrelersultatduncalcul.Dans ce cas, le calcul nest effectu quune seule fois au dbut du switch. Le type de la valeur teste peut tre

- 2-

ENI Editions - All rigths reserved

numriqueentire,caractreounumration.Ilfautbiensrqueletypedelavariabletestecorrespondeautype desvaleursdanslesdiffrentscase. switch (reponse) { case o: case O: System.out.println("reponse positive"); break; case n: case N: System.out.println("reponse negative"); break; default: System.out.println("mauvaise reponse"); }

2.Lesstructuresdeboucle
Troisstructuressontnotredisposition : while (condition) do ... while (condition) for Ellesonttoutespourbutdefaireexcuterunblocdecodeuncertainnombredefoisenfonctiondunecondition.

a.Structurewhile
Cettestructureexcuteunblocdefaonrptitivetantquelaconditionesttrue. while (condition) { Instruction 1 Instruction n } La condition est value avant le premier passage dans la boucle. Si elle est false cet instant alors le bloc de codenestpasexcut.Aprschaqueexcutiondublocdecodelaconditionestnouveauvaluepourvrifiersi une nouvelle excution du bloc de code est ncessaire. Il est recommand que lexcution du bloc de code contienne une ou plusieurs instructions susceptibles de faire voluer la condition. Si ce nestpaslecaslaboucle sexcuterasansfin.Ilnefautsurtoutpasplacerdecaractreaprslewhilecardanscecas,leblocdecodenest plusassocilaboucle. int i=0; while (i<10) { System.out.println(i); i++; }

b.Structuredo while
do { Instruction 1 Instruction n } while (condition) ; Cettestructureaunfonctionnementidentiquelaprcdentesaufquelaconditionestexamineaprslexcution

ENI Editions - All rigths reserved

- 3-

du bloc de code. Elle nous permet de garantir que le bloc de code sera excut au moins une fois puisque la condition sera teste pour la premire fois aprs la premire excution du bloc de code. Si la condition est true alorsleblocestexcutunenouvellefoisjusqucequelaconditionsoitfalse.Vousdevezfaireattentionne pasoublierlepointvirguleaprslewhilesinonlecompilateurdtecteuneerreurdesyntaxe. do { System.out.println(i); i++; } while(i<10);

c.Structurefor
Lorsque vous connaissez le nombre ditrations raliser dans une boucle il est prfrable dutiliser la structure for. Pour pouvoir utiliser cette instruction, une variable de compteur doit tre dclare. Cette variable peut tre dclaredanslastructureforoulextrieur,elledoitdanscecastredclareavantlastructurefor. Lasyntaxegnraleestlasuivante : for(initialisation ;condition ;instruction ditration) { Instruction 1 Instruction n

} Lapartieinitialisationestexcuteuneseulefoislorsdelentredanslaboucle.Lapartieconditionestvalue lorsdelentredanslabouclepuischaqueitration.Lersulatdelvaluationdelaconditiondterminesilebloc decodeestexcut,ilfautpourcelaquelaconditionsoitvaluecommetrue.Aprslexcutiondublocdecode linstructionditrationestsontourexcute.Puislaconditionestnouveautesteetainsidesuitetantquela conditionestvaluecommetrue. Voicicidessousdeuxbouclesforenactionpourafficherunetabledemultiplication. int k; for(k=1;k<10;k++) { for (int l = 1; l < 10; l++) { System.out.print(k * l + "\t"); } System.out.println(); } Nousobtenonslersultatsuivant : 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81

Uneautresyntaxedelaboucleforpermetdefaireexcuterunblocdecodepourchaquelmentcontenudansun tableauoudansuneinstancedeclasseimplmentantlinterfaceIterable.Lasyntaxegnraledecetteinstruction estlasuivante : for( type variable : tablo) { Instruction 1 Instruction n

- 4-

ENI Editions - All rigths reserved

} Il ny a pas de notion de compteur dans cette structure puisquelle effectue ellemme les itrations sur tous les lmentsprsentsdansletableauoulacollection. Lavariabledclaredanslastructuresertextraireununleslmentsdutableauoudelacollectionpourquele bloc de code puisse les manipuler. Il faut bien sr que le type de la variable soit compatible avec le type des lmentsstocksdansletableauoulacollection.Lavariabledoitobligatoirementtredclaredanslastructure for et non lextrieur. Elle ne sera utilisable qu lintrieur de la structure. Par contre vous navez pas vous soucierdunombredlmentscarlastructureestcapabledegrerellemmeledplacementdansletableauoula collection.Voiciunpetitexemplepourclarifierlasituation ! Avecuneboucleclassique : String[] tablo={"rouge","vert","bleu","blanc"}; int cpt; for (cpt = 0; cpt < tablo.length; cpt++) { System.out.println(tablo[cpt]); } Aveclaboucleforditration: String[] tablo={"rouge","vert","bleu","blanc"}; for (String s : tablo) { System.out.println(s); }

d.Interruptiondunestructuredeboucle
Troisinstructionspeuventmodifierlefonctionnementnormaldesstructuresdeboucle. break Si cette instruction est place lintrieur du bloc de code dune structure de boucle elle provoque la sortie immdiate de ce bloc de code. Lexcution se poursuit par linstruction place aprs le bloc de code. Cette instructiondoitengnraltreexcutedemanireconditionnelle,sinonlesinstructionssituesaprslintrieur delaboucleneserontjamaisexcutes. Continue Cetteinstructionpermetdinterromprelexcutiondelitrationcouranteduneboucleetdecontinuerlexcution litration suivante aprs vrification de la condition de sortie de boucle. Comme pour linstruction break elle doit treexcutedemanireconditionnelle. Voici un exemple de code utilisant une boucle sans fin et ses deux instructions pour afficher les nombres impairs jusqucequelutilisateursaisisseunretourchariot. import java.io.IOException; public class TestStructures { static boolean stop; public static void main(String[] args) { new Thread() { public void run() { int c; try { c=System.in.read(); stop=true; } catch (IOException e) { e.printStackTrace(); } }

ENI Editions - All rigths reserved

- 5-

}.start(); long compteur=0; while(true) { compteur++; if (compteur%2==0) continue; if (stop) break; System.out.println(compteur); } } } Return Linstruction return est utilise pour sortir immdiatement de la mthode en cours dexcution et poursuivre lexcutionparlinstructionsuivantcellequiaappelcettemthode.Sielleestplacedansunestructuredeboucle, elle provoque bien sr la sortie immdiate de la boucle puis de la mthode dans laquelle se trouve la boucle. Lutilisation de cette instruction dans une fonction dont le type de retour est autre que void oblige fournir linstructionreturnunevaleurcompatibleavecletypederetourdelafonction.

- 6-

ENI Editions - All rigths reserved

Introduction
AvecJava,lanotiondobjetestomniprsenteetncessiteunminimumdapprentissage.Nousallonsdoncvoirdansun premier temps les principes de la programmation objet et le vocabulaire associ, puis nous verrons comment mettre celaenapplicationavecJava. Dansunlangageprocduralclassique,lefonctionnementduneapplicationestrglparunesuccessiondappelsaux diffrentesprocduresetfonctionsdisponiblesdanslecode.Cesprocduresetfonctionssontchargesdemanipuler les donnes de lapplication qui sont reprsentes par les variables de lapplication. Il ny a aucun lien entre les donnes et le code qui les manipule. Dans un langage objet on va au contraire essayer de regrouper le code. Ce regroupement est appel une classe. Une application dveloppe avec un langage objet est donc constitue de nombreuses classes reprsentant les diffrents lments manipuls par lapplication. Les classes vont dcrire les caractristiques de chacun des lments. Cest ensuite lassemblage de ces lments qui va permettre le fonctionnementdelapplication. Ceprincipeestlargementutilisdansdautresdomainesquelinformatique.Danslindustrieautomobile,parexemple,il nexiste certainement pas chez aucun constructeur un plan complet dcrivant les milliers de pices constituant un vhicule. Par contre chaque sousensembledun vhicule peut tre reprsent par un plan spcifique (le chssis, la bote de vitesse, le moteur). Chaque sousensemble est galement dcompos jusqu la pice lmentaire (un boulon,unpiston,unpignon).Cestlassemblagedetousceslmentsquipermetlafabricationdunvhicule. En fait ce nest pas lassemblage des plans qui permet la construction du vhicule, mais lassemblage des pices fabriques partir de ces plans. Dans une application informatique cest lassemblage des objets crs partir des classesquivapermettrelefonctionnementdelapplication.Lesdeuxtermesclasseetobjetsontsouventconfondus maisilsreprsententdesnotionsbiendistinctes.Laclassedcritlastructuredunlmentalorsquelobjetreprsente un exemplaire cr sur le modle de cette structure. Aprs sa cration un objet est indpendant des autres objets construitspartirdelammeclasse.Parexempleuneportiredevoiturepourraaprsfabricationtrepeintedune couleurdiffrentedesautresportiresfabriquesselonlemmeplan. Parcontresileplanvienttremodifi,touteslesportiresfabriquesaprslamodificationduplanbnficierontdes changementsapportsauplan(aveclerisquedeneplustrecompatiblesaveclesanciennesversions). Lesclassessontconstituesdechampsetdemthodes.Leschampsreprsententlescaractristiquesdesobjets.Ils sont reprsents par des variables et il est donc possible de lire leur contenu ou de leur affecter une valeur directement. Le robot qui va peindre une portire va modifier le champ couleur de cette portire. Les mthodes reprsentent les actions quun objet peut effectuer. Elles sont mises en uvre par la cration de procdures ou de fonctionsdansuneclasse. Cecinestquunefacettedelaprogrammationorientobjet.Troisautresconceptssontgalementfondamentaux :
q

Lencapsulation Lhritage Lepolymorphisme

Lencapsulation consiste cacher les lments qui ne sont pas ncessaires pour lutilisation dun objet. Cette technique permet de garantir que lobjet sera correctement utilis. Cest un principe qui est aussi largement utilis dans dautresdomainesquelinformatique. Pour reprendre lexemple de lindustrie automobile, savezvous comment fonctionne la bote de vitesse de votre voiture ? Pour changer de vitesse allezvous directement modifier la position desdiffrentsengrenages ?Heureusementquenon.Lesconstructeursontenfaitprvudessolutionspluspratiques pourlamanipulationdelabotedevitesse. Leslmentsduneclassevisiblesdelextrieurdelaclassesontappelslinterfacedelaclasse.Danslecasdenotre voiture,lelevierdevitesseconstituelinterfacedelabotedevitesse.Cestparsonintermdiairequelonpeutagir sansrisquesurlesmcanismesinternesdelabotedevitesse. Lhritagepermetlacrationdunenouvelleclassepartirduneclasseexistante.Laclasseservantdemodleest appele classe de base. La classe ainsi cre hrite des caractristiques de sa classe de base. Elle peut aussi tre personnalise en y ajoutant des caractristiques supplmentaires. Les classes cres partir dune classe de base sontappelesclassesdrives.Ceprincipeestbiensraussiutilisdanslemondeindustriel.Labotedevitessede votrevoiturecomportecertainementcinqrapports.Lesingnieursquiontconucettepicenesontcertainementpas repartisdezro.Ilsontreprisleplandelagnrationprcdente(quatrerapports)etyontajoutdeslments.De mmequelesingnieursquirflchissentdjlabotedevitessesixrapportsdevotrefuturevoiturevontrepartir delaversionprcdente. Lepolymorphismeestuneautrenotionimportantedelaprogrammationorienteobjet.Parsonintermdiaire,ilest possibledutiliserplusieursclassesdemanireinterchangeablemmesilefonctionnementinternedecesclassesest diffrent.SivoussavezchangerdevitessesurunevoiturePeugeot,voussavezgalementcommentlefairesurune voitureRenaultetpourtantlesdeuxtypesdebotedevitessenesontpasconusdelammefaon. Deux autres concepts sont galement associs au polymorphisme. La surcharge et le masquage de mthodes. La

ENI Editions - All rigths reserved

- 1-

surcharge est utilise pour concevoir dans une classe des mthodes ayant le mme nom mais ayant un nombre de paramtresdiffrentoudestypesdeparamtresdiffrents.Lemasquageestutilislorsquedansuneclassedrive, onsouhaitemodifierlefonctionnementdunemthodedontonahrit.Lenombreetletypedesparamtresrestant identiquesceuxdfinisdanslaclassedebase. Voicimisenplacelesquelquesprincipesdebasedelaprogrammationobjet.Lesujetdecetouvragentantpasla mcaniqueautomobilenousallonstoutdesuitevoirlamiseen uvredecesprincipesaveclelangageJava.

- 2-

ENI Editions - All rigths reserved

MiseenuvreavecJava
Danslerestedecechapitre,nousallonstravaillersurlaclassePersonnedontlareprsentationUML(UnifiedModeling Language)estdisponiblecidessous.

UML est un langage graphique ddi la reprsentation des concepts de programmation oriente objet. Pour plus dinformationssurcelangage,vouspouvezconsulterlouvrageUML2danslacollectionRessourcesInformatiquesdes ditionsENI.

1.Crationduneclasse
Lacrationduneclassepasseparladclarationdelaclasseellemmeetdetousleslmentslaconstituant.

a.Dclarationdelaclasse
La dclaration dune classe se fait en utilisant le mot cl class suivi du nom de la classe puis dun bloc de code dlimit par les caractres { et }. Dans ce bloc de code, on trouve des dclarations de variables qui seront les champsdelaclasseetdesfonctionsquiserontlesmthodesdelaclasse.Plusieursmotsclspeuventtreajouts pourmodifierlescaractristiquesdelaclasse.Lasyntaxegnralededclarationduneclasseestdonclasuivante. [liste de modificateurs] class NomDeLaClasse [extends NomDeLaClasseDeBase] [implements NomDeInterface1,NomDeInterface2,] { Code de la classe } Les signes [ et ] sont utiliss ici pour indiquer le caractre optionnel de llment. Ils ne doivent pas tre utiliss danslecodededclarationduneclasse.

ENI Editions - All rigths reserved

- 1-

Lesmodificateurspermettentdedterminerlavisibilitdelaclasseetcommentvouspouvezlutiliser.Voicilaliste desmodificateursdisponibles : public:indiquequelaclassepeuttreutilisepartouteslesautresclasses.Sanscemodificateurlaclassenesera utilisablequeparlesautresclassesfaisantpartiedummepackage. abstract : indique que la classe est abstraite et ne peut donc pas tre instancie. Elle ne peut tre utilise que commeclassedebasedansunerelationdhritage.Engnral,danscegenredeclasseseuleslesdclarationsde mthodessontdfinies,etilfaudracrirelecontenudesmthodesdanslesclassesdrives. final :laclassenepeutpastreutilisecommeclassedebasedansunerelationdhritageetpeutuniquement treinstancie. Lasignificationdesmotsclsabstractetfinaltantcontradictoireleurutilisationsimultaneestbiensrinterdite. Pour indiquer que votre classe rcupre les caractristiques dune autre classe par une relation dhritage, vous devezutiliserlemotclextendssuividunomdelaclassedebase.Vouspouvezgalementimplmenterdansvotre classeuneouplusieursinterfacesenutilisantlemot implementssuividelalistedesinterfacesimplmentes.Ces deuxnotionsserontvuesendtailplusloindanscechapitre. LedbutdeladclarationdenotreclassePersonneestdonclesuivant: public class Personne { } Cecodedoitobligatoirementtresaisidansunfichierayantlemmenomquelaclasseetlextension.java.

b.Crationdeschamps
Intressonsnous maintenant au contenu de notre classe. Nous devons crer les diffrents champs de la classe. Pour cela il suffit de dclarer des variables lintrieur du bloc de code de la classe en indiquant la visibilit de la variable,sontypeetsonnom. [private | protected | public] typeDeLaVariable nomDeLaVariable ; Lavisibilitdelavariablerpondauxrglessuivantes: private :lavariablenestaccessiblequedanslaclasseoelleestdclare. protected :lavariableestaccessibledanslaclasseoelleestdclare,danslesautresclassesfaisantpartiedu mmepackageetdanslesclasseshritantdelaclasseoelleestdclare. public :lavariableestaccessiblepartirdenimporteo. Siaucuneinformationnestfournieconcernantlavisibilit,lavariableestaccessiblepartirdelaclasseoelleest dclare et des autres classes faisant partie du mme package. Lorsque que vous choisissez la visibilit dune variablevousdevezautantquepossiblerespecterleprincipedencapsulationetlimiteraumaximumlavisibilitdes variables.Lidaltantdetoujoursavoirdesvariablesprivateouprotectedmaisjamaispublic. Lavariabledoitgalementavoiruntype.Ilnyapasdelimitationconcernantletypedunevariableetvouspouvez doncutiliseraussibienlestypesdebasedulangageJavatelsqueint,float,char,quedestypesdobjets. Lenomdelavariabledoitquantluisimplementrespecterlesrglesdenommage(pasdutilisationdemotcldu langage). LaclassePersonneprenddoncmaintenantlaformesuivante: public class { private private private } Personne String nom; String prenom; GregorianCalendar date_nais;

c.Crationdemthodes
Lesmthodessontsimplementdesfonctionsdfinieslintrieurduneclasse.Ellessontengnralutilisespour manipulerleschampsdelaclasse.Lasyntaxegnralededclarationdunemthodeestdcritecidessous. [modificateurs] typeDeRetour nomDeLaMethode ([listeDesParamtres])

- 2-

ENI Editions - All rigths reserved

[throws listeException] { } Lesmodificateurssuivantssontdisponibles : private :indiquequelamthodenepeuttreutilisequedanslaclasseoelleestdfinie. protected : indique que la mthode peut tre utilise dans la classe o elle est dfinie, dans les sousclasses de cetteclasseetdanslesclassesfaisantpartiedummepackage. public :indiquequelamthodepeuttreutilisedepuisnimportequelleautreclasse. Siaucundecesmotsclsnestutilisalorslavisibilitseralimiteaupackagedanslequellaclasseestdfinie. static :indiquequelamthodeestunemthodedeclasse. abstract :indiquequelamthodeestabstraiteetquellenecontientpasdecode.Laclasseoelleestdfiniedoit elleaussitreabstraite. final :indiquequelamthodenepeutpastresubstituedansunesousclasse. native :indiquequelecodedelamthodesetrouvedansunfichierexternecritdansunautrelangage. synchronized :indiquequelamthodenepeuttreexcutequeparunseulthreadlafois. Letypederetourpeuttrenimportequeltypededonnes,typedebasedulangageoutypeobjet.Silamthode napasdinformationrenvoyervousdevezutiliserlemotclvoidenremplacementdutypederetour. Lalistedesparamtresestidentiqueunelistededclarationdevariables.Ilfautspcifierletypeduparamtreet lenomduparamtre.Siplusieursparamtressontattendusilfautsparerleurdclarationparunevirgule.Mmesi aucunparamtrenestattendu,lesparenthsessonttoutdemmeobligatoires. Lemotclthrowsindiquelalistedesexceptionsquecettemthodepeutdclencherlorsdesonexcution. AjoutonsdeuxmthodesnotreclassePersonne. public class { private private private Personne String nom; String prenom; GregorianCalendar date_nais;

public long calculAge() { long age; date_nais=new GregorianCalendar(1963,11,29); age=new GregorianCalendar().getTimeInMillis()date_nais.getTimeInMillis(); age=age/1000/60/60/24/365; return age; } public void affichage() { System.out.println("nom : " + nom); System.out.println("prnom : " + prenom); System.out.println("ge : " + calculAge()); } } Danscertainslangagesdeprogrammation,ilnestpaspossibledavoirplusieursfonctionsportantlemmenom.Le langage Java comme beaucoup de langages objet permet de contourner le problme en crant des fonctions surcharges. Une fonction surcharge porte le mme nom quune autre fonction de la classe mais prsente une signaturediffrente.Lesinformationssuivantessontprisesencomptepourdterminerlasignaturedunefonction :
q

lenomdelafonction lenombredeparamtresattendusparlafonction letypedesparamtres.

ENI Editions - All rigths reserved

- 3-

Pourpouvoircrerunefonctionsurchargeilfautquaumoinsundeseslmentschangeparrapportunefonction djexistante.Lenomdelafonctiondevantresterlemmepourpouvoirrellementparlerdesurcharge,nousne pouvons donc agir que sur le nombre de paramtres ou leur type. Nous pouvons par exemple ajouter la fonction suivantelaclassePersonne: public void affichage(boolean francais) { if (francais) { System.out.println("nom : " + nom); System.out.println("prnom : " + prenom); System.out.println("ge : " + calculAge()); } else { System.out.println("name : " + nom); System.out.println("first name : " + prenom); System.out.println("age : " + calculAge()); } } Elle possde effectivement une signature diffrente de la premire fonction affichage que nous avons cre puisquelle attend un paramtre de type boolean. Si maintenant nous ajoutons la fonction suivante le compilateur refuselacompilationducode. public void affichage(boolean majuscule) { if (majuscule) { System.out.println("nom : " + nom.toUpperCase()); System.out.println("prnom : " + prenom.toUpperCase()); System.out.println("ge : " + calculAge()); } else { System.out.println("nom : " + nom.toLowerCase()); System.out.println("prnom : " + prenom.toLowerCase()); System.out.println("ge : " + calculAge()); } } Il dtermine en fait que deux fonctions ont rigoureusement la mme signature, mme nom, mme nombre de paramtres,mmetypedeparamtre.Cetexemplenousmontregalementquelenomdesparamtresnestpas prisencomptepourdterminerlasignaturedunefonction. Une fonction peut tre conue pour accepter un nombre variable de paramtres. La premire solution consiste utiliser comme paramtre un tableau et vrifier dans le code de la fonction la taille du tableau pour obtenir les paramtres.Cettesolutionncessitecependantlacrationduntableauaumomentdelappeldelafonction.Elleest doncmoinsvidentequelutilisation dunelistedeparamtres.Poursimplifierlappeldecetypedefonction,vous pouvezutiliserladclarationsuivantepourindiquerquunefonctionattendunnombrequelconquedeparamtres. public void affichage(String...couleurs) { { if (couleurs==null) { System.out.println("pas de couleur"); return; } switch (couleurs.length) { case 1: System.out.println("une couleur"); break; case 2: System.out.println("deux couleurs"); break; case 3: System.out.println("trois couleurs");

- 4-

ENI Editions - All rigths reserved

break; default : System.out.println("plus de trois couleurs"); } } } lintrieurdelamthode,leparamtrecouleursestconsidrcommeuntableau(dechanesdecaractresdans notrecas). Parcontre,lorsdelappeldelafonction,vousutilisezunelistedechanesdecaractressparespardesvirgules. Lessyntaxessuivantessonttoutfaitvalidespourlappeldecettefonction. p.affichage("rouge"); p.affichage("vert","bleu","rouge"); p.affichage(); Ilyajusteunepetiteanomalieaumomentdelexcutioncarledernierappeldelafonctionaffichagenexcutepas la fonction que nous venons de concevoir mais la premire version qui nattend aucun paramtre. En effet le compilateur ne peut pas deviner quil sagit de la version qui attend un nombre variable de paramtres que nous souhaitons excuter sans lui passer de paramtre. Pour lui montrer notre intention nous devons donc appeler la fonctionaveclasyntaxesuivante. p.affichage(null); Lorsdelappeldunefonctionlesparamtressontpasssparvaleuraussibienpourlestypesdebasedulangage (int, float, boolean, ) que pour les types objets. Cependant si un objet est pass comme paramtre une fonction, le code de la fonction a accs aux champs de lobjet et peut donc modifier leurs valeurs. Par contre si le codedelafonctionmodifielarfrenceverslobjet,celleciserartablieaprsleretourdelafonction. Il faut noter que dans les mthodes de la classe nous pouvons utiliser les champs de la classe mme sils sont dclarsprivate,carnoussommeslintrieurdelaclasse.

d.Lesaccesseurs
La dclaration des attributs avec une visibilit prive est une bonne pratique pour respecter le principe dencapsulation.Toutefoiscettesolutionestlimitativepuisqueseullecodedelaclasseoilssontdclarspeuty accder.Pourpallierceproblmevousdevezmettreenplacedesaccesseurs.Cesontdesfonctionsordinairesqui ont simplement pour but de rendre visibles les champs partir de lextrieur de la classe. Par convention les fonctions charges daffecter une valeur un champ sont nommes set suivi du nom du champ, les fonctions chargesdefournirlavaleurdunchampsontnommesgetsuividunomduchamp.Silechampestdetypeboolean, leprfixegetestremplacparleprfixeis.Siunchampdoittreenlectureseule,laccesseursetnedoitpastre disponible,siunchampdoittreencritureseulealorscestlafonctiongetquidoittreomise.Aveccettetechnique vous pouvez contrler lutilisation qui sera faite des champs dune classe. Nous pouvons donc modifier la classe Personneenyajoutantquelquesrglesdegestion.
q

Lenomdoittreenmajuscule. Leprnomdoittreenminuscule.

public class { private private private

Personne String nom; String prenom; GregorianCalendar date_nais;

public String getNom() { return nom; } public void setNom(String n) { nom = n.toUpperCase(); } public String getPrenom() {

ENI Editions - All rigths reserved

- 5-

return prenom; } public void setPrenom(String p) { prenom = p.toLowerCase(); } } Leschampsdelaclassesontmaintenantaccessiblesdepuislextrieurgrcecesmthodes. p.setNom("dupont"); p.setPrenom("albert"); System.out.println(p.getNom()); System.out.println(p.getPrenom());

e.Constructeursetdestructeurs
Les constructeurs sont des mthodes particulires dune classe par diffrents aspects. Le constructeur est une mthodeportanttoujourslemmenomquelaclasseellemme.Ilneretourneaucuntype,mmepasvoid.Ilnest jamaisappelexplicitementdanslecodemaisdemanireimplicite,lacrationduneinstancedeclasse.Comme pour une mthode classique, un constructeur peut attendre des paramtres. Le constructeur dune classe qui nattendpasdeparamtresestdsigncommeleconstructeurpardfautdelaclasse.Lerleduconstructeurest principalement linitialisation des champs dune instance de classe. Comme les autres mthodes dune classe, les constructeurspeuventgalementtresurchargs.Lacrationdunconstructeurpardfautnestpasobligatoirecar lecompilateurenfournitunautomatiquement.Ceconstructeureffectuesimplementunappelauconstructeurdela super classe qui doit bien sr exister. Par contre si votre classe contient un constructeur surcharg, elle doit galement possder un constructeur par dfaut. Une bonne habitude prendre consiste toujours crer un constructeurpardfautpourchacunedevosclasses.AjoutonslaclassePersonnedesconstructeurs. public Personne() { nom=""; prenom=""; date_nais=null; } public Personne(String n,String p,GregorianCalendar d) { nom=n; prenom=p; date_nais=d; } Les destructeurs sont dautres mthodes particulires dune classe. Comme les constructeurs ils sont appels implicitement mais uniquement lors de la destruction dune instance de classe. La signature du destructeur est impose.Cettemthodedoittreprotected,elleneretourneaucunevaleur,senommeobligatoirementfinalize, neprendaucunparamtreetelleestsusceptiblededclencheruneexceptiondetypeThrowable.Dufaitdecette signatureimpose,ilnepeutyavoirquunseuldestructeurpouruneclasse,doncpasdesurchargepossiblepour lesdestructeurs.Ladclarationdundestructeurestdonclasuivante: protected void finalize() throws Throwable { } Lecodeprsentdansledestructeurdoitpermettrelalibrationdesressourcesutilisesparlaclasse.Onpeutpar exempleytrouverducodefermantunfichierouvertparlaclasseoulafermetureduneconnexionversunserveurde base de donnes. Nous verrons en dtail dans le paragraphe Destruction dune instance les circonstances dans lesquellesestappelledestructeur.

f.Champsetmthodesstatiques
Lesmembresstatiquessontdeschampsoumthodesquisontaccessiblesparlaclasseellemmeoupartoutesles instancesdelaclasse.Onparlegalementdanscertainslangagesdemembrespartags.Ilssonttrsutileslorsque vousavezgrerdansuneclassedesinformationsquinesontpasspcifiquesuneinstancedelaclassemaisla classe ellemme. Par opposition aux membres dinstance pour lesquels il existe un exemplaire par instance de la classe,lesmembresstatiquesexistentenunexemplaireunique.Lamodificationdelavaleurdunmembredinstance nemodifielavaleurquepourcetteinstancedeclassealorsquelamodificationdelavaleurdunmembrestatique

- 6-

ENI Editions - All rigths reserved

modifie la valeur pour toutes les instances de la classe. Les membres statiques sont assimilables des variables globales dans une application. Ils sont utilisables dans le code en y faisant rfrence par le nom de la classe ou grceuneinstancedelaclasse.Cettedeuximesolutionnestpasconseillecarellenemetpasvidencelefait quelontravailleavecunmembrestatique. Les mthodes statiques suivent les mmes rgles et peuvent servir la cration de bibliothques de fonctions. LexempleclassiqueestlaclasseMathdanslaquelledenombreusesfonctionsstatiquessontdfinies.Lesmthodes statiques possdent cependant une limitation car elles ne peuvent utiliser que des variables locales ou dautres membresstatiquesdelaclasse.Ellesnedoiventjamaisutiliserdesmembresdinstanceduneclassecarilsepeut quelamthodesoitutilisesansquilexisteuneinstancedelaclasse.Lecompilateurdtecteracettesituationen indiquant :non-static variable cannot be referenced from a static context. Lesmembresstatiquesdoiventtredclarsaveclemotclstatic.Vouspouvezgalement,commepournimporte quel autre membre dune classe, spcifier une visibilit. Par contre une variable locale une fonction ne peut pas trestatique. Pour illustrer lutilisation des membres statiques nous allons ajouter la classe Personne un champ numro. La valeurdecechampserarenseigneautomatiquementlacrationdechaqueinstancedelaclasseetseraunique pourchaqueinstance.Lesconstructeursdenotreclassesonttoutfaitadaptspourralisercetravail.Parcontre, il nous faut mmoriser combien dinstances ont t cres pour pouvoir affecter un numro unique chaque instance.Unevariablestatiqueprivevasechargerdecetteopration.Voicicidessouslecodecorrespondant. public class Personne { private String nom; private String prenom; private GregorianCalendar date_nais; // champ priv reprsentant le numro de la Personne private int numero; // champ statique priv reprsentant le compteur de Personnes private static int nbInstances; public String getNom() { return nom; } public void setNom(String n) { nom = n.toUpperCase(); } public String getPrenom() { return prenom; } public void setPrenom(String p) { prenom = p.toLowerCase(); } // mthode dinstance permettant dobtenir le numro dune Personne public int getNumero() { return numero; } // methode statique permettant dobtenir le nombre dinstances cres public static int getNbInstances() { return nbInstances; } public Personne() { nom=""; prenom=""; date_nais=null; // cration dune nouvelle Personne donc incrmentation du compteur nbInstances++; // affectation la nouvelle Personne de son numro numero=nbInstances; }
ENI Editions - All rigths reserved - 7-

g.Lesannotations
Lesannotationssontutilisespourajouterunlmentdesinformationssupplmentaires.Cesinformationsnont aucun effet sur le code mais peuvent tre utilises par le compilateur, la machine virtuelle qui se chargera de lexcution de lapplicationoucertainsoutilsdedveloppement.Ellespeuventsappliqueruneclasse,unchamp, une mthode. Elle doit tre spcifie avant llment auquel elle se rapporte. Une annotation est prcde du symbole@etsuiviedunomdelannotation.Lecompilateurreconnattroistypesdannotationsquivontpermettrela modificationdesoncomportementaumomentdelacompilationducode. @Deprecatedestutilispourindiquerquunemthodenedoitplustreutilise.Cestparexemplelecaslorsquevous avez dcid de faire voluer une mthode et que vous souhaitez que la version prcdente ne soit plus utilise. Cetteannotationnechangepaslersultatdelacompilationmaisajoutedesinformationssupplmentairesaucode compil.Siuneautreclasseessaiedutilisercettemthodeunavertissementestdclenchlorsdelacompilationdu codedecetteclasse.SinousajoutonscetteannotationlamthodeaffichagedelaclassePersonnelecodequi utiliselaclassePersonnenedoitplusappelercettemthodesouspeinedavoirunavertissementaumomentdela compilation. public class Personne { private String nom; private String prenom; private GregorianCalendar date_nais; private int numro; private static int nbInstances; ... @Deprecated public void affichage() { System.out.println("nom : " + nom); System.out.println("prnom : " + prenom); System.out.println("ge : " + calculAge()); } ... } La compilation dune classe contenant un appel la mthode affiche de la classe Personne dclenche un avertissementsurlalignecontenantlappelcettemthode. javac -Xlint:deprecation Principale.java Principale.java:16: warning: [deprecation] affichage() in Personne has been deprecated p.affichage(); ^ 1 warning

Pour avoir un message dtaill sur les avertissements il faut utiliser loption -Xlint:deprecation lors de lappelducompilateur.

@Overrideestutilispourindiquerquunemthodesesubstitueunemthodehrite.Cetteannotationnestpas obligatoiremaiselleobligelecompilateurvrifierquelasubstitutionestcorrectementralise(signatureidentique desmthodesdanslaclassedebaseetdanslaclasseactuelle).Sicenestpaslecas,uneerreurdecompilationest dclenche. Lexemple suivant substitue la mthodecalculAge dans une classe hritant de la classePersonne (la miseen uvredelhritageestvueendtailunpeuplusloindanscechapitre). public class Client extends Personne { @Override public long calculAge() { ... ...

- 8-

ENI Editions - All rigths reserved

} } Cette classe est compile sans problme, car la mthode calculAge possde bien la mme signature que dans la classePersonne.Parcontre,sinousessayonsdecompilerlecodesuivant: public class Client extends Personne { @Override public long calculAge(int unite) { ... ... } } Nousobtenonslarponsesuivanteducompilateur. Client.java:6: method does not override or implement a method from a supertype @Override ^ 1 error Ilaeffectivementraison(ilfautbienavouerquecestpratiquementtoujourslecas !)nousluiavonsannoncnotre intentiondesubstituerlamthodecalculAgeet,enfait,nousavonseffectuunesurcharge,carilnexistepasdans laclassePersonnedemthodeaveccettesignature.Sinousenlevonslemotcl@Override,lecodesecompilemaisil sagitdanscecasdunesurcharge. @SuppressWarnings(",")indique au compilateur de ne pas gnrer certaines catgories davertissements. Si par exemplevousvoulezdiscrtementutiliserdansunefonctionunemthodemarquecomme@Deprecatedvousdevez utiliserlannotationsuivantedevantlafonctionosetrouvelappeldecettemthode. @SuppressWarnings("deprecation") public static void main(String[] args) { Personne p; p=new Personne(); p.affichage(); } Ce code se compile correctement sans aucun avertissement, jusquau jour o la mthode concerne aura disparu compltementdelaclassecorrespondante.Carilfautavoirlespritquelebutdelannotation@Deprecatedestde dconseillerlutilisationdunemthode,aveccertainementlintentiondelafairedisparatredansuneversionfuture delaclasse.

2.Utilisationduneclasse
Lutilisationduneclassedansuneapplicationpassepartroistapes:
q

ladclarationdunevariablepermettantlaccslobjet lacrationdelobjet linitialisationduneinstance.

a.Crationduneinstance
Les variables objet sont des variables de type rfrence. Elles diffrent des variables classiques par le fait que la variable ne contient pas directement les donnes mais une rfrence sur lemplacement dans la mmoire o se trouvent les informations. Comme pour toutes les variables elles doivent tre dclares avant leur utilisation. La dclarationsefaitdemanireidentiquecelledunevariableclassique(intouautre). Personne p;

ENI Editions - All rigths reserved

- 9-

Aprs cette tape la variable existe mais ne rfrence pas demplacement valide. Elle contient la valeur null. La deuxime tape consiste rellement crer linstance de la classe. Le mot clnew est utilis cet effet. Il attend commeparamtrelenomdelaclassedontilestchargdecreruneinstance.Loprateur newfaitunedemande pour obtenir la mmoire ncessaire au stockage de linstance de la classe, puis initialise la variable avec cette adressemmoire.Leconstructeurdelaclasseestensuiteappelpourinitialiserlanouvelleinstancecre. p=new Personne(); Lesdeuxoprationspeuventtrecombinesenuneseuleligne. Personne p=new Personne(); Leconstructeurpardfautestappeldanscecas.Pourutiliserunautreconstructeurvousdevezspcifieruneliste de paramtres et en fonction du nombre et du type des paramtres loprateur new appelle le constructeur correspondant. Personne p = new Personne("Dupont","albert",new GregorianCalendar(1956,12,13));

b.Initialisationduneinstance
Plusieurs possibilits sont disponibles pour initialiser les champs dune instance de classe. La premire consiste initialiserlesvariablesconstituantleschampsdelaclasseaumomentdeleursdclarations. public class Personne { private String nom="nouveauNom"; private String prenom="nouveauPrenom"; private GregorianCalendar date_nais=new GregorianCalendar(1900,01,01); ... ... } Cettesolution,bienquetrssimple,estrelativementlimitepuisquilnestpaspossibledutiliserdesstructuresde contrletellesquunebouclelextrieurdunblocdecode.Lasolutionquinousvientimmdiatementlespritest deplacerlecodedinitialisationlintrieurdunconstructeur.Cesteffectivementunetrsbonneideetcestmme lobjectifprincipalduconstructeurquedinitialiserlesvariablesdinstance.Parcontre,unproblmeseposeavecles champs statiques, car pour eux il nest bien sr pas ncessaire davoir une instance de classe pour pouvoir les utiliser. Donc si nous plaons le code charg de les initialiser dans un constructeur, rien ne nous garantit que ce constructeurauratappelaumoinsunefoisavantlutilisationdeschampsstatiques. Pour pallier ce problme, Java propose les blocs dinitialisation statiques. Ce sont simplement des blocs de code prcdsdumotclstaticetdlimitsparlescaractres{et}.Ilspeuventapparatrenimporteodanslecode de la classe et ils sont excuts au chargement de la classe par la machine virtuelle dans lordre dans lequel ils apparaissentdanslecode.Nouspouvonsparexempleutiliserlecodesuivantpourinitialiserunchampstatiqueavec unevaleuralatoiresuprieureougale1000. public class Personne { private String nom="nouveauNom"; private String prenom="nouveauPrenom"; private GregorianCalendar date_nais=new GregorianCalendar(1900,01,01); private int numro=0; private static int numInstance; static { while(numInstance<1000) { numInstance=(int)(10000*Math.random()); } } ... ... }

- 10 -

ENI Editions - All rigths reserved

Lemmersultatpeuttreobtenuencrantunefonctionprivestatiqueetenlappelantpourinitialiserlavariable. public class Personne { private String nom="nouveauNom"; private String prenom="nouveauPrenom"; private GregorianCalendar date_nais=new GregorianCalendar(1900,01,01); private int numro=0; private static int numInstance=initCompteur(); private static int initCompteur() { int cpt=0; while(cpt<1000) { cpt=(int)(10000*Math.random()); } return cpt; } ... ... } Cettesolutionprsentelavantagedepouvoirutiliserlafonctiondansuneautrepartieducodedelaclasse. Le mme principe peut tre appliqu pour linitialisation des champs dinstance. Le bloc de code charg de linitialisationnedoitpas,danscecas,treprcddumotclstatic.Ceblocdecodeestimplicitementrecopiau dbutdechaqueconstructeurdelaclassependantlacompilation.Linitialisationdunchampdinstanceparunappel defonctionestgalementpossible.Unepetiterestrictiondoitcependanttreappliquesurlafonctionutilisecar ellenedoitpaspouvoirtresubstituedansunesousclasse.Ilfautpourcelaladclareraveclemotclfinal.

c.Destructionduneinstance
Lagestiondelammoireestparfoisunvraicassettedanscertainslangagesdeprogrammation.Ledveloppeur est responsable de la cration des instances de classes mais aussi de leur destruction afin de librer la mmoire. HeureusementJavaprendtotalementsachargecettegestionetnousvitecettetchefastidieuse. Il dtermine de luimme quun objet nest plus utilis dans lapplication et le supprime alors de la mmoire. Ce mcanisme est appel Garbage Collector (Ramassemiettes). Il considre quun objet peut tre supprim lorsque lapplication na plus aucun moyen dy accder. Cette situation se produit, par exemple la sortie dune fonction, lorsquunevariablelocaleestutilisepourrfrencerlobjet.Ellepeutgalementtreprovoqueparlaffectationde lavaleurnullunevariable.Pourquunobjetsoitrellementeffacdelammoire,ilfautquetouslesmoyensdy accderdepuislapplicationaientdisparu.Ilnefautpasoublierquesiunobjeteststockdansunecollectionouun tableau,lacollectionoutableau,conserveunerfrenceverslobjet. RegardonsunpeuplusdansledtaillefonctionnementduGarbageCollector.Ilexisteplusieursalgorithmespour mettreen uvrelemcanismedegestiondelammoire.Cesmcanismessontimplmentsparlesconcepteursde lamachinevirtuelleJava.Nousallonsrapidementregardertitredecuriositquelquesmcanismespossibles. MarkandSweep AveccemcanismeleGarbageCollectortravailleendeuxtapes.Ilcommenceparuneexplorationdelammoire depuislaracinedelapplication,lamthode main,etparcourtainsitouslesobjetsaccessiblesdepuiscetteracine. Chaqueobjetaccessibleestmarqupendantcetteexploration(Mark).Ileffectueensuiteundeuximepassageau cours duquel il supprime tous les objets qui ne sont pas marqus, donc inaccessibles, et retire les marques des objets restant quil a places lors du premier passage. Cette solution rudimentaire prsente quelques inconvnients :
q

Pendantlapremiretapelexcutiondelapplicationestinterrompue. Sadureestproportionnellelaquantitdemmoireutiliseparlapplication. Aprsplusieurspassageslammoirerisquedtrefragmente.

StopandCopy Cette solution dcoupe lespace mmoire disponible pour lapplication en deux parties identiques. Ds que le Garbage Collector entre en action, il effectue, comme pour la solution prcdente, une exploration de la mmoire

ENI Editions - All rigths reserved

- 11 -

depuislaracinedelapplication.Dsquiltrouveunobjetaccessible,illerecopieversladeuximezonemmoireet modifie bien sr les variables pour quelles rfrencent ce nouvel emplacement. la fin de lexploration tous les objetsaccessiblesonttrecopisdansladeuximezonemmoire.Ilestalorspossibledeffacercompltementle contenudelapremirezone.Lemmemcanismepeutalorstrerptultrieurementaveclazonemmoirequi vientdtrelibre.Cettesolutionprsentelavantagedliminerlafragmentationdelammoirepuisquelesobjets sont recopis les uns la suite des autres. Par contre, un inconvnient important rside dans le dplacement frquentdesobjetsayantunelongueduredeviedanslapplication.Unesolutionintermdiaireconsisterpartir lesobjetsenmmoireenfonctiondeleuresprancedevieoudeleurge.Lamoitidelammoiredisponibleest doncparfoisdcoupeentroiszones :
q

Une zone pour les objets ayant une trs longue dure de vie et qui nont pratiquement aucun risque de disparatrependantlefonctionnementdelapplication. Unezonepourlesobjetscrsrcemment. Unezonepourlesobjetslesplusanciens.

Lorsque le Garbage Collector intervient, il traite tout dabord la zone rserve aux objets rcents. Si aprs ce premier passage lapplication dispose de suffisamment de mmoire, le Garbage Collector arrte son traitement noterquependantcepremierpassageilpeuttransfrerdesobjetsdanslazonerserveauxobjetsanciens,sils existent depuis suffisamment longtemps. Si la mmoire disponible nestpassuffisante,ilrefaitletraitementsurla zonerserveauxobjetslesplusanciens. Lefficacitdecettesolutionreposesurunconstatcruel :lesobjetsJavanontpasunegrandeesprancedevie.Ily adoncplusdechancedentrouverliminerparmiceuxquionttcrsleplusrcemment. Parmi ces deux solutions il est difficile de dire laquelle est utilise par une machine virtuelle Java puisque limplmentationduGarbageCollectorestlaisselibreauconcepteurdelamachinevirtuelle. Avantdlimineruneinstancedelammoire,leGarbageCollectorappelleledestructeurdecetteinstance. Le dernier point claircir concernant le Garbage Collector concerne son dclenchement. Cest en fait la machine virtuelleJavaquisurveillelesressourcesmmoiredisponiblesetprovoquelentreenactionduGarbageCollector lorsquecellesciontatteintunseuillimite(environ85%).IlestcependantpossibledeforcerlactivationduGarbage Collector en appelant la mthode gc() de la classe System. Cette utilisation doit tre exceptionnelle, car une utilisationtropfrquenteaffectelesperformancesdelapplication.Ellepeuttreutilisejusteavantquelapplication utiliseunequantitdemmoireimportante,commeparexemple,lacrationduntableauvolumineux. LecodecidessouspermetdemettreenvidencelactionduGarbageCollector. import java.util.GregorianCalendar; public class Personne { private String nom="nouveauNom"; private String prenom="nouveauPrenom"; private GregorianCalendar date_nais=new GregorianCalendar(1900,01,01); private int numero=0; private static int numInstance; public String getNom() { return nom; } public void setNom(String n) { nom = n.toUpperCase(); } public String getPrenom() { return prenom; } public void setPrenom(String p) { prenom = p.toLowerCase(); } @Override protected void finalize() throws Throwable

- 12 -

ENI Editions - All rigths reserved

{ System.out.print("\u2020"); super.finalize(); } public int getNumero() { return numero; } public static int getNbInstances() { return numInstance; } public Personne() { nom=""; prenom=""; date_nais=null; numInstance++; numero=numInstance; } public Personne(String n,String p,GregorianCalendar d) { nom=n; prenom=p; date_nais=d; numInstance++; numero=numInstance; } } /************************************************************************/ import java.util.GregorianCalendar;

public class GestionMemoire { public static void main(String[] args) throws InterruptedException { double total; double reste; double pourcentage; for (int j=0;j<1000;j++) { creationTableau(); total=Runtime.getRuntime().totalMemory(); reste=Runtime.getRuntime().freeMemory(); pourcentage=100-(reste/total)*100; System.out.println("cration du " + j + "ime tableau mmoire pleine : " + pourcentage + "%" ); // une petite pause pour pouvoir lire les messages Thread.sleep(1000); } } public static void creationTableau() { // cration dun tableau de 1000 Personnes dans une variable locale // la fin de cette fonction les lments du tableau ne sont plus // accessibles et peuvent tre supprims de la mmoire Personne[] tablo; tablo=new Personne[1000]; for (int i=0;i<1000;i++) { tablo[i]=new Personne("Dupont","albert",new GregorianCalendar(1956,12,13));

ENI Editions - All rigths reserved

- 13 -

} } }

3.Hritage
Lhritage est une puissante fonctionnalit dun langage orient objet mais peut parfois tre utilise mal propos. Deuxtypesderelationspeuventtreenvisagsentredeuxclasses.Nouspouvonsavoirlarelation est une sorte de et la relation concerneun . La relation dhritage doit tre utilise lorsque la relation est une sorte de peuttreappliqueentredeuxclasses.Prenonsunexempleavectroisclasses :Personne,Client,Commande. Essayonslarelation estunesortede pourchacunedesclasses.
q

Unecommandeestunesortedeclient. Unecommandeestunesortedepersonne. Unclientestunesortedecommande. Unclientestunesortedepersonne. Unepersonneestunesortedeclient. Unepersonneestunesortedecommande.

Parmitoutescestentatives,ilnyenaquuneseulequinoussemblelogique :unclientestunesortedepersonne. Nouspouvonsdoncenvisagerunerelationdhritageentrecesdeuxclasses. Lamiseen uvreettrssimpleauniveauducodepuisquedansladclarationdelaclasseilsuffitjustedespcifierle motclextendssuividunomdelaclassedontonsouhaitehriter.Javanacceptantpaslhritagemultiple,vousne pouvezspcifierquunseulnomdeclassedebase.lintrieurdecettenouvelleclassevouspouvez :


q

Utiliserleschampshritsdelaclassedebase(conditionbiensrqueleurvisibilitlepermette). Ajouterdesnouveauxchamps. Masquer un champ hrit en le dclarant avec le mme nom que celui utilis dans la classe de base. Cette techniquedoittreutiliseavecmodration. Utiliserunemthodehritesousrservequesavisibilitlepermette. Substituerunemthodehriteenladclarantlidentique(mmesignature). Surchargerunemthodehriteenlacrantavecunesignaturediffrente. Ajouterunenouvellemthode. Ajouterunouplusieursconstructeurs.

VoiciparexemplelacrationdelaclasseClientquihritedelaclassePersonneetlaquelleestajoutlechamptype etlesaccesseurscorrespondants. public class Client extends Personne { // dtermination du type de client // P -> particulier // E -> entreprise // A -> administration private char type; public char getType() {
- 14 ENI Editions - All rigths reserved

return type; } public void setType(char t) { type = t; } } La classe peut ensuite tre utilise et propose toutes les fonctionnalits dfinies dans la classe Client plus celles hritesdelaclassePersonne. Client c; c=new Client(); c.setNom("ENI"); c.setPrenom(""); c.setDate_nais(new GregorianCalendar(1981,05,15)); c.setType(E); c.affichage();

a.thisetsuper
Il est lgitime de vouloir ensuite modifier le fonctionnement de certaines mthodes hrites pour les adapter la classe Client. Par exemple la mthode affichage peut tre substitue pour tenir compte du nouveau champ disponibledanslaclasse. public void affichage() { System.out.println("nom : " + getNom()); System.out.println("prenom : " + getPrenom()); System.out.println("age : " + calculAge()); switch (type) { case P: System.out.println("type de client : Particulier"); break; case E: System.out.println("type de client : Entreprise"); break; case A: System.out.println("type de client : Administration"); break; default: System.out.println("type de client : Inconnu"); break; } } Ce code fonctionne trs bien mais ne respecte pas un des principes de la programmation objet qui veut que lon rutiliseaumaximumcequiexistedj.Dansnotrecasnousavonsdjuneportiondecodechargedelaffichage dunom,duprnom,etdelgedunepersonne.Pourquoinepaslarutiliserdanslamthodeaffichagedelaclasse Clientpuisquelonenhrite ? Notremthodedevientdonc: public void affichage() { affichage(); switch (type) { case P: System.out.println("type de client : Particulier"); break; case E: System.out.println("type de client : Entreprise"); break; case A: System.out.println("type de client : Administration"); break;

ENI Editions - All rigths reserved

- 15 -

default: System.out.println("type de client : Inconnu"); break; } } Essayonsdelutiliser : Client c; c=new Client(); c.setNom("ENI"); c.setPrenom(""); c.setDate_nais(new GregorianCalendar(1981,05,15)); c.setType(E); c.affichage(); Hlaslersultatnestpaslahauteurdenosesprances !

Quesestilpasslorsdelexcution ? Lorsdelappeldelamthodeaffichagelapremirelignedecodeaconsistappelerlamthodeaffichagedela classedebase.EnfaitlamachinevirtuelleJavarecherchelapremiremthodeaffichagequelletrouve.Pourcela, ellecommencelarecherchedanslaclassepartirdelaquelleestcrlobjet,dansnotrecaslaclasseClient.Elle appelle donc ainsi en boucle la mthode affichage de la classe Client do lerreur de dbordement de pile que nousobtenons.Pourvitercegenredeproblme,nousdevonsluiprciserquelamthodeaffichageappelerse trouvedanslaclassedebase.Pourcelanousdevonsutiliserlemotclsuperpourqualifierlamthodeaffichage appele. public void affichage() { super.affichage(); switch (type) { case P: System.out.println("type de client : Particulier"); break; case E: System.out.println("type de client : Entreprise"); break; case A: System.out.println("type de client : Administration"); break; default: System.out.println("type de client : Inconnu"); break; } } Aprscettemodificationtoutrentredanslordreetnotrecodeaffiche:

- 16 -

ENI Editions - All rigths reserved

Lemmemotclpeuttreutilispourappelerleconstructeurdelaclassedebase. Lappelauconstructeurdelaclassedebasedoittrelapremirelignedunconstructeur. NouspouvonsdonccrerunconstructeurpourlaclasseClientquirutiliseleconstructeurdelaclassePersonne. Aprs la cration dun constructeur surcharg, le constructeur par dfaut gnr automatiquement par le compilateur nest plus disponible. Cest donc une bonne habitude de toujours crer un constructeur par dfaut. Celuici devra simplement faire un appel au constructeur par dfaut de la classe de base. Nous devons doncajouterlecodesuivantlaclasseClient.

public Client() { // appel au constructeur par dfaut de la super classe super(); } Public Client(String nom,String prenom,GregorianCalendar date_nais,char type) { // appel au constructeur surcharg de la super classe super(nom,prenom,date_nais); // initialisation du type de client type=type; } Vrifionsquelenouveauconstructeurfonctionne. c=new Client("ENI","",new GregorianCalendar(1981,05,15),E); c.affichage(); Nousaffiche: nom : ENI prenom : age : 27 type de client : Inconnu Les informations ont bien t prises en compte sauf le type de client qui na pas t initialis. Regardons de plus prslecodeduconstructeur.Nousdcouvronsquunparamtreduconstructeurportelemmenomquunchampde la classe. Lorsque nous crivons la ligne type=type, le compilateur considre que nous souhaitons affecter au paramtretypelavaleurcontenuedansleparamtretype.Riendillgal,maiscenestabsolumentpascequenous souhaitonsfaire.Nousdevonsindiquerquelaffectationdoitsefaireauchampdelaclasse.Pourcelanousdevons prfixersonnomaveclemotclthis. Leconstructeurdevientdonc : public Client(String nom,String prenom,GregorianCalendar date_nais,char type) {

ENI Editions - All rigths reserved

- 17 -

// appel au constructeur surcharg de la super classe super(nom,prenom,date_nais); this.type=type; } Notrecodedetestaffichealorslesbonnesinformations : nom : ENI prenom : age : 27 type de client : Entreprise

b.Classesabstraites
Les classes abstraites sont des classes qui peuvent uniquement tre utilises comme classe de base dans une relationdhritage.Ilestimpossibledecreruneinstanceduneclasseabstraite.Ellesserventessentiellementde modle pour la cration de classe devant toutes avoir un minimum de caractristiques identiques. Elles peuvent contenir des champs, des proprits et des mthodes comme une classe ordinaire. Pour quune classe soit une classeabstraitevousdevezutiliserlemotclabstractlorsdesadclaration. Cette technique facilite lvolution de lapplication car si une nouvelle fonctionnalit doit tre disponible dans les classesdrives,ilsuffitdajoutercettefonctionnalitdanslaclassedebase.Ilestgalementpossibledenepas fournirdimplmentationpourcertainesmthodesduneclasseabstraiteetainsilaisserlutilisateurdelaclassele soindecrerlimplmentationdanslaclassedrive.Cesmthodesdoiventgalementtredclaresaveclemot cl abstract. Il ny a dans ce cas pas de bloc de code correspondant cette mthode et sa dclaration doit se termineravecunpointvirgule. Uneclasseabstraitenapasobligatoirementdemthodesabstraites,parcontreuneclassecontenantunemthode abstraite doit obligatoirement tre elle aussi abstraite. La classe qui hritera de la classe abstraite devra implmenter les mthodes dclares abstraites dans sa classe de base ou tre elle aussi abstraite. Si elle implmente une mthode abstraite, elle ne peut pas rduire la visibilit dclare dans la classe abstraite. Voici ci dessousunexempledeclasseabstraite: public abstract class EtreVivant { private double taille; private double poids; public double getTaille() { return taille; } public void setTaille(double taille) { this.taille = taille; } public double getPoids() { return poids; } public void setPoids(double poids) { this.poids = poids; } // cette mthode devra tre implmente dans les classes drives protected abstract void seDeplacer(); }

c.Classesfinales
Lesclassessontdesclassesordinairesquipeuventtreinstanciesmaisnesontpasutilisablescommeclassede base dans une relation dhritage. Elles doivent tre dclares avec le mot cl final. Cest le cas de plusieurs classesdulangageJava,commeparexemplelaclasseStringdontvoiciladclarationextraitedeladocumentation Java.

- 18 -

ENI Editions - All rigths reserved

Une mthode peut galement tre dclare avec le mot cl final pour interdire sa redfinition dans une sous classe.

d.Conversiondetype
Pour bien comprendre les oprations de conversion de type il faut toujours garder prsent lesprit que une fois crenmmoireunobjetnechangerajamaisdetypejusqulafindesavie.Ainsisivouscrezuneinstancedela classePersonne,cetteinstanceresteratoujoursuneinstancedelaclassePersonne.Avecceprambulevousdevez vousposerdesquestionssurlasignificationrelleduterme"conversion".Enfaitlaconversionnintervientpassur lobjet luimme mais sur la faon de le manipuler. Elle va agir sur le type de la variable utilise pour accder lobjet. Larelationdhritageentreclassesestllmentfondamentalpermettantlutilisationdesconversionsdetype.Nous avonsvuquuneclassepouvaitrcuprerlescaractristiquesduneautreclasseparcetintermdiaire.Cestdire quelle rcupre automatiquement les caractristiques de sa classe de base. Nous pouvons par exemple avoir la hirarchiedeclassesuivante.

LaclasseClientestunevolutiondelaclassePersonneaummetitrequelaclasseFournisseurestunevolution de la classe Personne. Toutes les caractristiques disponibles avec une instance de la classe Personne seront galementdisponiblesavecuneinstancedelaclasseClientouuneinstancedelaclasseFournisseur.Enfaitnotre schmanestpascomplet,ildevraitpluttavoirlaformesuivante :

ENI Editions - All rigths reserved

- 19 -

IlnefautjamaisoublierquuneclassequinapasdeclassedebaseexplicitehriteimplicitementdelaclasseObject. Nouspouvonsdoncdirequenimportequelleinstancedeclasseauraauminimumlescaractristiquesduneinstance delaclasseObject. Maintenantquenousavonstabliunbilan,voyonssousformedunpetitjeucequenouspouvonsfaireetnepas faireaveclesconversions. Enpartantducodesuivant : Object o; Personne p; Client c; Fournisseur f; Vousdevezindiquerparmileslignessuivantesquellessontcellesquiposentunproblme. Pourvousaider,posezvoustoujourslaquestion :estcequecequejepeuxfaireavecunevariabledetypeXest disponibledanslinstancedeclassequejeveuxluifairerfrencer ? f=new Fournisseur(); o=ffonctionnenefonctionnepas p=ffonctionnenefonctionnepas c=ffonctionnenefonctionnepas c=newClient() o=cfonctionnenefonctionnepas p=cfonctionnenefonctionnepas f=cfonctionnenefonctionnepas p=newPersonne() o=pfonctionnenefonctionnepas c=pfonctionnenefonctionnepas f=pfonctionnenefonctionnepas o=newObject()

- 20 -

ENI Editions - All rigths reserved

p=ofonctionnenefonctionnepas f=ofonctionnenefonctionnepas c=ofonctionnenefonctionnepas Voicilasolution: f=newFournisseur() o=ffonctionnenefonctionnepas p=ffonctionnenefonctionnepas c=ffonctionnenefonctionnepas c=newClient() o=cfonctionnenefonctionnepas p=cfonctionnenefonctionnepas f=cfonctionnenefonctionnepas p=newPersonne() o=pfonctionnenefonctionnepas c=pfonctionnenefonctionnepas f=pfonctionnenefonctionnepas o=newObject() p=ofonctionnenefonctionnepas f=ofonctionnenefonctionnepas c=ofonctionnenefonctionnepas Nous pouvons dduire de ce rsultat la rgle suivante : avec une variable du type X nous pouvons bien sr rfrenceruneinstancedeclassedetypeXmaisaussiuneinstancedenimportequellesousclassedelaclasseX. AinsiunevariabledetypeObjectpeuttreutilisepourrfrenceruneinstancedenimportequelleclasse. Pourpoursuivrenosexprimentationssurlesconversionsvoiciundeuximetest. ... o=newObject() p=newPersonne() c=newClient() f=newFournisseur() essai(o)fonctionnenefonctionnepas essai(p)fonctionnenefonctionnepas essai(f)fonctionnenefonctionnepas essai(c)fonctionnenefonctionnepas ... publicvoidessai(Objectobj) { Objecto Personnep Clientc Fournisseurf o=objfonctionnenefonctionnepas p=objfonctionnenefonctionnepas c=objfonctionnenefonctionnepas f=objfonctionnenefonctionnepas } Voicilasolutiondecedeuximeexercice : ... o=newObject() p=newPersonne() c=newClient() f=newFournisseur() essai(o)fonctionnenefonctionnepas essai(p)fonctionnenefonctionnepas essai(f)fonctionnenefonctionnepas essai(c)fonctionnenefonctionnepas ...
ENI Editions - All rigths reserved - 21 -

publicvoidessai(Objectobj) { Objecto Personnep Clientc Fournisseurf o=objfonctionnenefonctionnepas p=objfonctionnenefonctionnepas c=objfonctionnenefonctionnepas f=objfonctionnenefonctionnepas } Lesrglessuivrepourrsoudreceproblmesontlesmmesquepourlexerciceprcdent.Lorsdelappeldela fonction essai le passage du paramtre est quivalent une affectation une variable de type Object. Nous pouvonsdoncappelercettefonctionenluifournissantuneinstancedenimportequelleclasse. lintrieurdelafonctionessaileproblmeestinvers.Leparamtreobjrfrenceuneinstancedeclassemaisle compilateur ne peut pas savoir de quelle classe il sagit. Cest pour cette raison quil naccepte que laffectation o=obj;quiestsansrisquepuisquelesdeuxvariablessontdemmetype.Ilesttoutefoispossibledecontournerce problmeeneffectuantuneoprationdetranstypage.Cetteoprationestralisesimplementenfaisantprcder lavariabledunomdelaclasseverslaquellenousvoulonsraliserletranstypage.Lenomdelaclassedoittreplac entrelescaractres(et). publicstaticvoidessai(Objectobj) { Objecto Personnep Clientc Fournisseurf o=obj p=(Personne)obj c=(Client)obj f=(Fournisseur)obj } Nousnavonsplusderreursaumomentdelacompilation.Parcontreaumomentdelexcutionnousobtenonsune exceptiondetypejava.lang.ClassCastException.Cetteexceptionestdclencheparlamachinevirtuellelorsquelle dcouvrequenousluiavonsmentienessayantdeluifairecroirequelavariableobjrfrenceuneinstancedune certaineclassealorsquilnenestrien.Nousdevonsdonctreplusprudentsavecnosoprationsdetranstypageet vrifier ce que rfrence rellement la variable obj. Loprateur instanceof permet de faire cette vrification. La fonctionessaidoitdoncscriredelafaonsuivante : publicstaticvoidessai(Objectobj) { Objecto Personnep Clientc Fournisseurf o=obj if(objinstanceofPersonne) { p=(Personne)obj } if(objinstanceofClient) { c=(Client)obj } if(objinstanceofFournisseur) { f=(Fournisseur)obj } } Cetoprateurdoitpratiquementtoujourstreutilispourvrifierlafaisabilitduneoprationdetranstypage.

e.LaclasseObject
- 22 ENI Editions - All rigths reserved

LaclasseObjectestdirectementouindirectementprsentedanslahirarchiedetouteclasseduneapplication.Les mthodes dfinies dans la classeObjectsontdoncdisponiblespournimportequelleclasse.Linconvnient de ces mthodes est quelles ne font pas grandchose dutile ou leur fonctionnement nest pas adapt aux diffrentes classes de lapplication. Elles ont donc souvent besoin dtre substitues dans les classes de lapplication pour pouvoir tre utilises efficacement. Il est donc important de bien connatre leur utilit pour adapter leur fonctionnement.Nousallonsdonctudierendtaillesplusutilisesdentreelles. hashCode Cettemthodepermetdobtenirladressemmoireoeststockeuneinstancedeclasse.Enellemmeellenest pas trs utile, mis part pour quelques exprimentations comme nous le ferons dans le paragraphe suivant, par contreelleestutiliseeninternepardautresmthodesetprincipalementparlamthodeequals. clone Lamthodeclonepeutrevendiquerletitrede"photocopieur"dobjets.Parsonintermdiairenouspouvonsobtenir unecopieconformedunobjetprsentenmmoire.Pourquecettemthodesoitdisponible,ilestindispensableque la classe partir de laquelle lobjet copier a t cr, implmente linterface Cloneable. Cette interface exige la crationdunemthodeclonedanslaclasse.Cettemthodeestsouventtrssimplepuisquilsuffitquelleappellela mthodeclonedelaclasseObject.Cetteversionpardfautsecontentedeffectuerunecopiedelazonemmoire correspondant linstance de classe dupliquer. Si linstance dupliquer contient des rfrences vers dautres objets,cesobjetsneserontpasdupliqusetserontpartagsparloriginaletlacopie.Sicefonctionnementnest pasadaptlapplication,ilfautconcevoirlamthodeclonepourquelleeffectuegalementunecopiedesobjets rfrencs.Pourillustrercemcanisme,nousallonstravailleraveclaclasse Clientlaquellenousallonsassocier uneclasseCommandeellemmeassocieuneclasseLignesDeCommandes.

Sinouseffectuonsunecopiedunecommandenousconservonslarfrenceversleclientparcontreleslignesde commandedoiventtredupliqus.NousdevonsdoncconcevoirlamthodeclonedelaclasseCommandepourquelle dupliquegalementlinstancedelaclasseLignesDeCommanderfrence.Voicicidessousunextraitducodedeces classes. publicclassCommandeimplementsCloneable { ClientleClient LignesDeCommandelesLignes publicCommande() { super() lesLignes=newLignesDeCommande() } publicObjectclone()throwsCloneNotSupportedException { Commandecmd //crationdunecopiedelacommande cmd=(Commande)super.clone() //duplicationdeslignesdelacommande cmd.lesLignes=(LignesDeCommande)lesLignes.clone() returncmd } publicClientgetLeClient() { returnleClient } publicvoidsetLeClient(ClientleClient) { this.leClient=leClient } publicLignesDeCommandegetLesLignes() { returnlesLignes } publicvoidsetLesLignes(LignesDeCommandelesLignes)

ENI Editions - All rigths reserved

- 23 -

{ this.lesLignes=lesLignes } } /***********************************************************************/ publicclassLignesDeCommandeimplementsCloneable { publicObjectclone()throwsCloneNotSupportedException { returnsuper.clone() } } Nouspouvonsmaintenantcrerdesinstancesdenosclassesetvrifierlebonfonctionnement. Clientc c=newClient("ENI","",newGregorianCalendar(1981,05,15),E) Commandecmd1,cmd2 //crationetinitialisationdunecommande cmd1=newCommande() cmd1.setLeClient(c) System.out.println("hashCodedelacommande:"+cmd1.hashCode()) System.out.println("hashCodeduClient:" +cmd1.getLeClient().hashCode()) System.out.println("hashCodedeslignes:" +cmd1.getLesLignes().hashCode()) cmd2=(Commande)cmd1.clone() System.out.println("hashCodedelacopie:"+cmd2.hashCode()) System.out.println("hashCodeduClientdelacopie:" +cmd2.getLeClient().hashCode()) System.out.println("hashCodedeslignesdelacopie:" +cmd2.getLesLignes().hashCode()) Nousobtenonslersultatsuivantlexcutiondececode : hashCodedelacommande:6413875 hashCodeduClient:21174459 hashCodedeslignes:827574 hashCodedelacopie:17510567 hashCodeduClientdelacopie:21174459 hashCodedeslignesdelacopie:27744459 Nousavonsbiendeuxcommandesdistinctesquirfrencentlemmeclient. equals Lamthodeequalsestutilisepourcomparerdeuxinstancesdeclasse.Lecodesuivantpermetdevrifierlgalit dedeuxclients. Clientc1,c2 c1=newClient("ENI","",newGregorianCalendar(1981,05,15),E) c2=newClient("ENI","",newGregorianCalendar(1981,05,15),E) if(c1.equals(c2)) { System.out.println("lesdeuxclientssontidentiques") } else { System.out.println("lesdeuxclientssontdiffrents") } Malgrlesapparences,lexcutiondececodenousaffichelersultatsuivant : les deux clients sont diffrents Limplmentation par dfaut de cette mthode effectue une comparaison des rfrences pour dterminer sil y a galitdesdeuxobjets.Cesontenfaitles hashCodedesdeuxobjetsquisontcompars.Sinousvoulonsavoirun critredecomparaisondiffrent,nousdevonssubstituerlamthodeequals dans la classeClientenutilisantnos

- 24 -

ENI Editions - All rigths reserved

proprescritresdecomparaison. publicbooleanequals(Objectobj) { Clientc //vrificationsiobjestnullourfrenceuneinstance //duneautreclasse if(obj==null||obj.getClass()!=this.getClass()) { returnfalse } else { c=(Client)obj //vrificationdescritresdgalitsur //lenom //leprnom //ladatedenaissance //letypedeclient if(c.getNom().equals(getNom())& c.getPrenom().equals(getPrenom())& c.getDate_nais().equals(getDate_nais())& c.getType()==getType()) { returntrue } else { returnfalse } } } Pourconserverunecohrenceentrelamthode equalsetlamthodehashCode,ilestimportantderedfinircette dernirepourquellecalculelehashcodepartirdelavaleurdeschampsutilissdanslescritresdecomparaison. Lavaleurrenvoyeparcettefonctionapeudimportance,seulecompterellementlagarantiedobtenirtoujoursle mme rsultat pour toute instance de classe ayant les mmes valeurs de champs. Voici un exemple possible dimplmentationdelamthodehashCode: publicinthashCode() { returnthis.getNom().hashCode()+ this.getPrenom().hashCode()+ this.getDate_nais().hashCode()+ (int)this.getType() } getClass CettemthodefournituneinstancedelaclasseClasscontenantlescaractristiquesdelaclassepartirdelaquelle lobjetatcr.Nouspouvonsparexempleobtenirlenomdelaclasse,lesmthodesdisponibles,leschamps,etc. Parmesuredescurit,cettemthodenepeutpastresubstitue. Voiciunefonctionaffichantquelquesinformationssurlaclassedelobjetquiluiestpassenparamtre. publicstaticvoidinfoClasse(Objecto) { Classc c=o.getClass() System.out.println("nomdelaclasse:"+c.getName()) System.out.println("elleestdanslepackage:"+ c.getPackage().getName()) System.out.println("ellehritedelaclasse:"+ c.getSuperclass().getName()) System.out.println("ellepossdeleschamps:") for(inti=0i<c.getFields().lengthi++) {

ENI Editions - All rigths reserved

- 25 -

System.out.print("\t"+c.getFields()[i].getName()) System.out.println("detype:"+ c.getFields()[i].getType().getName()) } System.out.println("ellepossdelesmthodes:") for(inti=0i<c.getMethods().lengthi++) { System.out.print("\t"+c.getMethods()[i].getName()) System.out.print("quiattendcommeparamtre(") for(int j=0j<c.getMethods()[i].getParameterTypes().lengthj++) { System.out.print(c.getMethods()[i].getParameterTypes()[j]+"") } System.out.println(")") } } toString linversedelaprcdente,cettemthodedevraitpratiquementtoujourstresurcharge.Ellepermetdobtenirla reprsentation dun objet sous forme dune chane de caractres. Par dfaut limplmentation de cette mthode danslaclasseObjectretournelenomdelaclassesuividuhashCodedelinstance.Unereprsentationplusparlante est bien sr conseille. Elle doit tre construite partir des valeurs contenues dans les champs de lobjet. Une versionpossibledelamthodetoStringpourlaclassePersonnepourraitparexempletrelasuivante. publicStringtoString() { Stringchaine chaine="nom:"+getNom()+"\r\n" chaine=chaine+"prnom:"+getPrenom() returnchaine } Lappeldelamthode toStringestparfoisimplicitelorsquelonpasseunobjetcommeparamtreunefonction. Lesdeuxsyntaxessuivantessontdoncquivalentes. Clientc c=newClient("ENI","",newGregorianCalendar(1981,05,15),E) System.out.println(c) ou Clientc c=newClient("ENI","",newGregorianCalendar(1981,05,15),E) System.out.println(c.toString())

4.Interfaces
Nous avons vu que lonpouvaitobligeruneclasseimplmenterunemthodeendclarantcelleci avec le mot cl abstract. Si plusieurs classes doivent implmenter la mme mthode, il est plus pratique dutiliser les interfaces. Comme les classes, les interfaces permettent de dfinir un ensemble de constantes et mthodes. Cependant les interfacesnecontiennentaucuncode.Limplmentationdoitsefaireauniveaudelaclassequiimplmentelinterface. Linterfaceconstitueuncontratquelaclassesigne.Endclarantquelaclasseimplmenteuneinterface,ellesengage fournirtoutcequiestdfinidanslinterface.Ilfauttreprudentsivousutilisezlesinterfacesetnejamaismodifier uneinterfacequiestdjutilisesinonvouscourezlerisquededevoirreprendrelecodedetouteslesclassesqui implmententcetteinterface.

a.Crationduneinterface
Pourpouvoirutiliseruneinterface,ilfautladfiniraupralable.Ladclarationestsemblableladclarationdune classemaisonutiliselemotclinterfaceenlieuetplacedumotclclass. Vous pouvez ventuellement utiliser le mot cl extends pour introduire une relation dhritage dans linterface. Contrairementauxclasseslesinterfacesautorisentlhritagemultiple.Danscecas,lesnomsdesinterfaceshrites sontsparspardesvirgulesaprslemotclextends.Ilfauttreraisonnableaveccettepossibilitcarlesclasses

- 26 -

ENI Editions - All rigths reserved

quiimplmenterontcetteinterfacedevrontfournirtouteslesmthodesdfiniesdanslahirarchiedelinterface. Les seules instructions qui peuvent apparatre dans une interface sont des dclarations de constantes et des dclarations de fonctions. Par contre, il ne doit y avoir aucun code dans les fonctions donc pas de bloc de code dlimit par les caractres { et }. Crons donc notre premire interface. Celleci va imposer la prsence dune fonctioncompare attendant comme paramtre un objet. Lors de la dfinition duneinterface,ilestrecommandde fournir,sousformedecommentaires,unedescriptiondutravailquedevraaccomplirchaquemthodeetlesrsultats quelledevrafournir. //cetteinterfacedevratreimplmenteparlesclasses //pourlesquellesunclassementdesinstancesestenvisag publicinterfaceClassable { //cettemthodepourratreappelepourcomparerlinstancecourante //aveccellereueenparamtre //lamthoderetourneunentierdontlavaleurdpenddesrglessuivantes //1silinstancecouranteestsuprieurecellereueenparamtre //0silesdeuxinstancessontgales //1silinstancecouranteestinfrieurecellereueenparamtre //99silacomparaisonestimpossible intcompare(Objecto) publicstaticfinalintINFERIEUR=1 publicstaticfinalintEGAL=0 publicstaticfinalintSUPERIEUR=1 publicstaticfinalintERREUR=99 }

b.Utilisationduneinterface
Maisquelscritresallonsnousutiliserpourdirequunobjetestsuprieurunautre ? Dansladescriptiondenotreinterfacecenestpasnotresouci!Nouslaissonslesoinlutilisateurquivadfinirune classe implmentant linterface de dfinir quels sont les critres de comparaison. Par exemple dans notre classe Personne,nouspourrionsimplmenterlinterfaceClassabledelamaniresuivanteenchoisissantdecomparerdeux instancesdelaclassePersonnesurlenom : publicclassPersonne implementsClassable { publicintcompare(Objecto) { Personnep if(oinstanceofPersonne) { p=(Personne)o } else { returnClassable.ERREUR } if(getNom().compareTo(p.getNom())<0) { returnClassable.INFERIEUR } if(getNom().compareTo(p.getNom())>0) { returnClassable.SUPERIEUR } returnClassable.EGAL } ... ... }

ENI Editions - All rigths reserved

- 27 -

Deuxmodificationssontvisiblesdanslaclasse:
q

LefaitquelleimplmentelinterfaceClassable. Limplmentationrelledelafonctioncompare.

Danscettefonctionlacomparaisonseferasurlenomdesclients.Trsbien,maiscelasertquoi? Ilarrivefrquemmentquelonaitbesoindetrierdeslmentsdansuneapplication.Deuxsolutions:
q

Crerunefonctiondetrispcifiquepourchaquetypedlmentquelonveuttrier. Creruneroutinedetrignriqueetfaireensortequeleslmentsquelonutilisesoienttriablesparcette routine.

Lesinterfacesvontnousaidermettreen uvrecettedeuximesolution.Pourpouvoirtrierdeslments,etquelle quesoitlamthodeutilisepourletri,nousauronsbesoindecomparerdeuxlments.Pourtrecertainquenotre routinedetrifonctionnerasansproblme,ilfautsassurerqueleslmentsquelledevratrieraurontlapossibilit dtre compars les uns aux autres. Nous ne pouvons garantir cela que si tous nos lments implmentent linterfaceClassable.Nousallonsdonclexigerdansladclarationdenotreroutinedetri. publicstaticvoidtri(Classable[]tablo) { } Dfinieainsi,notrefonctionseracapabledetriertoutessortesdetableauxpourvuqueleurslmentsimplmentent linterfaceComparable.Elleretourneraletableautri.Nouspouvonsdonccrirelecodesuivantetutiliserlamthode comparesansrisque. publicstaticClassable[]tri(Classable[]tablo) { inti,j Classablec for(i=0i<tablo.lengthi++) { for(j=i+1j<tablo.lengthj++) { if(tablo[j].compare(tablo[i])==Classable.INFERIEUR) { c=tablo[j] tablo[j]=tablo[i] tablo[i]=c } elseif(tablo[j].compare(tablo[i])==Classable.ERREUR) { returnnull } } } returntablo } Puispourtesternotreprocdure,cronsquelquesclientsetessayonsdelestrier,puisdafficherleursnoms. Personne[]tab tab=newPersonne[5] tab[0]=newPersonne("toto2","prenom2",new GregorianCalendar(1922,2,15)) tab[1]=newPersonne("toto1","prenom1",new GregorianCalendar(1911,1,15)) tab[2]=newPersonne("toto5","prenom5",new GregorianCalendar(1955,05,15)) tab[3]=newPersonne("toto3","prenom3",new GregorianCalendar(1933,03,15)) tab[4]=newPersonne("toto4","prenom4",new GregorianCalendar(1944,04,15)) Personne[]tabTrie

- 28 -

ENI Editions - All rigths reserved

tabTrie=(Personne[])tri(tab) for(inti=0i<tabTrie.lengthi++) { System.out.println(tabTrie[i]) } Nousobtenonslersultatsuivant: Mrtoto1prenom1nle01/01/000100:00:00codeClient:1 Mrtoto2prenom2nle01/01/000100:00:00codeClient:2 Mrtoto3prenom3nle01/01/000100:00:00codeClient:3 Mrtoto4prenom4nle01/01/000100:00:00codeClient:4 Mrtoto5prenom5nle01/01/000100:00:00codeClient:5 Nousavonsbienlalistedenosclientstrieparordrealphabtiquesurlenom. EssayonsdutilisernotreprocduredetriavecuntableaudobjetsquinimplmententpaslinterfaceClassable. Commande[]tabCmd tabCmd=newCommande[5] tabCmd[0]=newCommande() tabCmd[1]=newCommande() tabCmd[2]=newCommande() tabCmd[3]=newCommande() tabCmd[4]=newCommande() Commande[]tabCmdTrie tabCmdTrie=(Commande[])tri(tabCmd) for(inti=0i<tabCmdTrie.lengthi++) { System.out.println(tabCmdTrie[i]) } lacompilationleschosessecompliquent.

Cetteerreurintervientaumomentdelappeldelaprocduredetri.Leslmentsdutableauquenousavonspass commeparamtrenimplmententpaslinterfaceClassableetnousnesommespascertainsquilscontiennentune fonction compare. noter que, mme sil existe une fonction compare correcte dans la classe Commande, il faut obligatoirementspcifierquecetteclasseimplmentelinterfaceClassable,pourquelecodepuissefonctionner.

5.Classesimbriques
La majorit des classes que vous utiliserez dans une application seront dfinies dans leur propre fichier source. Cependant Java fournit la possibilit de dclarer une classe lintrieur dune autre classe voire lintrieur dune mthode.Cettetechniquepermetdedfiniruneclasseuniquementdanslecontexteoelleestrellementutile.On dsignegalementlesclassesimbriquesparletermeclassesassistantes.Suivantlemplacementdeleurdclaration elles ont accs, soit aux autres membres de la classe dans laquelle elles sont dclares (y compris les membres privs)soituniquementauxvariableslocalesdesmthodes.

a.Classesimbriquesstatiques
Comme nimporte quel lment dclar dans une classe (champ ou mthode) une classe imbrique peut tre dclare avec le mot clstatic. Elle est dans ce cas soumise aux mmes rgles imposes par ce mot cl que les

ENI Editions - All rigths reserved

- 29 -

autreslmentsduneclasse.
q

Ellenepeututiliserqueleschampsetmthodesstatiquesdesaclassecontainer. Ellepeuttreutilise(instancie)sansquilexisteuneinstancedesaclassecontainer. Elle peut utiliser les membres dinstance de sa classe container uniquement par lintermdiaire dune instancedecelleci.

Voicicidessousunexemplesimpledeclasseimbriquestatique. publicclassExterne { staticclassInterne { publicdoublecalculTTC(doubleprix) { returnprix*taux } } staticdoubletaux=1.196 } Ellepeuttreutilisedefaontoutfaitsemblablenimportequelleautreclasse.Laseulecontraintersidedans lenomutilispouryfairerfrencedanslecodequidoittreprcddunomdelaclassecontainer. Externe.Interneci ci=newExterne.Interne() System.out.println(ci.calculTTC(100))

b.Classesimbriques
Les classes imbriques sont galement connues sous la dsignation de classes internes. Elles sont soumises aux mmesrglesquenimportequellmentdclardansuneclasse.
q

Ellespeuventavoiraccstouslesmembresdelaclassedanslaquelleellessontdclaresycomprisles membresprivs. Ellesnepeuventtreutilisesquesiuneinstancedelaclassecontainerestdisponible.

Ladclarationesttrssimpleettoutfaitsimilairelaprcdentehormislemotclstaticquidisparat. publicclassExterne { classInterne { publicdoublecalculTTC(doubleprix) { returnprix*taux } } doubletaux=1.196 } Par contre, si nous tentons de lutiliser avec le mme code que la version static de la classe, nous rencontrons quelquessoucisaumomentdelacompilation.

- 30 -

ENI Editions - All rigths reserved

Effectivementnousdevonsobligatoirementavoiruneinstancedelaclassecontainerpourquelaclasseinternesoit disponible.Nousdevonsdoncaupralableinstancierlaclassepuisluidemanderdenousfourniruneinstancedela classeinterne.Labonnesyntaxeestdonc : Externee e=newExterne() Externe.Interneci ci=e.newInterne() System.out.println(ci.calculTTC(100))

c.Classesanonymes
Uneclasseanonymeestuneclasseinternepourlaquelleaucunnomnestfourni.Lesclassesanonymessonttout fait adaptes pour raliser une opration ncessitant un objet mais qui ne justifie pas la cration dune classe normale.Cestlecasparexemplesilaclasseesttrssimpleousiellenestutilisequedansuneseulemthode.Ce mcanisme est trs utilis pour la gestion des actions de lutilisateur dans une application en mode graphique. Il permetgalementdepallierlabsencedepointeursdefonctiondanslelangageJava. Pour illustrer lutilisation des classes internes anonymes, nous allons reprendre la fonction de tri de tableau cre prcdemmentetlarendreencoreplusuniverselle.Danssaversionactuelle,elleexigequeleslmentsdutableau implmentent linterface Classable pour quelle puisse les comparer deux deux. Nous modifions lgrement la fonctionpourque,lorsdelappel,onpuisseluifournirenplusdutableautrier,lafonctionquelledevrautiliserpour effectuerlescomparaisons.CommelespointeursdefonctionsnexistentpasdanslelangageJava,leseulmoyende transmettre une fonction une autre fonction est de lui fournir une instance de classe qui contient la fonction transmettre. Par mesure de scurit, nous pouvons exiger que cette instance soit cre partir dune classe implmentantuneinterfacepourgarantirlexistencedelafonction.Voicilecodedecettenouvelleinterface: //cetteinterfacedevratreimplmenteparlesclasses //pourlesquellesunecomparaisondesinstancesestenvisage publicinterfaceComparateur { //cettemthodepourratreappelepourcomparerlesdeuxobjets //reusenparamtre //lamthoderetourneunentierdontlavaleurdpenddesrglessuivantes //1silinstanceo1estsuprieureo2 //0silesdeuxinstancessontgales //1silinstanceo1estinfrieureo2 //99silacomparaisonestimpossible intcompare(Objecto1,Objecto2) publicstaticfinalintINFERIEUR=1 publicstaticfinalintEGAL=0 publicstaticfinalintSUPERIEUR=1 publicstaticfinalintERREUR=99 } Nouspouvonsmaintenantrevoirlgrementnotrefonctiondetrienprenantencomptenosamliorations. publicstaticObject[]tri(Object[]tablo,Comparateurtrieur)

ENI Editions - All rigths reserved

- 31 -

{ inti,j Objectc Object[]tabloTri tabloTri=Arrays.copyOf(tablo,tablo.length) for(i=0i<tabloTri.lengthi++) { for(j=i+1j<tabloTri.lengthj++) { //utiliselafonctioncomparedelobjetreuenparametrepour //comparerlecontenudedeuxcasesdutableau if (trieur.compare(tabloTri[j],tabloTri[i])==Comparateur.INFERIEUR) { c=tabloTri[j] tabloTri[j]=tabloTri[i] tabloTri[i]=c } elseif (trieur.compare(tabloTri[j],tabloTri[i])==Comparateur.ERREUR) { returnnull } } } returntabloTri } Pourutilisercettenouvellefonctiondetrinousdevonsmaintenantluifournirdeuxparamtres :
q

letableautrier. Uneinstancedeclasseayantimplmentlinterfacecomparateur.

Pourfournircetteinstancedeclassenousavonsplusieurssolutions :
q

creruneinstanceduneclasse"normale"quiimplmentelinterface. Creruneinstanceclasseinternequiimplmentelinterface. Creruneinstanceduneclasseinterneanonymequiimplmentelinterface.

Cest cette dernire solution que nous allons utiliser. La syntaxe de cration dune instance dune classe interne anonymeestaupremierabordassezbizarre. newnomdelaclassedebaseoudelinterfaceimplmente() { //dclarationdeschamps inti floatj //dclarationdesmthodes publicintmethode1(,) { }//accoladedefermeturedublocdecodedelamthode }//accoladedefermeturedublocdecodedelaclasse Commepourcreruneinstancedeclassenormale,nousutilisonsloprateurnewsuividunomdelaclasse.Enfait nousnindiquonspasdirectementlenomdelaclassedontnoussouhaitonsobteniruneinstance,maislenomdela classedebaseoudelinterfaceimplmenteparcetteclasse(laclassenapasdenompuisquelleestanonyme !). Nousfournissonsensuiteunblocdecodedlimitpardesaccoladescorrespondantaucontenudelaclasse,comme pourladfinitionduneclassenormale.noterquesilaclasseanonymeimplmenteuneinterface,ceblocdecode doitobligatoirementfournirtouteslesmthodesexigesparlinterface. Voicilamiseenapplicationdecesprincipespourlappeldenotrefonctiondetriaveccommecritredetrilenomde lapersonne.

- 32 -

ENI Editions - All rigths reserved

Personne[]tab tab=newPersonne[5] tab[0]=newPersonne("toto2","prenom2",new GregorianCalendar(1922,2,15)) tab[1]=newPersonne("toto1","prenom1",new GregorianCalendar(1911,1,15)) tab[2]=newPersonne("toto5","prenom5",new GregorianCalendar(1955,05,15)) tab[3]=newPersonne("toto3","prenom3",new GregorianCalendar(1933,03,15)) tab[4]=newPersonne("toto4","prenom4",new GregorianCalendar(1944,04,15)) tabTrie=(Personne[])tri(tab, //crationduneinstancedeclasseimplmentantlinterface Comparateur newComparateur() //voicilecodedelaclasse { //commelexigelinterfacevoicilamthodecompare publicintcompare(Objecto1,Objecto2) { Personnep1,p2 if(o1instanceofPersonne&o2instanceofPersonne) { p1=(Personne)o1 p2=(Personne)o2 } else { returnClassable.ERREUR } if(p1.getNom().compareTo(p2.getNom())<0) { returnClassable.INFERIEUR } if(p1.getNom().compareTo(p2.getNom())>0) { returnClassable.SUPERIEUR } returnClassable.EGAL }//accoladedefermeturedelamthodecompare }//accoladedefermeturedelaclasse )//findelappeldelafonctiondetri //affichagedutableautri for(inti=0i<tabTrie.lengthi++) { System.out.println(tabTrie[i]) } Sinousvoulonseffectuerunautretriavecuncritrediffrent,nousdevonssimplementappelerlafonctiontriavec unenouvelleinstanceduneclasseinterneanonymequiimplmentediffremmentlafonctionCompare.Nouspouvons parexempletrierlespersonnessurleurge. tabTrie=(Personne[])tri(tab, //crationduneinstancedeclasseimplmentantlinterfaceComparateur newComparateur() //voicilecodedelaclasse { //commelexigelinterfacevoicilamthodecompare publicintcompare(Objecto1,Objecto2) { Personnep1,p2 if(o1instanceofPersonne&o2instanceofPersonne)

ENI Editions - All rigths reserved

- 33 -

{ p1=(Personne)o1 p2=(Personne)o2 } else { returnClassable.ERREUR } if(p1.calculAge()<p2.calculAge()) { returnClassable.INFERIEUR } if(p1.calculAge()>p2.calculAge()) { returnClassable.SUPERIEUR } returnClassable.EGAL }//accoladedefermeturedelamthode }//accoladedefermeturedelaclasse )//findelappeldelafonctiondetri for(inti=0i<tabTrie.lengthi++) { System.out.println(tabTrie[i]) } Lors de la compilation de ce code, des fichiers .class sont gnrs pour chaque classe utilise dans le code. Le compilateurgnreautomatiquementunnompourlefichierdechaqueclasseanonyme.Ilutilisepourcelalenomde classecontainerauquelilajoutelesuffixe$suividunevaleurnumrique.Lacompilationdececodevadoncgnrer lesfichierssuivants : Principale.class:lefichiercorrespondantlaclassePrincipale. Principale$1.class:lefichiercorrespondantlapremireclasseinterneanonyme. Principale$2.class:lefichiercorrespondantladeuximeclasseinterneanonyme. Le seul inconvnient des classes internes anonymes rside dans le fait quelles sont usage unique. Si vous souhaitezlarutiliserplusieursfois,ilfautdanscecascreruneclassenomme.Lenomattribuparlecompilateur laclasseinterneanonymentantbiensrpasaccessiblepartirducode(puisquelleestanonyme !).

6.Lesgnriques
Les types gnriques sont des lments dun programme qui sadaptent automatiquement pour raliser la mme fonctionnalitsurdiffrentstypesdedonnes.Lorsquevouscrezunlmentgnrique,vousnavezpasbesoinde concevoiruneversiondiffrentepourchaquetypededonneaveclequelvoussouhaitezraliserunefonctionnalit. Pourfaireuneanalogieavecunobjetcourant,nousallonsprendrelexempleduntournevis.Enfonctiondutypedevis que vous avez utiliser, vous pouvez prendre un tournevis spcifique pour ce type de vis (plat, cruciforme, torx). Unetechniquefrquemmentutiliseparunbricoleuraverticonsisteacquriruntournevisuniverselavecdemultiples embouts.Enfonctiondutypedevis,ilchoisitlemboutadapt.Lersultatfinalestlemmequesildisposaitdune multitudedetournevisdiffrents :ilpeutvisseretdvisser. Lorsque vous utilisez un type gnrique, vous le paramtrez avec un type de donnes. Ceci permet au code de sadapter automatiquement et de raliser la mme action indpendamment du type de donnes. Une alternative pourraittrelutilisationdutypeuniverselObject.Lutilisationdestypesgnriquesprsenteplusieursavantagespar rapportcettesolution :
q

Elle impose la vrification des types de donnes au moment de la compilation et vite les invitables vrificationsquidoiventtrefaitesmanuellementaveclutilisationdutypeObject. EllevitelesoprationsdeconversiondutypeObjectversuntypeplusspcifiqueetinversement. Lcritureducodeestfacilitedanscertainsenvironnementsdedveloppementaveclaffichageautomatique detouslesmembresdisponiblespouruntypededonnesparticulier. Ellefavoriselcrituredalgorithmesquisontindpendantsdestypesdedonnes.

- 34 -

ENI Editions - All rigths reserved

Les types gnriques peuvent cependant imposer certaines restrictions concernant le type de donnes utilis. Ils peuvent par exemple imposer que le type utilis implmente une ou plusieurs interfaces, soit un type rfrence ou possde un constructeur par dfaut. Il est important de bien comprendre quelques termes utiliss avec les gnriques.
q

Letypegnrique :cestladfinitionduneclasse,interfaceoufonctionpourlaquellevousspcifiezaumoins untypededonnesaumomentdesadclaration. Le type de paramtre : cestlemplacement rserv pour le type de paramtre dans la dclaration du type gnrique. Letypeargument :cest le type de donnes qui remplace le type de paramtre lors de la construction dun typepartirduntypegnrique. Les contraintes : ce sont les conditions que vous imposez qui limitent le type argument que vous pouvez fournir. Le type construit : cest la classe, interface, ou fonction construite partir dun type gnrique pour lequel vousavezspcifidestypesargument.

a.Classesgnriques
Une classe qui attend un type de paramtre est appele classe gnrique. Vous pouvez gnrer une classe construiteenfournissantlaclassegnriqueuntypeargumentpourchacundecestypesparamtre. Dfinitionduneclassegnrique Vouspouvezdfiniruneclassegnriquequifournitlesmmesfonctionnalitssurdiffrentstypesdedonnes.Pour cela,vousdevezfournirunouplusieurstypesdeparamtredansladfinitiondelaclasse.Prenonslexempledune classecapabledegrerunelistedlmentsaveclesfonctionnalitssuivantes.
q

Ajouterunlment. Supprimerunlment. Sedplacersurlepremierlment. Sedplacersurledernierlment. Sedplacersurllmentsuivant. Sedplacersurllmentprcdent. Obtenirlenombredlments.

Nousdevonstoutdaborddfinirlaclassecommeuneclasseordinaire. publicclassListeGenerique { } La transformation de cette classe en classe gnrique se fait en ajoutant un type de paramtre immdiatement aprslenomdelaclasse. publicclassListeGenerique<T> { } Si plusieurs types paramtres sont ncessaires, ils doivent tre spars par des virgules dans la dclaration. Par conventionlestypesparamtressontreprsentsparuncaractremajusculeunique. Silecodedelaclassedoitraliserdautresoprationsquedesaffectations,vousdevezajouterdescontraintessur letypeparamtre.Pourcela,ajoutezlemotclextendssuividelacontrainte.Lacontraintepeuttreconstituepar
ENI Editions - All rigths reserved - 35 -

uneclassespcifiquedontletypeargumentdevrahriterouparuneouplusieursinterfacesquildevraimplmenter. Siplusieurscontraintesdoiventsappliquer,ellessontsparesparlecaractre&.Ilfautdanscecasspcifieren dbut de liste la contrainte lie une classe puis celles lies aux interfaces. Cidessous quelques exemples pour illustrercela. Classegnriqueexigeantqueletypeargumenthritedelaclassepersonne. publicclassListeGenerique<TextendsPersonne> { } ClassegnriqueexigeantqueletypeargumentimplmentelinterfaceClassable. publicclassListeGenerique<TextendsClassable> { } Cestlemmemotclextendsquiestutilispourunecontraintelieuneclasseouuneinterface.

ClassegnriqueexigeantqueletypeargumenthritedelaclassePersonneetimplmentelesinterfacesClassable etCloneable. publicclassListeGenerique<TextendsPersonne&Classable&Cloneable> { } Silnyapasdecontraintespcifie,lesseulesoprationsautorisesserontcellessupportesparletypeObject. Danslecodedelaclasse,chaquemembrequidoittredutypeargumentdoittredfiniavecletypeparamtre,T dansnotrecas.Voyonsmaintenantlecodecompletdelaclasse. importjava.util.ArrayList publicclassListeGenerique<T> { //pourstockerleslmentsdelaliste privateArrayList<T>liste //pointeurdepositiondanslaliste privateintposition //nombredlmentsdelaliste privateintnbElements //constructeuravecunparamtrepermettantdedimensionnerlaliste publicListeGenerique(inttaille) { liste=newArrayList<T>(taille) } publicvoidajout(Telement) { liste.add(element) nbElements=nbElements+1 } publicvoidinsert(Telement,intindex) { //onvrifiesilindexnestpassuprieuraunombredlments //ousilindexnestpasinfrieur0 if(index>=nbElements||index<0) { return } liste.add(index,element) //onmetjourlenombredlments nbElements=nbElements+1 } publicvoidremplace(Telement,intindex) { //onvrifiesilindexnestpassuprieuraunombredlments //ousilindexnestpasinfrieur0 if(index>=nbElements||index<0) {
- 36 ENI Editions - All rigths reserved

return } liste.set(index,element) } publicvoidsupprime(intindex) { inti //onvrifiesilindexnestpassuprieuraunombredlments //ousilindexnestpasinfrieur0 if(index>=nbElements||index<0) { return } liste.remove(index) //onmetjourlenombredlments nbElements=nbElements1 } publicintgetTailleListe() { returnnbElements } publicTpremier()throwsException { if(nbElements==0) { thrownewException("listevide") } //ondplacelepointeursurlepremierlment position=0 returnliste.get(0) } publicTdernier()throwsException { if(nbElements==0) { thrownewException("listevide") } //ondplacelepointeursurledernierlment position=nbElements1 returnliste.get(position) } publicTsuivant()throwsException { if(nbElements==0) { thrownewException("listevide") } //onvrifiesionnestpaslafindelaliste if(position==nbElements1) { thrownewException("pasdelementsuivant") } //ondplacelepointeursurllmentsuivant position=position+1 returnliste.get(position) } publicTprecedent()throwsException { if(nbElements==0) { thrownewException("listevide") } //onvrifiesionnestpassurlepremierlment if(position==0) { thrownewException("pasdlmentprcdent") } //onsedplacesurllmentprcdent position=position1 returnliste.get(position)

ENI Editions - All rigths reserved

- 37 -

} } Utilisationduneclassegnrique Pourpouvoirutiliseruneclassegnrique,vousdeveztoutdabordgnreruneclasseconstruiteenfournissantun type argument pour chacun de ces types paramtre. Vous pouvez alors instancier la classe construite par un des constructeurs disponibles. Nous allons utiliser la classe conue prcdemment pour travailler avec une liste de chanesdecaractres. ListeGenerique<String> liste = new ListeGenerique<String>(5); Cettedclarationpermetdinstancierunelistedecinqchanes.Lesmthodesdelaclassesontalorsdisponibles. liste.ajout("premier") ; liste.ajout("deuxieme"); Le compilateur vrifie bien sr que nous utilisons notre classe correctement notamment en vrifiant les types de donnesquenousluiconfions.

Voicilecodedunepetiteapplicationpermettantdetesterlebonfonctionnementdenotreclassegnrique : importjava.io.BufferedReader importjava.io.InputStreamReader publicclassTestListeGenerique { staticListeGenerique<String>liste=new ListeGenerique<String>(5) publicstaticvoidmain(String[]args) { liste.ajout("premier") liste.ajout("deuxime") liste.ajout("troisime") liste.ajout("quatrime") liste.ajout("cinquime") menu() } publicstaticvoidmenu() { charchoix=\0 System.out.println("p(premier)<(prcdent)>(suivant)d (dernier)f(fin)") while(choix!=f) { try { BufferedReaderbr br=newBufferedReader(new InputStreamReader(System.in)) choix=br.readLine().charAt(0) switch(choix) { casep: System.out.println("lepremier"+

- 38 -

ENI Editions - All rigths reserved

liste.premier()) break case<: System.out.println("leprcdent"+ liste.precedent()) break case>: System.out.println("lesuivant"+ liste.suivant()) break cased: System.out.println("ledernier"+ liste.dernier()) break } } catch(Exceptione) { System.out.println(e.getMessage()) } System.out.println("p(premier)<(prcdent)>(suivant)d (dernier)f(fin)") } } } Nouspouvonsgalementvrifierquenotreclassefonctionnegalementsansproblmesinousluidemandonsde travailleravecdespersonnes. publicstaticvoidmain(String[]args) { liste.ajout(newPersonne("toto2","prenom2",new GregorianCalendar(1922,2,15))) liste.ajout(newPersonne("toto1","prenom1",new GregorianCalendar(1911,1,15))) liste.ajout(newPersonne("toto5","prenom5",new GregorianCalendar(1955,5,15))) liste.ajout(newPersonne("toto3","prenom3",new GregorianCalendar(1933,3,15))) liste.ajout(newPersonne("toto4","prenom4",new GregorianCalendar(1944,4,15)))menu() }

b.Mthodesgnriques
Unefonctiongnriqueestunemthodedfinieavecaumoinsuntypeparamtre.Cecipermetaucodeappelantde spcifierletypededonnesdontilabesoinchaqueappeldelafonction.Unetellemthodepeutcependanttre utilisesansindiquerdinformationspourletypeargument.Danscecaslecompilateuressaiededterminerletype en fonction des arguments qui sont passs la mthode. Pour illustrer la cration de fonctions gnriques, nous allonstransformerlafonctiondetrienversiongnrique. publicstatic<TextendsClassable>void tri(ListeGenerique<T>liste)throwsException { inti,j Tc for(i=0i<liste.getNbElements()1i++) { for(j=i+1j<liste.getNbElements()j++) { if (liste.getElement(j).compare(liste.getElement(i))==Classable.INFERIEUR) { c=liste.getElement(j) liste.remplace(liste.getElement(i),j) liste.remplace(c,i) } elseif

ENI Editions - All rigths reserved

- 39 -

(liste.getElement(j).compare(liste.getElement(i))==Classable.ERREUR) { thrownewException("erreurpendantletri") } } } } Comme pour la cration dune classe gnrique le type paramtre est spcifi entre les caractres < et>. Si des contraintes doivent sappliquerauxtypesarguments,vousdevezlesspcifieraveclesmmesrglesquepourles classesgnriques. Lappel dune fonction gnrique est semblable lappel dune fonction normale hormis le fait que nous pouvons spcifierdestypesargumentspourchacundestypesparamtre.Cecinestpasuneobligationcarlecompilateurest capabledinfrerlestypesargumentsaumomentdelacompilation. Lappeldelafonctionpeutdoncsefaireaveclesdeuxsyntaxessuivantes : TestListeGenerique.<Personne>tri(liste); ou TestListeGenerique.tri(liste);

c.Lesgnriquesetlhritage
Lutilisationcombinedesgnriquesetdelhritagepeutparfoisprovoquerquelquessoucisaudveloppeurdune application.Nousavonsdtermindansleparagrapheconsacrlhritagequavecunevariableduncertaintype lonpouvaitrfrenceruneinstancedeclassedecetypemaisaussiuneinstancedeclassedenimportelequelde sessoustypes.Lecodesuivantestdoncparfaitementlgaletfonctionnecorrectement. Personnep Clientc c=newClient() p=c p.setNom("Dupont") p.setPrenom("paul") Sinoustentonslammeexprienceaveclesgnriquesentestantlecodesuivant. ListeGenerique<Personne>listePersonnes ListeGenerique<Client>listeClient listeClient=newListeGenerique<Client>(10) listePersonnes=listeClient Ilesteffectivementlgitimedepenserque,puisquelonpeutaffecterunevariabledetypePersonneunerfrence vers une instance dune de ces sousclasses (Client), la mme opration est certainement ralisable avec une ListeGenerique<Personne> et une ListeGenerique<Client>. Pourtant le compilateur ne voit pas les choses de la mmefaon.

- 40 ENI Editions - All rigths reserved

Cettelimitationestenfaitlieaumcanismedeffacementdetypeutilisparlecompilateur.Sonprincipalbutestde rendrecompatibleaveclesversionsantrieuresdesmachinesvirtuellesJavalecodecompil. Enfaitlorsdelacompilationduneclassegnrique,lecompilateurremplaceletypeparamtreparletypeObjectou paruntypecorrespondantlacontrainteplacesurletypeparamtre.LecodedelaclasseListeGeneriquesera traitdelafaonsuivanteparlecompilateur. importjava.util.ArrayList publicclassListeGenerique<T> { //pourstockerleslmentsdelaliste privateArrayList<T Object>liste //pointeurdepositiondanslaliste privateintposition //nombredlmmentsdelaliste privateintnbElements //constructeuravecunparamtrepermettantdedimensionnerlaliste publicListeGenerique(inttaille) { liste=newArrayList<T Object>(taille) } publicvoidajout(T Objectelement) { liste.add(element) nbElements=nbElements+1 } publicvoidinsert(T Objectelement,intindex) { //onvrifiesilindexnestpassuprieuraunombredlments //ousilindexnestpasinfrieur0 if(index>=nbElements||index<0) { return } liste.add(index,element) //onmetjourlenombredlments nbElements=nbElements+1 } publicT Objectpremier()throwsException { if(nbElements==0) { thrownewException("listevide") } //ondplacelepointeursurlepremierlment position=0 returnliste.get(0) } publicT Objectdernier()throwsException { if(nbElements==0) { thrownewException("listevide") } //ondplacelepointeursurledernierlment position=nbElements1 returnliste.get(position) } ... ... } Pourentreconvaincu,essayonslecodesuivantdanslaclasseListeGnrique. publicvoidajout(Telement) { liste.add(element) nbElements=nbElements+1

ENI Editions - All rigths reserved

- 41 -

} publicvoidajout(Objectelement) { liste.add(element) nbElements=nbElements+1 } lacompilation,nousavonsbienunmessagederreurnousindiquantquelamthodeajout(Objet)estdfiniedeux foisdanslaclasse. Uneautreoprationraliseparlecompilateurconsisteeffectueruneconversionpourlesvaleursrenvoyespar lesfonctionsdelaclassegnrique.Lecodesuivant : staticListeGenerique<Personne>liste=newListeGenerique<Personne>(5) publicstaticvoidmain(String[]args)throwsException { liste.ajout(newPersonne("toto2","prenom2",new GregorianCalendar(1922,2,15))) liste.ajout(newPersonne("toto1","prenom1",new GregorianCalendar(1911,1,15))) liste.ajout(newPersonne("toto5","prenom5",new GregorianCalendar(1955,05,15))) liste.ajout(newPersonne("toto3","prenom3",new GregorianCalendar(1933,03,15))) liste.ajout(newPersonne("toto4","prenom4",new GregorianCalendar(1944,04,15))) Personnep p=liste.getElement(0) } seraenfaitimplicitementcompilsouscetteforme : staticListeGenerique<Personne>liste=newListeGenerique<Personne>(5) publicstaticvoidmain(String[]args)throwsException { liste.ajout(newPersonne("toto2","prenom2",new GregorianCalendar(1922,2,15))) liste.ajout(newPersonne("toto1","prenom1",new GregorianCalendar(1911,1,15))) liste.ajout(newPersonne("toto5","prenom5",new GregorianCalendar(1955,05,15))) liste.ajout(newPersonne("toto3","prenom3",new GregorianCalendar(1933,03,15))) liste.ajout(newPersonne("toto4","prenom4",new GregorianCalendar(1944,04,15))) Personnep p=(Personne)liste.getElement(0); } Ilfautdoncretenirdecesexpriencesquuneclassegnriqueconstruiteaveccommetypeparamtreuneclasse quelconque,nestpaslasousclasseduneclassegnriqueconstruiteavecuntypequiestlesupertypedecette classequelconque.

- 42 -

ENI Editions - All rigths reserved

Cettelimitationpeutparfoistregnante.Sinoussouhaitonscrerunefonctionquiacceptecommeparamtreune ListeGeneriqueconstruitepartirdenimportequeltypededonnes,notrepremireintuitionestdcrire le code suivant: publicstaticvoidaffichage(ListeGenerique<Object>liste) { } Hlas, notre premire intuition nest pas bonne car la fonction affichagenaccepte, comme paramtre, avec cette syntaxe,quedesinstancesdeListeGeneriquedObject. Pour reprsenter le fait que la fonction affichage accepte comme paramtre une instance de ListeGenerique construitepartirdenimportequeltype,nousdevonsutiliserlecaractrejoker "?"dansladfinitiondelafonction affichage.Elleprenddonclaformesuivante : publicstaticvoidaffichage(ListeGenerique<?>liste) { } Avec cette syntaxe nous pouvons utiliser la fonction affichage avec comme paramtre, une instance de ListeGenerique construite partir de nimporte quelle classe. Par contre, dans le code de la fonction nous ne pourronsutiliserquelesmthodesdelaclasseObjectsurleslmentsprsentsdanslaliste.Nouspouvonsajouter desrestrictionssurletypeargumentdelafonctionenfaisantsuivrelecaractre?parunecontraintedfinieavec exactement la mme syntaxe que pour une classe gnrique. Pour que la fonction affichage accepte comme paramtre une ListeGenerique de Personne et de nimporte laquelle de ces sousclasses, nous devons utiliser la syntaxesuivante: publicstaticvoidaffichage(ListeGenerique<?extends Personne>liste){ liste.premier() for(inti=0i<liste.getNbElements()i++) { System.out.println(liste.getElement(i).getNom()) System.out.println(liste.getElement(i).getPrenom()) System.out.println("") } } noterquedanscecaslesinstancesprsentesdanslalisteserontaumoinsdesinstancesdelaclassePersonne etpourronttreutilisescommetellesentoutescuritlintrieurdelafonction.

7.Lespackages

ENI Editions - All rigths reserved

- 43 -

Le but principal des packages est lorganisation et le rangement des classes et interfaces dune application. Le principeestlemmequedanslaviecourante.Sivousavezungrandplacarddansvotremaison,ilestvidentque linstallation dtagres dans ce placard va faciliter lorganisation et la recherche des objets qui y sont rangs par rapportunstockageen"vrac".Lorganisationdesclassesenpackageapportelesavantagessuivants :
q

Facilitpourretrouveretrutiliserunlment. Limitationdesrisquesdeconflitsdenoms. Crationdunenouvellevisibilitenplusdesvisibilitsstandards(private,protected,public).

a.Crationdunpackage
Lapremirechosefairelorsquelonsouhaitecrerunpackageestdeluitrouverunnom.Cenomdoittrechoisi avecprcautionpourpermettreaupackagederemplirpleinementsonrle.Ildoittreuniqueetreprsentatifdes lmentsstockslintrieur. Pourassurerlunicitdunomdunpackage,onutiliseparconventionsonnomdedomaineeninversantlordredes lmentscommepremirepartiepourlenomdupackage. Parexemple,silenomdedomaineesteni.fr,lapremirepartiedunomdupackageserafr.eni.Silenomdedomaine comportedescaractresinterditspourlesnomsdepackages,ilssontremplacsparlecaractre_.Ainsipourlenom de domaine eniecole.fr, la premire partie du nom de package sera fr.eni_ecole. Cette premire partie du nom permetdassurerlunicitdeslmentsparrapportlextrieur.Lasuitedunomdepackagevaassurerlunicitdes lmentslintrieurdelapplication.Ilfautbienchoisirdesnomsclairsetreprsentatifsdeslmentsdupackage. NouspouvonsparexempleavoirdansuneapplicationdeuxclassesClient lunereprsentantunepersonneayant pass des commandes notre entreprise, lautre reprsentant un client au sens informatique du terme (client serveur).Lesnomsdepackagesuivantpeuventtreutilisspourhbergercesdeuxclasses.fr.eni_ecole.compta pourlaclassereprsentantunclientphysiqueetfr.eni_ecole.reseaupourlaclassereprsentantunclientlogiciel. Parconventionlesnomsdepackagessontentirementenlettresminuscules.Lenomchoisidoittreplacdansle fichiersourceprcddumotclpackage.Ladclarationdupackagedoittreobligatoirementlapremirelignedu fichier.Tousleslmentsplacsdanscefichiersourcefontdsormaispartiedecepackage.Siaucuneinformation nest indique concernant le package dans le fichier source alors les lments dfinis dans ce fichier seront considrscommefaisantpartiedupackagepardfautquinepossdepasdenom.Ilconvientdtreprudentavec lepackagepardfautcarlesclassesquiysontdfiniesnesontpasaccessiblespartirdunpackagenomm. CestentreautrespourcetteraisonqueSUNrecommandedetoujoursplaceruneclassedansunpackagenomm. Lutilisationdespackagesnousimposegalementuneorganisationspcifiquepourlenregistrementsurdisquedes fichierssourcesetdesfichierscompils.Lesrpertoiresosontenregistrslesfichiersdoiventrespecterlesnoms utiliss pour les packages. Chaque composant du nom de package doit correspondre un sousrpertoire. Les fichiers sources et les fichiers compils peuvent tre stocks dans des branches darborescence diffrentes. Nous pouvonsparexempleavoirlorganisationsuivante:

Lerespectdecettearborescenceestimpratif.Silefichierduneclasseappartenantunpackagenestpasplac danslebonrpertoire,lamachinevirtuellechargedexcuterlapplicationseraincapabledelocalisercetteclasse.
- 44 ENI Editions - All rigths reserved

Pourlocaliseruneclasse,lamachinevirtuelleutiliselavariabledenvironnementCLASSPATHpourconstruirelechemin daccsaufichierdecetteclasse.Elleconcatnelechemincontenudanscettevariableaveclechemincorrespondant au package dans lequel se trouve la classe. Si plusieurs rpertoires sont indiqus dans la variable CLASSPATH, ils doivent tre spars par des pointsvirgules pour un environnement Windows et par des virgules pour un environnementUnix.Lerpertoirecourantfaitpartiepardfautducheminderecherche.

b.Utilisationetimportationdunpackage
Lorsquuneclassefaisantpartiedunpackageestutilisedansuneapplication,lenomcompletdelaclasse(nomdu package + nom de la classe) doit tre utilis. Ceci provoque lcriture de lignes de code relativement longues et difficilesrelire. fr.eni_ecole.compta.Client c=new fr.eni_ecole.compta.Client ("dupont","paul",new GregorianCalendar(1953,11,8),E); Java propose linstruction import pour indiquer au compilateur que certaines classes peuvent tre utilises directementparleurnomsansutilisationdunomdepackage.Cetteinstructiondoittreplaceendbutdefichier aussitt aprs une ventuelle dclaration de package mais avant la dfinition de la classe. La ligne de code prcdentepeuttreconsidrablementabrgeaveclasyntaxesuivante: importfr.eni_ecole.compta.Client Clientc=newClient("dupont","paul",new GregorianCalendar(1953,11,8),E) Par contre, si beaucoup de classes du mme package sont utilises, la liste des importations va devenir volumineuse. Il est plus rationnel dans ce cas dimporter le package complet avec le caractre joker *. Le code devientdonc : importfr.eni_ecole.compta.* Clientc=newClient("dupont","paul",new GregorianCalendar(1953,11,8),E) Aveclapossibilitdutilisertouteslesclassesdupackagefr.eni_ecole.comptasimplementenutilisantlenomdela classe. Cette solution peut parfois poser un problme si deux packages contenant des classes ayant des noms identiques sont imports. Il faudra dans ce cas, pour ces classes, utiliser leurs noms complets. Cette solution ne permetpasnonpluslimportationdeplusieurspackagessimultanment.Lesapparencestantparfoistrompeuses, lastructuredepackagesnestpashirarchiqueet,malgrcequepourraitlaisserpenserlastructuredesfichierssur le disque, le package fr.eni_ecole.compta nest pas inclus dans le package fr.eni_ecole. Limportation suivante import fr.eni_ecole.* ;permetuniquementlaccsauxclassesdecepackageetabsolumentpasauxclassesdu packagefr.eni_ecole.compta.Sictaitlecas,onpeutimaginerfacilementlesproblmespossparlesimportations suivantes : import com.* ; import fr.* ; Limportation peut galement simplifier lcriture du code lors de lutilisation de classes contenant de nombreuses mthodesstatic.Vousdevezpourchaqueappeldunedecesmthodeslaprfixerparlenomdelaclasse.Cecia pourconsquencederduirelalisibilitducode. publicclassDistance { publicstaticdoubledist(doublelat1,doublelon1,doublelat2,doublelon2) { doubledeltaLat doubleabscurv deltaLat=lon2lon1 abscurv=Math.acos((Math.sin(lat1)*Math.sin(lat2))+(Math.cos(lat1) *Math.cos(lat2)*Math.cos(deltaLat))) returnabscurv*6371598

ENI Editions - All rigths reserved

- 45 -

} } IlestpossibledesimplifiercecodeeneffectuantuneimportationstaticdelaclasseMathpermettantlutilisationde cesmembresstaticsanslesprfixerparlenomdelaclasse. importstaticjava.lang.Math.* publicclassDistance { publicstaticdoubledist(doublelat1,doublelon1,doublelat2,doublelon2) { doubledeltaLat doubleabscurv deltaLat=lon2lon1 abscurv=acos((sin(lat1)*sin(lat2))+(cos(lat1)*cos(lat2)*cos( deltaLat))) returnabscurv//*6371598 } }

- 46 -

ENI Editions - All rigths reserved

Gestiondesexceptions
Dans la vie dun dveloppeur, tout nest pas rose ! Les erreurs sont une des principales sources de stress. En fait, lorsque lon y regarde de plus prs, nous pouvons classer ces erreurs qui nous gchent la vie en trois catgories. Regardonschacunedentreellesetlessolutionsdisponiblespourlestraiter.

1.Leserreursdesyntaxe
Ce type derreur se produit au moment de la compilation lorsquun mot cl du langage est mal orthographi. Trs frquentesaveclesoutilsdedveloppementolditeurdecodeetlecompilateursontdeuxentitsspares,elles deviennentdeplusenplusraresaveclesenvironnementsdedveloppementintgr(Eclipse,NetBeans,Jbuilder.). La plupart de ces environnements proposent une analyse syntaxique au fur et mesure de la saisie du code. Les exemplessuivantssontobtenuspartirdelenvironnementEclipse. Si une erreur de syntaxe est dtecte, alors lenvironnement propose des solutions possibles pour corriger cette erreur.

Dautrepart,les"fautesdorthographe"danslesnomsdechampsoudemthodessontfacilementliminesgrce auxfonctionnalitsdisponiblesdanscesenvironnements.

2.Leserreursdexcution
Ces erreurs apparaissent aprs la compilation lorsque vous lancez lexcution de votre application. La syntaxe du codeestcorrectemaislenvironnementdevotreapplicationnepermetpaslexcutionduneinstructionutilisedans votreapplication.Cestparexemplelecassivousessayezdouvrirunfichierquinexistepassurledisquedevotre machine.Vousobtiendrezsrementunmessagedecetype.

ENI Editions - All rigths reserved

- 1-

Cetypedemessagenestpastrssympathiquepourlutilisateur! HeureusementJavapermetlarcuprationdecetypederreuretviteainsilaffichagedecetinquitantmessage. Nousdtailleronscelaunpeuplusloindanscechapitre.

3.Leserreursdelogique
Lespiresennemisdesdveloppeurs.Toutsecompilesansproblme,toutsexcutesanserreursetpourtant"ane marchepascommeprvu"!!! Ilfautdanscecasrevoirlalogiquedefonctionnementdelapplication.Lesoutilsdedbogagenouspermettentde suivreledroulementdelapplication,deplacerdespointsdarrt,devisualiserlecontenudesvariables,etc. Cesoutilsneremplacentcependantpasunebonnedosederflexion(etparfoisquelquescomprimsdaspirine).

a.Lesexceptions
Lorsquuneerreurseproduitaucoursdelexcutiondunemthode,unobjetExceptionestcrpourreprsenter lerreur qui vient de ce produire. Cet objet contient de nombreuses informations concernant lerreur qui est survenue dans lapplication ainsi que ltat de lapplication au moment de lapparition de lerreur. Cet objet est ensuite transmis la machine virtuelle. Cest le dclenchement de lexception. La machine virtuelle doit alors rechercher une solution pour la grer. Pour cela, elle explore les diffrentes mthodes ayant t appeles pour atteindre lemplacement o lerreursest produite. Dans ces diffrentes mthodes, elle recherche un gestionnaire dexceptionscapabledetraiterleproblme.Larecherchedbuteparlamthodeolexceptionatdclenche puis remonte jusqu la mthode main de lapplication si besoin. Lorsquun gestionnaire dexception adapt est trouv, lobjet Exception lui est transmis pour quil en assure le traitement. Si la recherche est infructueuse, lapplicationsarrte. Lesexceptionssontengnralclassesentroiscatgories.
q

Les exceptions vrifies correspondent une situation anormale au cours du fonctionnement de lapplication.Cettesituationestengnrallieunlmentextrieurlapplication,commeparexemple uneconnexionversunebasededonnesouunelecturedefichier. Leserreurscorrespondentdesconditionsexceptionnellesextrieureslapplication que cellecinepeut gnralementpasprvoir. Leserreursliesunemauvaiseutilisationdunefonctionnalitdulangage,ouuneerreurdelogiquedans laconceptiondelapplication.LerreurlaplusfrquentequevousrencontrerezdansvosdbutsavecJava sera certainement lexception NullPointerException dclenche lors de lutilisation dune variable non initialise.

Seules les exceptions vrifies doivent obligatoirement tre traites au moment de leur dclenchement ou propagesaucodeappelant.

- 2-

ENI Editions - All rigths reserved

b.Rcuprationdexceptions
Lagestiondesexceptionsdonnelapossibilitdeprotgerunblocdecodecontrelesexceptionsquipourraientsy produire.Lecode"dangereux"doittreplacdansunbloc try.Siuneexceptionestdclenchedansceblocde code, le ou les blocs de code catch sont examins. Sil en existe un capable de traiter lexception, le code correspondant est excut, sinon la mme exception est dclenche pour ventuellement tre rcupre par un bloc try de plus haut niveau. Une instruction finally permet de marquer un groupe dinstructions qui seront excutes la sortie du bloc try si aucune exception ne sest produite ou la sortie dun bloc catch si une exceptionatdclenche.Lasyntaxegnraleestdonclasuivante: try { ... Instructions dangereuses ... } catch (exception1 e1) { ... code excut si une exception de type Exception1 se produit ... } catch (exception2 e2) { ... code excut si une exception de type Exception1 se produit ... } finally { ... code excut dans tous les cas avant la sortie du bloc try ou dun bloc catch ... } Cettestructureaunfonctionnementtrssemblableauswitch casedjtudi. Vousdevezindiquerpourchaquebloccatchletypedexceptionquildoitgrer. public void lireFichier(String nom) { FileInputStream fichier=null; BufferedReader br=null; String ligne=null; try { fichier=new FileInputStream("c:\\data\\bilan.txt"); } catch (FileNotFoundException e) { e.printStackTrace(); } br=new BufferedReader(new InputStreamReader(fichier)); try { ligne=br.readLine(); } catch (IOException e) { e.printStackTrace(); } while (ligne!=null) { System.out.println(ligne); try { ligne=br.readLine(); }

ENI Editions - All rigths reserved

- 3-

catch (IOException e) { e.printStackTrace(); } } } Danslexempleprcdent,chaqueinstructionsusceptiblededclencheruneexceptionestprotgeparsonpropre bloc try. Cette solution prsente lavantage dtre extrmement prcise pour la gestion des exceptions au dtrimentdelalisibilitducode.Unesolutionplussimpleconsisteregrouperplusieursinstructionsdansunmme bloctry.Notreexemplepeutgalementtrecoddelafaonsuivante: public void lireFichier(String nom) { FileInputStream fichier=null; BufferedReader br=null; String ligne=null; try { fichier=new FileInputStream(nom); br=new BufferedReader(new InputStreamReader(fichier)); ligne=br.readLine(); while (ligne!=null) { System.out.println(ligne); ligne=br.readLine(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } Lecodeestbeaucouppluslisible,parcontrenousperdonsenprcisioncarildevientdifficilededterminerquelle instructionadclenchlexception. Ilfautgalementtrevigilantsurlordredesblocscatchettoujourslesorganiserduplusprcisauplusgnral. Lesexceptionstantdesclasses,ellespeuventavoirdesrelationsdhritage.Siunbloccatchestprvupourgrer untypeparticulierdexception,ilestgalementcapabledegrertouteslestypesdexceptionsquihritentdecelle ci. Cest le cas dans notre exemple puisque la classe FileNotFoundException hrite de la classe IOException. Le compilateurdtecteunetellesituationetgnreuneerreur.Sinousmodifionsnotrecodedelafaonsuivante : public void lireFichier(String nom) { FileInputStream fichier=null; BufferedReader br=null; String ligne=null; try { fichier=new FileInputStream(nom); br=new BufferedReader(new InputStreamReader(fichier)); ligne=br.readLine(); while (ligne!=null) { System.out.println(ligne); ligne=br.readLine(); } } catch (IOException e) { e.printStackTrace(); } catch (FileNotFoundException e) {

- 4-

ENI Editions - All rigths reserved

e.printStackTrace(); }

} Nousobtenonscetteerreuraumomentdelacompilation.

Le code de chaque bloc catch peut obtenir plus dinformations sur lexception quil doit traiter en utilisant les mthodesdisponiblesdanslaclassecorrespondantlexception.Lesmthodessuivantessontlesplusutilespour obtenirdesinformationscomplmentairessurlexception.
q

getMessage :permetdobtenirlemessagederreurassocilexception. getCause :permetdobtenirlexceptioninitialedanslecasolechanagedexceptionestutilis. getStackTrace : permet dobtenir un tableau de StackTraceElement dont chaque lment reprsente une mthode appele jusqu celle o est traite lexception. Pour chacune delle nous pouvons obtenir les informationssuivantes:
q

Lenomdelaclasseosetrouvelamthode :getClassName Lenomdufichierosetrouvecetteclasse :getFilename Lenumrodelaligneolexceptionatdclenche :getLineNumber Lenomdelamthode :getMethodName.

Ces informations peuvent tre utilises pour gnrer des fichiers historiques du fonctionnement de lapplication. Voiciunexempledenregistrementdecesinformationsdansunfichiertexte. import import import import import import import import java.io.BufferedReader; java.io.BufferedWriter; java.io.FileInputStream; java.io.FileNotFoundException; java.io.FileWriter; java.io.IOException; java.io.InputStreamReader; java.util.GregorianCalendar;

public class LectureFichier { public static void main(String args[]) { try { lireFichier("bilan.txt"); } catch (CaMarchePasException e) { FileWriter log; BufferedWriter br; try {

ENI Editions - All rigths reserved

- 5-

log=new FileWriter("historique.txt",true); br=new BufferedWriter(log); br.write("------>"+ new GregorianCalendar().getTime()+" <--------\r\n"); br.write("erreur : " + e.getMessage()+"\r\n"); for (int i=0;i<e.getStackTrace().length;i++) { br.write("dans le fichier " +e.getStackTrace()[i].getFileName()); br.write(" la ligne " +e.getStackTrace()[i].getLineNumber()); br.write(" dans la mthode " +e.getStackTrace()[i].getMethodName()); br.write(" de la classe " + e.getStackTrace()[i].getClassName()+ "\r\n"); } br.close(); log.close(); } catch (IOException ex) { System.out.println("erreur dans lapplication"); } } } public static void lireFichier(String nom) throws CaMarchePasException { FileInputStream fichier=null; BufferedReader br=null; String ligne=null; try { fichier=new FileInputStream(nom); br=new BufferedReader(new InputStreamReader(fichier)); ligne=br.readLine(); while (ligne!=null) { System.out.println(ligne); ligne=br.readLine(); } } catch (FileNotFoundException e) { throw new CaMarchePasException("le fichier nexiste pas",e); } catch (IOException e) { throw new CaMarchePasException("erreur de lecture du fichier",e); } } }

c.Crationetdclenchementdexceptions
Lesexceptionssontavanttoutdesclasses,ilestdoncpossibledecrernospropresexceptionsenhritantdune desnombreusesclassesdexceptiondjdisponibles.Pourrespecterlesconventions,ilestconseilldeterminerle nomdelaclasseparletermeException.Nouspouvonsparexemplecrirelecodesuivant : public class CaMarchePasException extends Exception { public CaMarchePasException() { super(); } public CaMarchePasException(String message)
- 6 ENI Editions - All rigths reserved

{ super(message); } public CaMarchePasException(String message, Throwable cause) { super(message,cause); } public CaMarchePasException(Throwable cause) { super(cause); } }

Lasurchargedesconstructeursdelaclassedebaseestfortementconseillepourconserverlacohrence entrelesclassesdexception. Cetteclassepeutensuitetreutilisepourledclenchementduneexceptionpersonnalise.Pourdclencherune exception, il faut au pralable crer une instance de la classe correspondante puis dclencher lexception avec le mot cl throw. Le dclenchement dune exception dans une fonction avec le mot cl throw provoque la sortie immdiatedelafonction.Lecodesuivantdclencheuneexceptionpersonnalisedanslesblocscatch. public static void lireFichier2(String nom) throws CaMarchePasException { FileInputStream fichier=null; BufferedReader br=null; String ligne=null; try { fichier=new FileInputStream(nom); br=new BufferedReader(new InputStreamReader(fichier)); ligne=br.readLine(); while (ligne!=null) { System.out.println(ligne); ligne=br.readLine(); } } catch (FileNotFoundException e) { throw new CaMarchePasException("le fichier nexiste pas",e); } catch (IOException e) { throw new CaMarchePasException("erreur de lecture du fichier",e); } } Lorsquunefonctionestsusceptiblededclencheruneexception,vousdevezlesignalerdanslasignaturedecette fonctionaveclemotclthrowssuividelalistedesexceptionsquellepeutdclencher.Lorsquecettefonctionsera ensuiteutilisedansuneautrefonction,vousdevrezobligatoirementtenircomptedecette,oudecesventuelles exceptions.Vousdevrezdoncsoitgrerlexceptionavecunbloctry catchsoitlapropagerenajoutantlemotcl throwsladclarationdelafonction.Ilfautcependanttreprudentetnepaspropagerlesexceptionsaudelde lamthodemaincardanscecas,cestlamachinevirtuelleJavaquilesrcupreetarrtebrutalementlapplication.

ENI Editions - All rigths reserved

- 7-

Introduction
Jusquprsent,touslesexemplesdecodequenousavonsralissfonctionnentexclusivementenmodecaractres. Lesinformationssontaffichesdansuneconsoleetgalementsaisiespartirdecelleci.Lasimplicitdecemodede fonctionnement est un atout indniable pour lapprentissagedun langage. Par contre, la plupart des utilisateurs de vos futures applications sattendent certainement avoir une interface un petit peu moins austre quun cran en modecaractres.NousallonsdonctudierdanscechapitrecommentfonctionnentlesinterfacesgraphiquesavecJava. Vous allez rapidement vous apercevoir que la conception dinterfaces graphiques en Java nest pas trs simple et ncessite lcriture de nombreuses lignes de code. Dans la pratique, de nombreux outils de dveloppement sont capablesdeprendreenchargelagnrationdunegrandepartiedececodeenfonctiondelaconceptiongraphiquede lapplicationquevousdessinez.Ilestcependantimportantdebiencomprendrelesprincipesdefonctionnementdece code pour ventuellement intervenir dessus et loptimiser. Nous nutiliserons pas dans ce chapitre doutil spcifique maisnousconserveronsnotretrioditeurdetexte,compilateur,machinevirtuelle.

1.Lesbibliothquesgraphiques
LelangageJavaproposedeuxbibliothquesddieslaconceptiondinterfacesgraphiques.LabibliothqueAWTet labibliothqueSWING.Lesprincipesdutilisationsontquasimentidentiquespourcesdeuxbibliothques.Lutilisation simultanedecesdeuxbibliothquesdansunemmeapplicationpeutprovoquerdesproblmesdefonctionnement etdoittrevite.

a.LabibliothqueAWT
Cette bibliothque est la toute premire disponible pour le dveloppement dinterfaces graphiques. Elle contient une multitude de classes et interfaces permettant la dfinition et la gestion dinterfaces graphiques. Cette bibliothque utilise en fait les fonctionnalits graphiques du systme dexploitation. Ce nest donc pas le code prsentdanscettebibliothquequiassurelerendugraphiquedesdiffrentscomposants.Cecodesertuniquement dintermdiaire avec le systme dexploitation. Son utilisation est de ce fait relativement conome en ressources. Parcontreellesouffredeplusieursinconvnients.
q

Laspectvisueldechaquecomposanttantlilareprsentationquenfaitlesystmedexploitation,ilest parfois dlicat de dvelopper une application ayant une apparence cohrente sur tous les systmes. La taille et la position des diffrents composants tant les deux lments principalement affects par ce problme. Pour que cette bibliothque soit compatible avec tous les systmes dexploitation, les composants quelle contientsontdonclimitsauxpluscourants(boutons,zonedetexte,listes).

b.LabibliothqueSwing
CettebibliothqueatconuepourpallierlesprincipalesinsuffisancesdelabibliothqueAWT.Cetteamlioration a t obtenue en crivant entirement cette bibliothque en Java sans pratiquement faire appel aux services du systme dexploitation. Seuls quelques lments graphiques (fentres et botes de dialogue) sont encore en relation avec le systme dexploitation. Pour les autres composants, cest le code de la bibliothque Swing qui dtermine entirement leurs aspects et comportements. La bibliothque Swing contient donc une quantit impressionnantedeclassesservantredfinirlescomposantsgraphiques.Ilnefautcependantpaspenserquela bibliothqueSwingrendcompltementobsoltelabibliothqueAWT.BeaucoupdlmentsdelabibliothqueAWT sontdailleursreprisdanslabibliothqueSwing.Nousutiliseronsprincipalementcettebibliothquedanslerestede cechapitre.

2.Constitutiondelinterfacegraphiqueduneapplication
Laconceptiondelinterfacegraphiqueduneapplicationconsisteessentiellementcrerdesinstancesdesclasses reprsentant les diffrents lments ncessaires, modifier les caractristiques de ces instances de classe, les assembleretprvoirlecodedegestiondesdiffrentsvnementspouvantinterveniraucoursdufonctionnementde lapplication. Une application graphique est donc constitue dune multitude dlments superposs ou imbriqus. Parmiceslments,lundentreeuxjoueunrleprpondrantdanslapplication.Ilestsouventappelconteneurde premier niveau. Cest lui qui va interagir avec le systme dexploitation et contenir tous les autres lments. En gnral ce conteneur de premier niveau ne contient pas directement les composants graphiques mais dautres conteneurssurlesquelssontplacslescomposantsgraphiques.Pourfaciliterladispositiondeceslmentslesuns par rapport aux autres, nous pouvons utiliser laide dun gestionnaire de mise en page. Cette superposition dlments peut tre assimile une arborescence au sommet de laquelle nous avons le conteneur de premier

ENI Editions - All rigths reserved

- 1-

niveau et dont les diffrentes branches sont constitues dautres conteneurs. Les feuilles de larborescence correspondantauxcomposantsgraphiques. Le conteneur de premier niveau tant llment indispensable de toute application graphique, nous allons donc commencer par tudier en dtail ces caractristiques et son utilisation puis nous tudierons les principaux composantsgraphiques.

- 2-

ENI Editions - All rigths reserved

Conceptionduneinterfacegraphique
Nous avons vu un petit peu plus haut que toute application graphique est au moins constitue dun conteneur de premierniveau.LabibliothqueSwingdisposedetroisclassespermettantdejouercerle : JApplet :reprsenteunefentregraphiqueembarquelintrieurdunepagehtmlpourtrepriseenchargeparun navigateur.Cetlmentesttudiendtaildanslechapitrequiluiestconsacr. JWindow :reprsenteunefentregraphiquelaplusrudimentairequisoit.Cellecinedisposepasdebarredetitre,de menu systme, pas de bordure, cest en fait un simple rectangle sur lcran. Cette classe est rarement utilise sauf pourlaffichageduncrandaccueillorsdudmarrageduneapplication(splashscreen). JFrame :reprsenteunefentregraphiquecomplteetpleinementfonctionnelle.Elledisposedunebarredetitre,dun menu systme, dune bordure, elle peut facilement accueillir un menu, cest bien sr cet lment que nous allons utiliserdanslatrsgrandemajoritdescas.

1.Lesfentres
LaclasseJFrame est llmentindispensabledetouteapplicationgraphique.Commepouruneclassenormalenous devonscreruneinstance,modifierventuellementlespropritsetutiliserlesmthodes.Voicidonclecodedela premireapplicationgraphique. package fr.eni; import javax.swing.JFrame; public class Principale { public static void main(String[] args) { JFrame fenetre; // cration de linstance de la classe JFrame fenetre=new JFrame(); // modification de la position et de la // taille de la fentre fenetre.setBounds(0,0,300,400); // modification du titre de la fentre fenetre.setTitle("premire fentre en JAVA"); // affichage de la fentre fenetre.setVisible(true); } Etlersultatdesonexcution:

Cest simple dutilisation et trs efficace. Cest dailleurs tellement efficace que vous ne pouvez pas arrter lapplication.Eneffetmmesilafentreestfermeparlutilisateur,cettefermetureneprovoquepaslasuppression de linstance de la JFrame de la mmoire. La seule solution pour arrter lapplication est de stopper la machine virtuelleJavaaveclacombinaisondetouches[Ctrl]C.Ilfautbiensrprvoiruneautresolutionpourterminerplus facilementlexcutiondelapplicationetfaireensortequecellecisarrtelafermeturedelafentre. Lapremiresolutionconsistegrerlesvnementsseproduisantlorsdelafermeturedelafentreetdansunde ces vnements provoquer larrt de lapplication. Cette solution sera tudie dans le paragraphe consacr la gestiondesvnements. Ladeuximesolutionutilisedescomportementsprdfinispourlafermeturedelafentre.Cescomportementssont dtermins par la mthode setDefaultCloseOperation. Plusieurs constantes sont dfinies pour dterminer laction entrepriselafermeturedelafentre. DISPOSE_ON_CLOSE:cetteoptionprovoquelarrtdelapplicationlorsdelafermeturedeladernirefentrepriseen

ENI Editions - All rigths reserved

- 1-

chargeparlamachinevirtuelle. DO_NOTHING_ON_CLOSE :aveccetteoption,ilnesepasserienlorsquelutilisateurdemandelafermeturedelafentre. Il est dans ce cas obligatoire de grer les vnements pour que laction de lutilisateur provoque un effet sur la fentreoulapplication. EXIT_ON_CLOSE:cetteoptionprovoquelarrtdelapplicationmmesidautresfentressontencorevisibles. HIDE_ON_CLOSE:aveccetteoptionlafentreestsimplementmasqueparunappelsamthodesetVisible(false). LaclasseJFramesetrouvesituelafindunehirarchiedeclassesassezimportanteetimplmentedenombreuses interfaces.Decefaitellepossdedoncdenombreusesmthodesetattributs.

LebutdecetouvragenestpasdereprendreentirementladocumentationduJDK,aussiilneprsentepastoutes lesmthodesdisponiblesmaissimplementlespluscourammentutilisesaufuretmesuredesbesoins.Ilpeuttre cependant intressant de parcourir la documentation avant de se lancer dans la conception dune mthode pour dterminersicequelonsouhaiteralisernapasdjtprvuparlesconcepteursdeJava. Maintenantquenoussommescapablesdafficherunefentre,leplusgrosdenotretravailvaconsisterajouterun contenulafentre.Avantdepouvoirajouterquelquechosesurunefentre,ilfautbiencomprendresastructure quiestrelativementcomplexe.UnobjetJFrameestcomposdeplusieurslmentssuperpossjouantchacununrle bienspcifiquedanslagestiondelafentre.

LlmentRootPanecorrespondauconteneurdestroisautreslments.LlmentLayeredPaneestluiresponsablede lagestiondelapositiondeslmentsaussibiensurlesaxesXetYquesurlaxeZcequipermetlasuperpositionde diffrents lments. Llment ContentPane est le conteneur de base de tous les lments ajouts sur la fentre. Cest bien sr lui que nous allons confier les diffrents composants de linterface de lapplication.Pardessous le ContentPane,sesuperposeleGlassPanecommeonlefaitavecunevitreplacesurunephoto.Ilprsentedailleurs beaucoupdesimilitudesaveclavitre.
q

Ilesttransparentpardfaut. CequiestdessinsurleGlassPanemasquelesautreslments. Il est capable dintercepter les vnements lis la souris avant que ceuxci natteignent les autres composants.

Detousceslments,cestincontestablementleContentPanequenousallonsleplusutiliser.Celuiciestaccessible par la mthode getContentPane de la classe JFrame. Il est techniquement possible de placer des composants directement sur lobjet ContentPane mais cest une pratique dconseille par Sun. Il est prfrable dintercaler un conteneur intermdiaire qui lui va contenir les composants et de placer ce conteneur sur le ContentPane. Le composantJPanelestlepluscourammentutilisdanscerle. Lescnarioclassiquedeconceptionduneinterfacegraphiqueconsistedonccrerlesdiffrentscomposantspuis les placer sur un conteneur et enfin placer ce conteneur sur le ContentPanedelafentre.Lexemple suivant met

- 2-

ENI Editions - All rigths reserved

celaenapplicationencrantuneinterfaceutilisateurcomposedetroisboutons. package fr.eni; import java.awt.Graphics; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Principale {

public static void main(String[] args) { // cration de la fentre JFrame fenetre; fenetre=new JFrame(); fenetre.setTitle("premire fentre en JAVA"); fenetre.setBounds(0,0,300,100); fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane fenetre.getContentPane().add(pano); // affichage de la fentre fenetre.setVisible(true); } } lexcution,cecodeaffichelafentresuivante :

Ltapesuivantedenotretudevanouspermettrededterminercequedoitfairelapplicationlorsquelutilisateurva cliquersurlundesboutons.

2.Lagestiondesvnements
Tous les systmes dexploitation utilisant une interface graphique doivent en permanence surveiller les diffrents priphriques de saisie pour dtecter les actions de lutilisateur et transmettre ces actions aux diffrentes applications.Pourchaqueactiondelutilisateur, un vnement est cr. Ces vnements sont ensuite proposs chaqueapplicationquidtermineensuitesielleestconcerneparlvnementetsicestlecas,quedoitellefaire pour y rpondre. La manire de grer ces vnements diffre suivant les langages. Dans certains cas, chaque composantdisposeduneportiondecodeprdfinieassocieautomatiquementchaquetypedvnement.Lerle du dveloppeur consiste dans ce cas personnaliser les diffrentes portions de code associes aux vnements. Dans dautres langages, les vnements sont simplement placs dans une file par le systme et cest alors le dveloppeurquidoitsurveillercettefilepourdterminerquelcomposantestconcernparlvnementetprovoquer lexcutiondelaportiondecodequilauraprvu.LadmarcheutiliseparJavaestunetechniqueintermdiaire.Java sechargededterminerquelvnementvientdeseproduireetsurquellment.Ledveloppeurestresponsable duchoixdelaportiondecodequivatraiterlvnement.Dunpointdevueplustechnique,llment loriginede

ENI Editions - All rigths reserved

- 3-

lvnementestappelsourcedvnementetllmentcontenantlaportiondecodechargedegrerlvnement est appele couteur dvnement. Les sources dvnements grent, pour chaque vnement quelles peuvent dclencher, une liste leur permettant de savoir quels couteurs doivent tre avertis si lvnementseproduit.Les sources dvnements et les couteurs dvnements sont bien entendu des objets. Il faut bien sr que les couteurs soient prvus pour grer les vnements que va leur transmettre la source dvnement. Pour garantir cela,chaquetypedvnementcorresponduneinterfacequedoitimplmenterunobjetsilveuttrecandidatpour lagestiondecetvnement.Pourviterlamultiplicationdesinterfaces(djtrsnombreuses),lesvnementssont regroupsparcatgories.Lenomdecesinterfacesrespectetoujourslaconventionsuivante : La premire partie du nom est reprsentative de la catgorie dvnements pouvant tre grs par les objets implmentantcetteinterface.LenomseterminetoujoursparListener. Nous avons par exemple linterface MouseMotionListener correspondant aux vnements dclenchs par les dplacementsdelasourisoulinterfaceActionListenercorrespondantunclicsurunbouton.Cestdanschacune decesinterfacesquenoustrouvonslessignaturesdesdiffrentesmthodesassocieschaquevnement. public interface MouseMotionListener extends EventListener { void mouseDragged(MouseEvent e) ; void mouseMoved(MouseEvent e) ; } Chacune des mthodes attend comme argument un objet reprsentant lvnement luimme. Cet objet est cr automatiquementlorsdudclenchementdelvnementpuispasscommeargumentlamthodechargedegrer lvnement dans lcouteur dvnement. Il contient gnralement des informations complmentaires concernant lvnementetilestspcifiquechaquetypedvnement. Nous avons donc besoin de crer des classes implmentant ces interfaces. De ce point de vue, nous avons une multitudedepossibilits:
q

Creruneclasse"normale"implmentantlinterface. Implmenterlinterfacedansuneclassedjexistante. Creruneclasseinterneimplmentantlinterface. Creruneclasseinterneanonymeimplmentantlinterface.

Dans certains cas, vous navez peuttre pas besoin de grer tous les vnements prsents dans linterface. Cependant vous tes tout de mme oblig dcrire toutes les mthodes exiges par linterface mme si plusieurs dentreellesnecontiennentaucuncode.Cecipeutnuirelalisibilitducode.Pourpallierceproblme,Javapropose pourpratiquementchaqueinterfaceXXXXXListeneruneclasseabstraitecorrespondanteimplmentantdjlinterface donccontenantlesmthodesexigesparlinterface.Cesmthodesnecontiennentaucuncodepuisqueletraitement de chaque vnement doit tre spcifique chaque application. Ces classes utilisent la mme convention de nommagequelesinterfaceshormislefaitqueListenerestremplacparAdapter.Nousavonsparexemplelaclasse MouseMotionAdapterimplmentantlinterfaceMouseMotionListener.Cesclassessontutilisablesdeplusieursfaons:
q

Creruneclasse"normale"hritantdunedecesclasses. Creruneclasseinternehritantdunedecesclasses. Creruneclasseinterneanonymehritantdunedecesclasses.

Lutilisation dune classe interne anonyme est la solution la plus frquemment utilise avec le petit inconvnient davoirunesyntaxedifficilementlisiblelorsquelonnyestpashabitue. Pour clarifier tout cela, nous allons illustrer chacune de ces possibilits par un petit exemple. Cet exemple va nous permettredeterminerproprementlapplicationlorsdelafermeturedelafentreprincipaleenappelantlamthode System.exit(0). Cettemthodedoittreappelelorsdeladtectiondelafermeturedelafentre.Pourcela,nousdevonsgrerles vnements lis la fentre et plus particulirement lvnement windowClosing qui est dclench au moment o lutilisateur demande la fermeture de la fentre par le menu systme. Linterface WindowListener est tout fait adaptepourcegenredetravail. Notrebasedetravailestconstituedesdeuxclassessuivantes : package fr.eni;
- 4 ENI Editions - All rigths reserved

import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame { public Ecran() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur sur le ContentPane getContentPane().add(pano); } }

package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } } Si nous excutons ce code, la fentre apparat mais il nest plus possible de la fermer et encore moins darrter lapplication.Voyonsmaintenantcommentremdierceproblmeaveclesdiffrentessolutionsvoquesplushaut. Utilisationduneclasse"normale"implmentantlinterface package fr.eni; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; public class EcouteurFenetre implements WindowListener { public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { System.exit(0); } public void windowDeactivated(WindowEvent arg0)
ENI Editions - All rigths reserved - 5-

{ } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } }

package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // cration dune instance de la classe charge // de grer les vnements EcouteurFenetre ef; ef=new EcouteurFenetre(); // rfrencement de cette instance de classe // comme couteur dvnement pour la fentre fenetre.addWindowListener(ef); // affichage de la fentre fenetre.setVisible(true); } } Implmenterlinterfacedansuneclassedjexistante Danscettesolution,nousallonsconfierlaclassereprsentantlafentrelesoindegrersespropresvnements enluifaisantimplmenterlinterfaceWindowListener. package fr.eni; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame implements WindowListener { public Ecran() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1);

- 6-

ENI Editions - All rigths reserved

pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // rfrencement de la fentre elle-mme // comme couteur de ses propres vnements addWindowListener(this); } public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { System.exit(0); } public void windowDeactivated(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } } package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } } Aveccettesolution,lecodeestcentralisdansuneseuleetuniqueclasse.Silyadenombreuxvnementsgrer, cetteclassevacomporterunemultitudedemthodes. Creruneclasseinterneimplmentantlinterface Cettesolutionestunmlangedesdeuxprcdentespuisquenousavonsuneclassespcifiquepourlagestiondes vnementsmaiscelleciestdfinielintrieurdelaclassecorrespondantlafentre. package fr.eni; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame { public Ecran()

ENI Editions - All rigths reserved

- 7-

{ setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance de la classe charge // de grer les vnements EcouteurFenetre ef; ef=new EcouteurFenetre(); // rfrencement de cette instance de classe // comme couteur dvnement pour la fentre addWindowListener(ef); } public class EcouteurFenetre implements WindowListener { public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { System.exit(0); } public void windowDeactivated(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } } } package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } }

- 8-

ENI Editions - All rigths reserved

Aveccettesolutionlesresponsabilitssontbienrpartiesentreplusieursclasses,parcontrenousallonsavoirune multiplicationdunombredeclasses. Creruneclasseinterneanonymeimplmentantlinterface Cettesolutionestunepetitevariantedelaprcdentepuisquenousavonstoujoursuneclassespcifiquecharge delagestiondesvnementsmaiscelleciestdclareaumomentdesoninstanciation. package fr.eni; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame { public Ecran() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowListener() // dbut de la dfinition de la classe { public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { System.exit(0); } public void windowDeactivated(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } } // fin de la dfinition de la classe ); // fin de lappel de la mthode addWindowListener }// fin du constructeur

ENI Editions - All rigths reserved

- 9-

}// fin de la classe Ecran package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } } Le seul reproche que lon puisse faire cette solution rside dans la relative complexit de la syntaxe. Les commentairesplacssurlesdiffrenteslignesfournissentuneaideprcieusepoursyretrouverdanslesaccolades etparenthses. Parcontre,ilyaunreprochequelonpeutfairedemanireglobaletoutescessolutions.Pouruneseulemthode rellementutile,noussommesobligsdencriresept. Pour viter ce code inutile, nous pouvons travailler avec une classe implmentant dj la bonne interface et simplementredfiniruniquementlesmthodesnousintressant. Creruneclasse"normale"hritantduneclasseXXXXAdapter package fr.eni; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class Ecouteurfenetre extends WindowAdapter { public void windowClosing(WindowEvent arg0) { System.exit(0); } }

package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // cration dune instance de la classe charge // de grer les vnements EcouteurFenetre ef; ef=new EcouteurFenetre(); // rfrencement de cette instance de classe // comme couteur dvnement pour la fentre fenetre.addWindowListener(ef); // affichage de la fentre fenetre.setVisible(true); } } CreruneclasseinternehritantduneclasseXXXXAdapter package fr.eni;

- 10 -

ENI Editions - All rigths reserved

import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame { public Ecran() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance de la classe charge // de grer les vnements EcouteurFenetre ef; ef=new EcouteurFenetre(); // rfrencement de cette instance de classe // comme couteur dvnement pour la fentre addWindowListener(ef); } public class Ecouteurfenetre extends WindowAdapter { public void windowClosing(WindowEvent arg0) { System.exit(0); } } } package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } } CreruneclasseinterneanonymehritantduneclasseXXXXAdapter package fr.eni; import java.awt.event.WindowEvent;
ENI Editions - All rigths reserved - 11 -

import java.awt.event.WindowListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Ecran extends JFrame { public Ecran() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton b1,b2,b3; b1=new JButton("Rouge"); b2=new JButton("Vert"); b3=new JButton("Bleu"); // cration du conteneur intermdiaire JPanel pano; pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(b1); pano.add(b2); pano.add(b3); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowAdapter() // dbut de la dfinition de la classe { public void windowClosing(WindowEvent arg0) { System.exit(0); } } // fin de la dfinition de la classe ); // fin de lappel de la mthode addWindowListener }// fin du constructeur }// fin de la classe Ecran package fr.eni; public class Principale { public static void main(String[] args) { // cration de la fentre Ecran fenetre; fenetre=new Ecran(); // affichage de la fentre fenetre.setVisible(true); } } Cettesolutionestbiensrlaplusconomeennombredelignesetcestcellequiestutilisepardenombreuxoutils dedveloppementgnrantautomatiquementducode.Larelativecomplexitducodepeutparfoistretroublante lorsquelonnyestpashabitu. Jusquprsent,nousavonsunesourcedvnementetuncouteurpourcettesourcedvnement.Nouspouvons avoir dans certains cas la situation o nous avons plusieurs sources dvnements et souhaiter utiliser le mme couteur ou avoir une source dvnement et prvenir plusieurs couteurs. La situation classique o nous avons plusieurs sources dvnements et un seul couteur se produit lorsque nous fournissons lutilisateur plusieurs solutions pour lancer lexcution dune mme action (menu et barre doutils ou boutons). Quel que soit le moyen utilispourlancerlaction,lecodeexcuterrestelemme.Nouspouvonsdanscecasdefigureutiliserlemme couteurpourlesdeuxsourcesdvnements.Pourillustrercela,nousallonsajouterunmenulapplicationetfaire en sorte que lutilisation du menu ou dun des boutons lance la mme action en modifiant la couleur de fond correspondante au bouton ou au menu utilis. Comme nous devons utiliser le mme couteur pour deux sources

- 12 -

ENI Editions - All rigths reserved

dvnements il est prfrable dutiliser une classe interne pour la cration de lcouteur. Voici cidessous le code correspondant. package fr.eni; import import import import import import import import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JButton; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel;

public class Ecran extends JFrame { JPanel pano; public Ecran () { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons JButton btnRouge,btnVert,btnBleu; btnRouge=new JButton("Rouge"); btnVert=new JButton("Vert"); btnBleu=new JButton("Bleu"); // cration des trois couteurs EcouteurRouge ecR; EcouteurVert ecV; EcouteurBleu ecB; ecR=new EcouteurRouge(); ecV=new EcouteurVert(); ecB=new EcouteurBleu(); // association de lcouteur chaque bouton btnRouge.addActionListener(ecR); btnVert.addActionListener(ecV); btnBleu.addActionListener(ecB); // Cration du menu JMenuBar barreMenu; barreMenu=new JMenuBar(); JMenu mnuCouleurs; mnuCouleurs=new JMenu("Couleurs"); barreMenu.add(mnuCouleurs); JMenuItem mnuRouge,mnuVert,mnuBleu; mnuRouge=new JMenuItem("Rouge"); mnuVert=new JMenuItem("Vert"); mnuBleu=new JMenuItem("Bleu"); mnuCouleurs.add(mnuRouge); mnuCouleurs.add(mnuVert); mnuCouleurs.add(mnuBleu); // association de lcouteur chaque menu // ( les mmes que pour les boutons ) mnuRouge.addActionListener(ecR); mnuVert.addActionListener(ecV); mnuBleu.addActionListener(ecB); // ajout du menu sur la fentre setJMenuBar(barreMenu); // cration du conteneur intermdiaire pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(btnRouge); pano.add(btnVert); pano.add(btnBleu); // ajout du conteneur intermdiaire sur le ContentPane

ENI Editions - All rigths reserved

- 13 -

getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements de la fentre addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { System.exit(0); } } ); } public class EcouteurRouge implements ActionListener { public void actionPerformed(ActionEvent arg0) { pano.setBackground(Color.RED); } } public class EcouteurVert implements ActionListener { public void actionPerformed(ActionEvent arg0) { pano.setBackground(Color.GREEN); } } public class EcouteurBleu implements ActionListener { public void actionPerformed(ActionEvent arg0) { pano.setBackground(Color.BLUE); } } } Dans ce code, nous avons nos trois classes couteur qui sont trs similaires. Avec une petite astuce, nous allons pouvoirsimplifierlecodepournavoir plus quune seule classe couteur pour les trois boutons. La mme mthode actionPerformedseraappelesuiteunclicsurnimportelequeldesboutons.Lechoixdelactionexcutersera fait lintrieurdecettemthode.Pourcela,nousallonsutiliserleparamtreActionEvent fourni cette mthode. Celuici permet dobtenir une rfrence sur objet lorigine de lvnement par lintermdiaire de la mthode getSource.Lecodesimplifiestprsentcidessous: package fr.eni; import import import import import import import import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JButton; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel;

public class Ecran extends JFrame { JPanel pano; JButton btnRouge,btnVert,btnBleu; JMenuItem mnuRouge,mnuVert,mnuBleu; public Ecran () { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons

- 14 -

ENI Editions - All rigths reserved

btnRouge=new JButton("Rouge"); btnVert=new JButton("Vert"); btnBleu=new JButton("Bleu"); // cration des trois couteurs EcouteurCouleur ec; ec=new EcouteurCouleur(); // association de lcouteur chaque bouton btnRouge.addActionListener(ec); btnVert.addActionListener(ec); btnBleu.addActionListener(ec); // Cration du menu JMenuBar barreMenu; barreMenu=new JMenuBar(); JMenu mnuCouleurs; mnuCouleurs=new JMenu("Couleurs"); barreMenu.add(mnuCouleurs); mnuRouge=new JMenuItem("Rouge"); mnuVert=new JMenuItem("Vert"); mnuBleu=new JMenuItem("Bleu"); mnuCouleurs.add(mnuRouge); mnuCouleurs.add(mnuVert); mnuCouleurs.add(mnuBleu); // association de lcouteur chaque menu // ( le mme que pour les boutons ) mnuRouge.addActionListener(ec); mnuVert.addActionListener(ec); mnuBleu.addActionListener(ec); // ajout du menu sur la fentre setJMenuBar(barreMenu); // cration du conteneur intermdiaire pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(btnRouge); pano.add(btnVert); pano.add(btnBleu); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { System.exit(0); } } ); } public class EcouteurCouleur implements ActionListener { public void actionPerformed(ActionEvent arg0) { if (arg0.getSource()==btnRouge | arg0.getSource()==mnuRouge) { pano.setBackground(Color.RED); } if (arg0.getSource()==btnVert | arg0.getSource()==mnuVert) { pano.setBackground(Color.GREEN); } if (arg0.getSource()==btnBleu | arg0.getSource()==mnuBleu) { pano.setBackground(Color.BLUE); } } } }

ENI Editions - All rigths reserved

- 15 -

noter que pour que cette solution puisse fonctionner, les objets source dvnements doivent tre accessibles depuislaclassecouteurdvnements.Ladclarationdesboutonsetdeslmentsdemenuadonctdplace auniveaudelaclasseellemmeetnonplusdansleconstructeurcommectaitlecasdanslaversionprcdente. Cettesolutionestpossibleuniquementsilaclassecouteurestuneclasseinterne.Danslecasolaclassecouteur estparfaitementindpendantedelaclasseosontcrslesobjetssourcedvnement,ilfautrevoirlecodedela mthodeactionPerformed.LeparamtreActionEventdelamthodeactionPerformednousfournituneautresolution pourcontournerceproblme.ParlintermdiairedelamthodegetActionCommandnousavonsaccsunechanede caractresreprsentantlobjetloriginedelvnement.Pardfautcettechanedecaractrescorrespondaulibell ducomposantayantdclenchlvnementmaisellepeuttremodifieparlamthodesetActionCommanddechaque composant.Cest dailleursunepratiquerecommandepuisquellenouspermetdavoiruncodeidentiquepourune applicationfonctionnantenplusieurslangues.Voicilesmodificationscorrespondantes. package fr.eni; import import import import import import import import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JButton; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel;

public class Ecran extends JFrame { JPanel pano; JButton btnRouge,btnVert,btnBleu; JMenuItem mnuRouge,mnuVert,mnuBleu;

public Ecran () { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons btnRouge=new JButton("Rouge"); btnRouge.setActionCommand("red"); btnVert=new JButton("Vert"); btnVert.setActionCommand("green"); btnBleu=new JButton("Bleu"); btnBleu.setActionCommand("blue"); // cration des trois couteurs EcouteurCouleur ec; ec=new EcouteurCouleur(); // association de lcouteur chaque bouton btnRouge.addActionListener(ec); btnVert.addActionListener(ec); btnBleu.addActionListener(ec); // Cration du menu JMenuBar barreMenu; barreMenu=new JMenuBar(); JMenu mnuCouleurs; mnuCouleurs=new JMenu("Couleurs"); barreMenu.add(mnuCouleurs); mnuRouge=new JMenuItem("Rouge"); mnuRouge.setActionCommand("red"); mnuVert=new JMenuItem("Vert"); mnuVert.setActionCommand("green"); mnuBleu=new JMenuItem("Bleu"); mnuBleu.setActionCommand("blue"); mnuCouleurs.add(mnuRouge); mnuCouleurs.add(mnuVert); mnuCouleurs.add(mnuBleu); // association de lcouteur chaque menu

- 16 -

ENI Editions - All rigths reserved

// ( le mme que pour les boutons ) mnuRouge.addActionListener(ec); mnuVert.addActionListener(ec); mnuBleu.addActionListener(ec); // ajout du menu sur la fentre setJMenuBar(barreMenu); // cration du conteneur intermdiaire pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(btnRouge); pano.add(btnVert); pano.add(btnBleu); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { System.exit(0); } } ); } public class EcouteurCouleur implements ActionListener { public void actionPerformed(ActionEvent arg0) { String commande; commande=arg0.getActionCommand(); if (commande.equals("red")) { pano.setBackground(Color.RED); } if (commande.equals("green")) { pano.setBackground(Color.GREEN); } if (commande.equals("blue")) { pano.setBackground(Color.BLUE); } } } } noterquedanscettesolution,ladclarationdesboutonsetdeslmentsdemenupeuttrerintgredansle constructeurpuisquenousnenavonsplusbesoinauniveaudelaclasse. La dernire tape de notre marathon sur les vnements va nous permettre davoir plusieurs couteurs pour une mme source dvnements et ventuellement supprimer un couteur existant. Pour cela, nous allons crer une nouvelleclassecouteurquivanouspermettredaffichersurlaconsoleladateetheuredelvnementetlobjet loriginedelvnement. package fr.eni; import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; java.text.SimpleDateFormat; java.util.Date;

import javax.swing.AbstractButton; import javax.swing.JButton; import javax.swing.JMenuItem; public class ConsoleLog implements ActionListener { public void actionPerformed(ActionEvent e)

ENI Editions - All rigths reserved

- 17 -

{ String message; SimpleDateFormat sdf; sdf=new SimpleDateFormat("dd/MM/yyyy hh:mm:ss"); message=sdf.format(new Date()); message=message + " clic sur le "; if (e.getSource() instanceof JButton) { message=message+ "bouton "; } if (e.getSource() instanceof JMenuItem) { message=message+ "menu "; } message=message + ((AbstractButton)e.getSource()).getText(); System.out.println(message); } } Dans notre application, nous ajoutons ensuite une case cocher permettant de choisir si les vnements sont affichs sur la console. En fonction de ltat de cette case cocher nous ajoutons, avec la mthode addActionListener,ousupprimons,aveclamthoderemoveActionListener,uncouteurauxboutonsetmenus.Ces deuxmthodesattendentcommeargumentlinstancedelcouteurajouterousupprimer. package fr.eni; import import import import import import import import import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JButton; javax.swing.JCheckBox; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel;

public class Ecran extends JFrame { JPanel pano; JButton btnRouge,btnVert,btnBleu; JMenuItem mnuRouge,mnuVert,mnuBleu; ConsoleLog lg; public Ecran () { setTitle("premiere fenetre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons btnRouge=new JButton("Rouge"); btnRouge.setActionCommand("red"); btnVert=new JButton("Vert"); btnVert.setActionCommand("green"); btnBleu=new JButton("Bleu"); btnBleu.setActionCommand("blue"); // cration des trois couteurs EcouteurCouleur ec; ec=new EcouteurCouleur(); // association de lcouteur chaque bouton btnRouge.addActionListener(ec); btnVert.addActionListener(ec); btnBleu.addActionListener(ec); // cration de la case cocher JCheckBox chkLog; chkLog=new JCheckBox("log sur console");

- 18 -

ENI Editions - All rigths reserved

// ajout dun couteur la case cocher chkLog.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { JCheckBox chk; chk=(JCheckBox)arg0.getSource(); if (chk.isSelected()) { // ajout dun couteur supplmentaire // aux boutons et menus lg=new ConsoleLog(); btnBleu.addActionListener(lg); btnRouge.addActionListener(lg); btnVert.addActionListener(lg); mnuBleu.addActionListener(lg); mnuRouge.addActionListener(lg); mnuVert.addActionListener(lg); } else { // suppression de lcouteur supplmentaire // des boutons et menus btnBleu.removeActionListener(lg); btnRouge.removeActionListener(lg); btnVert.removeActionListener(lg); mnuBleu.removeActionListener(lg); mnuRouge.removeActionListener(lg); mnuVert.removeActionListener(lg); } } }); // Cration du menu JMenuBar barreMenu; barreMenu=new JMenuBar(); JMenu mnuCouleurs; mnuCouleurs=new JMenu("Couleurs"); barreMenu.add(mnuCouleurs); mnuRouge=new JMenuItem("Rouge"); mnuRouge.setActionCommand("red"); mnuVert=new JMenuItem("Vert"); mnuVert.setActionCommand("green"); mnuBleu=new JMenuItem("Bleu"); mnuBleu.setActionCommand("blue"); mnuCouleurs.add(mnuRouge); mnuCouleurs.add(mnuVert); mnuCouleurs.add(mnuBleu); // association de lcouteur chaque menu // ( le mme que pour les boutons ) mnuRouge.addActionListener(ec); mnuVert.addActionListener(ec); mnuBleu.addActionListener(ec); // ajout du menu sur la fentre setJMenuBar(barreMenu); // cration du conteneur intermdiaire pano=new JPanel(); // ajout des boutons sur le conteneur intermdiaire pano.add(btnRouge); pano.add(btnVert); pano.add(btnBleu); pano.add(chkLog); // ajout du conteneur intermdiaire sur le ContentPane getContentPane().add(pano); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0)

ENI Editions - All rigths reserved

- 19 -

{ System.exit(0); } } ); } public class EcouteurCouleur implements ActionListener { public void actionPerformed(ActionEvent arg0) { String commande; commande=arg0.getActionCommand(); if (commande.equals("red")) { pano.setBackground(Color.RED); } if (commande.equals("green")) { pano.setBackground(Color.GREEN); } if (commande.equals("blue")) { pano.setBackground(Color.BLUE); } } } } lexcutionetsuivantltatdelacasecocher,nousvoyonsapparatrelesmessagessuivantssurlaconsole. 27/11/2008 27/11/2008 27/11/2008 27/11/2008 27/11/2008 27/11/2008 09:19:43 09:19:45 09:19:47 09:19:51 09:19:54 09:19:56 clic clic clic clic clic clic sur sur sur sur sur sur le le le le le le bouton Rouge bouton Vert bouton Bleu menu Rouge menu Vert menu Bleu

noter que, indpendamment de laffichage de ces messages, la couleur de la fentre change toujours lors de lutilisationdesboutonsoumenus. Touscesprincipesdegestionsontidentiquesquelsquesoientlesvnementsetlesobjetslesdclenchant.Leseul problmequevouspourrezrencontreraudbutcestdesavoirquelssontlesvnementsdisponiblespourunobjet particulier. ce niveau, seule la documentation Java va pouvoir vous venir en aide. Une petite astuce consiste chercherdanslaclassecorrespondantlobjetconcern,lesmthodesnommesaddXXXXXListenerpuispartirde cette mthode remonter jusqu linterface correspondante et dcouvrir, grce aux mthodes dfinies dans linterface, les diffrents vnements possibles. Lanalyse du type dargument reu dans les diffrentes mthodes vouspermettradesavoirquellesinformationssupplmentairessontdisponiblespourunvnementparticulier.Par exemple,vousavezreprlamthodeaddMouseListener.

Vouspouvezdjdterminerquecettemthodevavouspermettretravailleravecdesvnementslislasouris. PouravoirplusdinformationssurlesdiffrentsvnementsvousdevezallervoirlinterfaceMouseListener.

- 20 -

ENI Editions - All rigths reserved

La documentation de cette interface vous apprend que cinq mthodes sont prvues donc que cinq types dvnements sont disponibles et dans quelles circonstances ils sont dclenchs. Pour savoir quelles informations seront disponibles lors du dclenchement dun de ces vnements, vous poursuivez votre priple vers la classe correspondantautypedesargumentsreusparcesmthodes.

Vouspensezcertainementquetoutceciestfastidieuxmaisvousallezrapidementvousrendrecomptequecesont pratiquementtoujourslesmmesvnementsdontonabesoinetvousalleztrsrapidementlesconnatreparc ur.

3.Lepositionnementdescomposants
Sivousavezdjutilisunautrelangagedeprogrammationpermettantdedvelopperdesinterfacesgraphiques, unechosedoitvousparatretrangedanslesexemplesdecodequenousavonsutiliss.
q

Nullepart,nousnavonsindiqulatailleetlapositiondescomposantsutiliss. Sivousredimensionnezlafentredelapplication,lescomposantschangentdeplace.

Etpourtantaucunelignedecodenestprvuepoureffectuercetraitement.Cepetitmiracleestliunconcepttrs pratiquedejava :lesgestionnairesdemiseenpage(layoutmanager).Enfaitlorsquevousconfiezdescomposants un conteneur, celuici dlgue son gestionnaire de mise en page le soin dorganiser la disposition des composants sur sa surface. De nombreux types de gestionnaire de mise en page sont disponibles, chacun deux ayant une stratgie diffrente pour le placement des composants. Chaque type de conteneur dispose dun gestionnairedemiseenpagepardfaut,diffrentenfonctiondutypedeconteneur.Sicegestionnairepardfautne vousconvientpas,vousteslibredeleremplacerparunautreenappelantlamthodesetLayoutetenfournissant cettemthodelenouveaugestionnaireutiliserparceconteneur. Pourpouvoirtravailleretorganiserladispositiondescomposants,legestionnairedemiseenpagedoitconnatrela tailledechaquecomposant.Lameilleurefaondobtenircetteinformationestdesadresseraucomposantluimme. Pour cela, le gestionnaire de mise en page questionne chaque composant en appelant sa mthode getPreferredSize.Cettemthodecalculelatailleducomposantenfonctiondesoncontenu,parexemplelalongueur

ENI Editions - All rigths reserved

- 21 -

dulibellpourunbouton.Pourcourtcircuitercecalcul,vouspouvezfixerunetaillepardfautchaquecomposant aveclamthodesetPreferedSize. La russite de la conception dune interface utilisateur ncessite donc de bien connatre comment fonctionnent les diffrentsgestionnairesdemiseenpage.Nousallonsdonctudierlescaractristiquesdesplusutilissdentreeux.

a.FlowLayout
Cegestionnairedemiseenpageestcertainementleplussimpleutiliser.Ilestassocipardfautuncomposant JPanel.Sastratgiedeplacementdescomposantsconsistelesplacerlesunslasuitedesautressuruneligne jusqu ce quil ny ait plus de place sur cette ligne. Aprs le remplissage de la premire ligne, les composants suivantssontplacssurunenouvelleligneetainsidesuite.Cestlordredajoutdescomposantssurleconteneur qui dtermine leurs positions sur les diffrentes lignes. Chaque composant est spar horizontalement de son voisin par un espace de cinq pixels par dfaut et chaque ligne de composants est spare de sa voisine par un espacedecinqpixelspardfautgalement.Lorsquecegestionnaireplacelescomposants,illesalignepardfaut surlecentreduconteneur.Touscesparamtrespeuventtremodifispourchaquegestionnairedemiseenpage FlowLayout.VouspouvezlefairedslacrationduFlowLayoutenindiquantdansleconstructeurlesinformations correspondantes. Trois constructeurs sont disponibles pour cette classe. Le premier nattend aucun argument et creunFlowLayoutaveclescaractristiquespardfautdcritescidessus.Ledeuximeattendcommeargument unedesconstantessuivantespermettantdespcifierletypedalignementutilis.
q

FlowLayout.CENTER:chaquelignedecomposantestcentredansleconteneur(valeurpardfaut). FlowLayout.LEFT:chaquelignedecomposantestalignesurlagaucheduconteneur. FlowLayout.RIGHT :chaquelignedecomposantestalignesurladroiteduconteneur.

Le dernier constructeur disponible attend comme arguments deux entiers en plus de la constante indiquant lalignement.Cesdeuxentiersindiquentlespacementhorizontaletverticalentrelescomposants.Lalignedecode suivante cre un FlowLayout qui aligne les lignes de composants sur le centre du conteneur, laisse un espace horizontaldecinquantepixelsetunespaceverticaldevingtpixelsentrelescomposants. fl=new FlowLayout(FlowLayout.LEFT,50,20); SivousnecrezpasvousmmedeFlowLayoutmaisquevousutilisezceluifournipardfautavecunJpanel,vous pouvezintervenirsurcesparamtresdefonctionnementaveclesmthodessuivantes :
q

setAlignment :pourspcifierlalignementdescomposants. setHgap :pourspcifierlespacementhorizontalentrelescomposants. setVgap :pourspcifierlespacementverticalentrelescomposants.

Ilestdanscecasncessairedobtenirunerfrencesurle FlowLayoutassociauJPanelenutilisantlamthode getLayoutdeceluici.Uneoprationdetranstypageestdanscecasobligatoirepourpouvoirutiliserlesmthodes delaclasseFlowLayoutsurlarfrenceobtenue. ((FlowLayout)pano.getLayout()).setAlignment(FlowLayout.LEFT); ((FlowLayout)pano.getLayout()).setHgap(50); ((FlowLayout)pano.getLayout()).setVgap(20);

b.BorderLayout
Cegestionnairedemiseenpagedcoupelasurfacequiluiestconfieencinqzonessuivantleschmacidessous.

- 22 -

ENI Editions - All rigths reserved

Lorsquun composant est confi un BorderLayout, il convient dindiquer dans quelle zone celui doit tre plac. Cetteindicationestfourniecommedeuximeargumentdelamthode add,lepremierargumenttanttoujoursle composant insrer sur le conteneur. Les constantes suivantes sont disponibles pour identifier une zone du BorderLayout.

Si aucune information nest indique pour identifier une zone lors de lajout dun composant celuici est systmatiquementplacdanslazoneCentre. LeBorderLayoutnaimepaslevideetdecefaitilredimensionneautomatiquementtouslescomposantsquevous luiconfiezpouroccupertoutlespacedisponible.Lorsqueleconteneurestredimensionn,lescomposantsplacsen bordurenechangentpasdelargeurpourleszonesOuestetEst,dehauteurpourleszonesNordetSud.Lespace estdoncgagnouperduparlazoneCentre.ChaquezoneduBorderLayoutnepeutcontenirquunseulcomposant. SiplusieurscomposantssontmalgrtoutajoutsunemmezonedunBorderLayout,seulledernierajoutsera prisenchargeparleBorderLayout,lesautresneserontpasvisibles. Du fait de cette limitation, le BorderLayout est gnralement utilis pour positionner des conteneurs les uns par rapportauxautrespluttquedescomposantsisols. LeBorderLayoutestlegestionnairedemiseenpagepardfautdellmentContentPaneduneJFrame.Lutilisation classique consiste placer dans la zone Nord la ou les barres doutils, dans la zone Sud la barre dtat de lapplicationetdanslazoneCentreledocumentsurlequellutilisateurdoittravailler.CommepourleFlowLayout il est possible dindiquer auBorderLayout quil doit mnager un espace vertical ou horizontal entre ces diffrentes zones.CecipeuttrefaitlacrationduBorderlayoutenindiquantlespacehorizontaletverticaldanslappeldu constructeur ou, si vous utilisez un BorderLayout existant, en appelant les mthodes setHgap et setVgap du BorderLayout.Pourillustrertoutcela,nousallonsremanierlinterface de notre application en plaant les boutons danslazoneNord,lacasecocherdanslazoneSudetenmodifiantlacouleurdelazoneCentrelorsduclicsurles boutonsoumenus. package fr.eni;

ENI Editions - All rigths reserved

- 23 -

import import import import import import import import import import import import import import

java.awt.BorderLayout; java.awt.Color; java.awt.FlowLayout; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; javax.swing.JButton; javax.swing.JCheckBox; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel;

public class Ecran9 extends JFrame { JPanel panoBoutons; JPanel panoChk; JPanel panoCouleur; JButton btnRouge,btnVert,btnBleu; JMenuItem mnuRouge,mnuVert,mnuBleu; ConsoleLog lg; public Ecran9() { setTitle("premire fentre en JAVA"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // cration des trois boutons btnRouge=new JButton("Rouge"); btnRouge.setActionCommand("red"); btnVert=new JButton("Vert"); btnVert.setActionCommand("green"); btnBleu=new JButton("Bleu"); btnBleu.setActionCommand("blue"); // cration des trois couteurs EcouteurCouleur ec; ec=new EcouteurCouleur(); // association de lcouteur chaque bouton btnRouge.addActionListener(ec); btnVert.addActionListener(ec); btnBleu.addActionListener(ec); // cration de la case cocher JCheckBox chkLog; chkLog=new JCheckBox("log sur console"); // ajout dun couteur la case cocher chkLog.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { JCheckBox chk; chk=(JCheckBox)arg0.getSource(); if (chk.isSelected()) { // ajout dun couteur supplmentaire // aux boutons et menus lg=new ConsoleLog(); btnBleu.addActionListener(lg); btnRouge.addActionListener(lg); btnVert.addActionListener(lg); mnuBleu.addActionListener(lg); mnuRouge.addActionListener(lg); mnuVert.addActionListener(lg); } else { // suppression de lcouteur supplmentaire

- 24 -

ENI Editions - All rigths reserved

// des boutons et menus btnBleu.removeActionListener(lg); btnRouge.removeActionListener(lg); btnVert.removeActionListener(lg); mnuBleu.removeActionListener(lg); mnuRouge.removeActionListener(lg); mnuVert.removeActionListener(lg); } } }); // Cration du menu JMenuBar barreMenu; barreMenu=new JMenuBar(); JMenu mnuCouleurs; mnuCouleurs=new JMenu("Couleurs"); barreMenu.add(mnuCouleurs); mnuRouge=new JMenuItem("Rouge"); mnuRouge.setActionCommand("red"); mnuVert=new JMenuItem("Vert"); mnuVert.setActionCommand("green"); mnuBleu=new JMenuItem("Bleu"); mnuBleu.setActionCommand("blue"); mnuCouleurs.add(mnuRouge); mnuCouleurs.add(mnuVert); mnuCouleurs.add(mnuBleu); // association de lcouteur chaque menu // ( le mme que pour les boutons ) mnuRouge.addActionListener(ec); mnuVert.addActionListener(ec); mnuBleu.addActionListener(ec); // ajout du menu sur la fentre setJMenuBar(barreMenu); // cration du conteneur intermdiaire panoBoutons=new JPanel(); // ajout des boutons sur le conteneur intermdiaire panoBoutons.add(btnRouge); panoBoutons.add(btnVert); panoBoutons.add(btnBleu); // ajout du conteneur intermdiaire sur le ContentPane zone nord getContentPane().add(panoBoutons,BorderLayout.NORTH); // cration du conteneur pour la case cocher panoChk=new JPanel(); panoChk.add(chkLog); // ajout du conteneur dans la zone sud getContentPane().add(panoChk,BorderLayout.SOUTH); // cration du conteneur pour affichage de la couleur panoCouleur=new JPanel(); // ajout du conteneur dans la zone centre getContentPane().add(panoCouleur,BorderLayout.CENTER); // cration dune instance dune classe anonyme // charge de grer les vnements addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { System.exit(0); } } ); ((FlowLayout)panoBoutons.getLayout()).setAlignment (FlowLayout.LEFT); ((FlowLayout)panoBoutons.getLayout()).setHgap(50); ((FlowLayout)panoBoutons.getLayout()).setVgap(20); } public class EcouteurCouleur implements ActionListener { public void actionPerformed(ActionEvent arg0) {

ENI Editions - All rigths reserved

- 25 -

String commande; commande=arg0.getActionCommand(); if (commande.equals("red")) { panoCouleur.setBackground(Color.RED); } if (commande.equals("green")) { panoCouleur.setBackground(Color.GREEN); } if (commande.equals("blue")) { panoCouleur.setBackground(Color.BLUE); } } } } Notrefentreprsentemaintenantladispositionsuivante:

c.GridLayout
Cegestionnairedemiseenpagedcoupelasurfacequiluiestconfiesousformedunegrilleinvisible.Lenombre de lignes et de colonnes doit tre indiqu dans lappel du constructeur. Lorsque ce gestionnaire place les composants quon lui confie, il commence par remplir toutes les cases de la premire ligne puis passe la ligne suivante et ainsi de suite. Toutes les cases ont une taille identique et leurs contenus sont donc redimensionns pour occuper tout lespace disponible de chaque case. Par dfaut les composants sont placs cte cte. Un espace vertical et horizontal peut tre insr entre chaque composant en spcifiant deux arguments supplmentaires lors de lappel du constructeur. Ces deux arguments indiquent lespacement horizontal et lespacementvertical.CesespacementspeuventgalementtremodifisaveclesmthodessetHgapetsetVgap. SivousinsrezplusdecomposantsquilyadecasesdansleGridLayout,celuicicredescasessupplmentaires en augmentant le nombre de colonnes et en respectant le nombre de lignes dorigine. Par exemple avec le code suivant,nousprvoyonsunegrillede2x2casesmaisnousajoutonssixcomposants. JPanel grille; grille=new JPanel(); GridLayout grl; grl=new GridLayout(2,2); grille.setLayout(grl); grille.add(new JButton("1")); grille.add(new JButton("2"));

- 26 -

ENI Editions - All rigths reserved

grille.add(new JButton("3")); grille.add(new JButton("4")); grille.add(new JButton("5")); grille.add(new JButton("6")); pano.add(grille); Lescomposantssontdispossselonleschmasuivant :

SivoussouhaitezqueleGridLayoutrespectelenombredecolonnes,vousdevezindiquerquelenombredelignes vousestindiffrentenspcifiantlavaleur0pourcetargumentdansleconstructeur.Danscecas,legestionnairede miseenpageajoutedeslignessupplmentairespourlescomposantsensurplus. JPanel grille; grille=new JPanel(); GridLayout grl; grl=new GridLayout(0,2); grille.setLayout(grl); grille.add(new JButton("1")); grille.add(new JButton("2")); grille.add(new JButton("3")); grille.add(new JButton("4")); grille.add(new JButton("5")); grille.add(new JButton("6")); pano.add(grille);

d.BoxLayout
Cegestionnaireestutilislorsquelonabesoindeplacerdescomposantssuruneligneouunecolonne.Bienque lonpuisseobtenirlemmersultatavecunGridLayoutduneseuleligneouduneseulecolonne,cegestionnaire procureplusdefonctionnalits.Leprixpayerpourcesfonctionnalitssupplmentairesestunerelativecomplexit dutilisation.LeconstructeurdelaclasseBoxLayoutattendcommepremierargumentleconteneurdontilvagrerle contenuetcommedeuximeargumentuneconstanteindiquantsiceconteneurgreuneligne(BoxLayout.X_AXIS) ouunecolonne(BoxLayout.Y_AXIS). Bien que lonfournisseunerfrencesurleconteneurlorsdelacrationdegestionnairedemiseenpage,ilest toutdemmeobligatoiredassocierlegestionnaireauconteneuraveclamthodesetLayoutcommenouslavons djfaitaveclesautresgestionnaires. tudions maintenant la stratgie de fonctionnement de ce gestionnaire. Nous allons prendre le cas dun gestionnairehorizontal.
q

Legestionnairerecherchelecomposantleplushaut.

ENI Editions - All rigths reserved

- 27 -

Iltentedagrandirlesautrescomposantsjusqucettehauteur. Siuncomposantnepeutpasatteindrecettehauteur,ilestalignverticalementsurlesautrescomposants enfonctiondelavaleurrenvoyeparlamthodegetAlignementYducomposant.


q

0pourunalignementsurlehautdesautrescomposants. 1pourunalignementsurlebasdesautrescomposants. 0.5pouruncentragesurlesautrescomposants.

Leslargeursprfresdechaquecomposantsontadditionnes. Si la somme est infrieure la largeur du conteneur, les composants sont agrandis jusqu leur largeur maximale. Si la somme est suprieure la largeur du conteneur, les composants sont rduits jusqu leur largeur minimale.Sicenestpassuffisant,lesdernierscomposantsneserontpasaffichs. Lescomposantssontensuiteplacssurleconteneurdegauchedroitesansespacedesparation.

Lefonctionnementesttoutfaitsimilairepourungestionnairevertical. JPanel ligne; ligne=new JPanel(); BoxLayout bl; bl=new BoxLayout(ligne,BoxLayout.X_AXIS); ligne.setLayout(bl); JButton b1,b2,b3,b4,b5; // cration dun bouton avec alignement sur le haut b1=new JButton("petit"); b1.setAlignmentY(0); ligne.add(b1); // cration dun bouton avec alignement sur le bas b2=new JButton(" moyen "); b2.setAlignmentY(1); ligne.add(b2); // utilisation de html pour le libell du bouton b3=new JButton("<html>trs<BR>haut</html>"); ligne.add(b3); b4=new JButton(" trs large "); ligne.add(b4); b5=new JButton("<html>trs haut<br>et<br>trs large</html>"); ligne.add(b5); getContentPane().add(ligne); Cecodenousdonnelinterfaceutilisateursuivante.

PardfautilnyapasdespaceentrelescomposantsgrsparunBoxLayoutetlaspectrsultantnesttrsar. Pourpouvoirajouterunespaceentrelescomposants,vousdevezinsrerdescomposantsderservationdespace. Troistypessontdisponibles: Strut :cetlmentestutilispourajouterunespacefixeentredeuxcomposants.UnStrutpeuttrehorizontalou verticalsuivantletypedeBoxLayoutauquelilestdestin.Cesdeuxtypesdlmentssontcrsparlesmthodes statiquescreateVerticalStrutetcreateHorizontalStrutdelaclasseBox.Ellesattendenttouteslesdeuxcomme

- 28 -

ENI Editions - All rigths reserved

argumentlenombredepixelspourlalargeuroulahauteur. // cration dun bouton avec alignement sur le haut b1=new JButton("petit"); b1.setAlignmentY(0); ligne.add(b1); ligne.add(Box.createHorizontalStrut(10)); // cration dun bouton avec alignement sur le bas b2=new JButton(" moyen "); b2.setAlignmentY(1); ligne.add(b2); RigidArea:cetlmentaunfonctionnementsimilaireaceluidun Strutensparantlescomposantslesunsdes autres.Ilforcegalementunehauteurminimalepourleconteneur.Siuncomposantcontenudansleconteneur unehauteursuprieurecelleci, cestdanscecasluiquiimposelahauteurduconteneur.Danslecascontraire, cestlecomposantleplushautquisimpose.CommepourunStrut,cestlamthodestatiquecreateRigidAreade la classe Box qui nous permet la cration dun RigidArea. Cette mthode attend comme argument un objet Dimensionspcifiantlespacemententrelescomposantsetlahauteurminimaleduconteneur. // cration dun bouton avec alignement sur le haut b1=new JButton("petit"); b1.setAlignmentY(0); ligne.add(b1); ligne.add(Box.createRigidArea(new Dimension(50,150))); // cration dun bouton avec alignement sur le bas b2=new JButton(" moyen "); b2.setAlignmentY(1); ligne.add(b2); Glue :lebutdecetlmentesttoujoursdesparerlescomposantsmaiscettefoislespaceentrelescomposants na pas une taille fixe. On peut comparer un Glue un ressort que lon place entre deux composants et qui les loignetoujourslepluspossible.PouravoirunfonctionnementcorrectduGlue,lescomposantsdoiventavoirune taillefixeouunetaillemaximalefixe.Commelesautreslmentsdesparation,ilestcrpartirdelamthode statiquecreateGluedelaclasseBox. JPanel ligne; ligne=new JPanel(); BoxLayout bl; bl=new BoxLayout(ligne,BoxLayout.X_AXIS); ligne.setLayout(bl); JButton b1,b2; // cration dun bouton avec alignement sur le haut b1=new JButton("petit"); b1.setAlignmentY(0); b1.setMaximumSize(new Dimension(50,20)); ligne.add(b1); ligne.add(Box.createGlue()); // cration dun bouton avec alignement sur le bas b2=new JButton(" moyen "); b2.setAlignmentY(1); b2.setMaximumSize(new Dimension(50,20)); ligne.add(b2);

e.GridBagLayout
VouspouvezconsidrerleGridBagLayoutcommele"super"gestionnairedemiseenpagetantdupointdevuedes performances que de la complexit dutilisation. Il fonctionne la base comme un GridLayout en plaant les composants lintrieur dune grille mais la comparaison sarrte l. Dans un GridBagLayout les lignes et les colonnesontdestaillesvariables,lescellulesadjacentespeuventtrefusionnespouraccueillirlescomposantsles plusgrands.Lescomposantsnoccupentpasobligatoirementtoutelasurfacedeleurscellulesetleurspositions lintrieur de la cellule peuvent tre modifies. La spcificit de ce gestionnaire se situe principalement dans la mthode dajout des composants. Cette mthode attend bien sr comme argument le composant ajouter mais galement un objet GridBagConstraints indiquant la faon de positionner le composant dans le conteneur. Cest donc les caractristiques de cet objet qui vont permettre le positionnement du composant par le GridBagLayout. Regardonsdonclesprincipalescaractristiquesdecetobjet:
q

gridx :colonneducoinsuprieurgaucheducomposant.

ENI Editions - All rigths reserved

- 29 -

gridy :ligneducoinsuprieurgaucheducomposant.

Pourcesdeuxpropritslanumrotationcommencezro.
q

gridwidth :nombredecolonnesoccupesparlecomposant. gridheight :nombredelignesoccupesparlecomposant. weightx :indiquecommentestrpartilespacesupplmentairedisponibleenlargeurlorsqueleconteneur est redimensionn. La rpartition est faite au prorata de cette valeur. Si cette valeur est gale zro le composant nest pas redimensionn. Si cette valeur est identique pour tous les composants lespace est rpartiquitablement. weighty :cettepropritjouelemmerlequelaprcdentemaissurlaxevertical. fill : cette proprit est utilise lorsque la zone alloue un composant est suprieure sa taille. Elle dterminesilecomposantestredimensionnetcomment.Lesconstantessuivantessontpossibles:
q

NONE:lecomposantnestpasredimensionn. HORIZONTAL:lecomposantestredimensionnenlargeuretsahauteurresteinchange. VERTICAL:lecomposantestredimensionnenhauteuretsalargeurresteinchange. BOTH : le composant est redimensionn en largeur et en hauteur pour remplir compltement la surfacedisponible.

anchor : indique comment est positionn le composant dans lespace disponible sil nest pas redimensionn.Lesconstantessuivantessontdisponibles.

UnmmeobjetGridBagConstraintspeuttreutilispourplacerplusieurscomposantssurunGridBagLayout.Ilfaut bienpenserdanscecasinitialisercorrectementlesdiffrentschampslorsdelajoutdechaquecomposant. titredexemplevoicilinterfaceduneapplicationsimpleetlecodecorrespondant.

- 30 -

ENI Editions - All rigths reserved

package fr.eni; import import import import import import import import import java.awt.GridBagConstraints; java.awt.GridBagLayout; javax.swing.JCheckBox; javax.swing.JComboBox; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JList; javax.swing.JPanel; javax.swing.JScrollPane;

public class Ecran extends JFrame { JPanel pano; JCheckBox chkGras,chkItalique; JLabel lblTaille,lblExemple; JComboBox cboTaille; JList lstPolices; JScrollPane defilPolices; public Ecran() { setTitle("choix d\une police"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des composants pano=new JPanel(); chkGras=new JCheckBox("gras"); chkItalique=new JCheckBox("italique"); lblTaille=new JLabel("taille"); lblExemple=new JLabel("essai de police de caractres"); cboTaille=new JComboBox(new String[] {"10","12","14","16","18","20"}); lstPolices=new JList(new String[]{"arial","courier","letter","helvetica","times roman","symbole", "antique"}); defilPolices=new JScrollPane(lstPolices); GridBagLayout gbl; gbl=new GridBagLayout(); pano.setLayout(gbl); GridBagConstraints gbc; gbc=new GridBagConstraints(); // position dans la case 0,0 gbc.gridx=0; gbc.gridy=0;
ENI Editions - All rigths reserved - 31 -

// sur une colonne de largeur gbc.gridwidth=1; // et sur trois lignes en hauteur gbc.gridheight=3; // pondration en cas dagrandissmment du conteneur gbc.weightx=100; gbc.weighty=100; // le composant est redimensionn pour occuper // tout lespace disponible dans son conteneur gbc.fill=GridBagConstraints.BOTH; pano.add(defilPolices,gbc); // position dans la case 1,0 gbc.gridx=1; gbc.gridy=0; // sur deux colonnes de largeur gbc.gridwidth=2; // et sur une ligne en hauteur gbc.gridheight=1; // pondration en cas dagrandissement du conteneur gbc.weightx=100; gbc.weighty=100; // le composant nest pas redimensionn pour occuper // tout lespace disponible dans son conteneur gbc.fill=GridBagConstraints.NONE; pano.add(chkGras,gbc); // position dans la case 1,1 gbc.gridx=1; gbc.gridy=1; // sur deux colonnes de largeur gbc.gridwidth=2; // et sur une ligne en hauteur gbc.gridheight=1; // pondration en cas dagrandissement du conteneur gbc.weightx=100; gbc.weighty=100; pano.add(chkItalique,gbc); // position dans la case 1,2 gbc.gridx=1; gbc.gridy=2; // sur une colonne de largeur gbc.gridwidth=1; // et sur une ligne en hauteur gbc.gridheight=1; // pondration en cas dagrandissement du conteneur gbc.weightx=100; gbc.weighty=100; pano.add(lblTaille,gbc); // position dans la case 2,2 gbc.gridx=2; gbc.gridy=2; // sur une colonne de largeur gbc.gridwidth=1; // et sur une ligne en hauteur gbc.gridheight=1; // pondration en cas dagrandissement du conteneur gbc.weightx=100; gbc.weighty=100; pano.add(cboTaille,gbc); // position dans la case 0,3 gbc.gridx=0; gbc.gridy=3; // sur trois colonnes de largeur gbc.gridwidth=3; // et sur une ligne en hauteur gbc.gridheight=1; // pondration en cas dagrandissement du conteneur gbc.weightx=100; gbc.weighty=100; pano.add(lblExemple,gbc);

- 32 -

ENI Editions - All rigths reserved

getContentPane().add(pano); } }

f.Sansgestionnairedemiseenpage
Sivousntespasconvaincudelutilitdungestionnairedemiseenpage,vousavezlapossibilitdegrervous mmelatailleetpositiondescomposantsdelinterfaceutilisateur.Vousdevezdabordindiquerquevousrenoncez utiliser un gestionnaire de mise en forme en appelant la mthode setLayout du conteneur et en lui passant la valeur null. Vous pouvez ensuite ajouter les composants au conteneur avec la mthode add de celuici. Et finalementvousdevezpositionneretdimensionnerlescomposants.Cesdeuxoprationspeuventtreeffectues endeuxtapesaveclesmthodessetLocationetsetSizeouenuneseuletapeaveclamthodesetBounds. package fr.eni; import import import import import import import import import java.awt.GridBagConstraints; java.awt.GridBagLayout; javax.swing.JCheckBox; javax.swing.JComboBox; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JList; javax.swing.JPanel; javax.swing.JScrollPane;

public class Ecran extends JFrame { JPanel pano; JCheckBox chkGras,chkItalique; JLabel lblTaille,lblExemple; JComboBox cboTaille; JList lstPolices; JScrollPane defilPolices; public Ecran() { setTitle("choix d\une police"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des composants pano=new JPanel(); chkGras=new JCheckBox("gras"); chkItalique=new JCheckBox("italique"); lblTaille=new JLabel("taille"); lblExemple=new JLabel("essai de police de caractres"); cboTaille=new JComboBox(new String[]{"10","12","14","16","18","20"}); lstPolices=new JList(new String[]{"arial","courier","letter","helvetica","times roman","symbole", "antique"}); defilPolices=new JScrollPane(lstPolices); // ajout sur le conteneur pano.setLayout(null); pano.add(defilPolices); pano.add(chkGras); pano.add(chkItalique); pano.add(lblTaille); pano.add(cboTaille); pano.add(lblExemple); // position des composants. defilPolices.setBounds(24, 29, 156, 255); chkGras.setBounds(258, 78, 170, 25); chkItalique.setBounds(261, 139, 167, 46); lblTaille.setBounds(215, 211, 106, 24); cboTaille.setBounds(354, 208, 107, 32); lblExemple.setBounds(17, 309, 459, 28);
ENI Editions - All rigths reserved - 33 -

getContentPane().add(pano); Notreapplicationprsentebienlemmeaspectquesielleutilisaitungestionnairedemiseenpage.

Parcontresilafentreestredimensionne,lescomposantsconserventleurstaillesetpositionsetlinterfacepeut alorsprendreunaspectincohrent.

4.Lescomposantsgraphiques
ChaquecomposantutilisableavecJavaestreprsentparuneclassedontnousallonspouvoircrerdesinstances pourconcevoirlinterfacedelapplication.LamajoritdescomposantsSwingdriventdelaclasseJComponentetdece fait,hritentdunbonnombredepropritsetdemthodesdecetteclasseoudesclassessituesaudessusdans lahirarchiedhritage.

- 34 -

ENI Editions - All rigths reserved

NousallonsdonctudierleslmentslesplusutilesdelaclasseJComponent.

a.LaclasseJComponent
Dimensionsetposition Une multitude de mthodes interviennent dans la gestion de la position et de la taille des composants. Deux catgoriesdinformationssontdisponiblespourlatailledescomposants :
q

La taille actuelle est accessible par la mthode getSize. Cette dernire obtient la taille du composant au momentdelappeldelamthode.Silecomposantestprisenchargeparungestionnairedemiseenpage, celuiciestsusceptibledemodifierlatailleducomposantetdonclappeldecettemthodepeutrenvoyerun rsultatdiffrentchaqueappel.LataillepeutaussitremodifieparlamthodesetSize.Leseffetsde cettemthodepeuventtredecourtedurecar,silecomposantestprisenchargeparungestionnairede miseenpage,celuicipeuttoutmomentredessinerlecomposantavecunetaillediffrente. La taille prfre est accessible par la mthode getPreferedSize. Par dfaut cette taille est calcule en fonctionducontenuducomposant.Cettemthodeestsurtoututiliseeninterneparlesgestionnairesde mise en page. Pour viter que la taille du composant soit recalcule en fonction de son contenu, vous pouvez utiliser la mthode setPreferedSize. Les informations fournies par cette mthode sont ensuite utilises par la mthode getPreferedSize lorsque le conteneur a besoin dinformations sur la taille du composant.

La position dun composant lintrieur de son conteneur peut tre obtenue ou dfinie avec les mthodes getLocationou setLocation.CommepourlamthodesetSize leffetdelamthodesetLocationpeuttretout momentannulparlegestionnairedemiseenpage,siceluicidoitredessinerlescomposants. Les mthodes getBounds et setBounds permettent de combiner la modification de la taille et de la position du composant. Ces mthodes nont vraiment dintrt que si vous assumez compltement la prsentation des composantslintrieurduconteneursanspasserparlesservicesdungestionnairedemiseenpage. Apparencedescomposants LacouleurdefondducomposantpeuttremodifieparlamthodesetBackgroundtandisquelacouleurdutexte du composant est modifie par la proprit setForeground. Ces mthodes attendent comme argument un objet Color.CetobjetColorpeuttreobtenuparlesconstantesdfiniesdanslaclasseColor. lstPolices.setBackground(Color.red); lstPolices.setForeground(Color.GREEN); La classe Color propose galement de nombreux constructeurs permettant dobtenir une couleur particulire en effectuantunmlangedescouleursdebase. lstPolices.setBackground(new Color(23,67,89)); lstPolices.setForeground(new Color(167,86,23)); LapoliceestmodifiableparlamthodesetFontducomposant.Onpeut,pourloccasion,crerunenouvelleinstance delaclasseFontetlaffecteraucomposant.Pourcela,nousutiliseronsundesconstructeursdelaclasseFonten indiquantlenomdelapolice,lestyledelapoliceetsataille. lstPolices.setFont(new Font("Serif",Font.BOLD,24)); La mthode setCursor permet de choisir lapparence du curseur lorsque la souris se trouve sur la surface du composant.PlusieurscurseurssontprdfinisetsontaccessiblesencrantuneinstancedelaclasseCursoravec unedesconstantesprdfinies.

ENI Editions - All rigths reserved

- 35 -

lstPolices.setCursor(new Cursor(Cursor.HAND_CURSOR)); Ladtectiondelentreetdelasortiedelasourissurlecomposantetlamodificationducurseurenconsquence estgreautomatiquementparlecomposantluimme. Comportementdescomposants LescomposantsplacssurunconteneurpeuventtremasqusenappelantlamthodesetVisibleoudsactivs enappelantlamthodesetEnabled.Danscecas,lecomposantesttoujoursvisiblemaisapparatavecunaspect grispourindiquerlutilisateurquececomposantestinactifpourlemoment. chkGras.setVisible(false); chkItalique.setEnabled(false); Lescomposantsdanscettatnepeuventbiensrpasrecevoirlefocusdanslapplication.Vouspouvezvrifiercela en appelant la mthode isFocusable qui renvoie un boolean. Vous pouvez galement vrifier si un composant dtientactuellementlefocus,enutilisantlamthodeisFocusOwner.Lefocuspeuttreplacsuruncomposantsans linterventiondelutilisateur,enappelantlamthoderequestFocusducomposant. Poursurveillerlepassagedufocusduncomposantlautre,deuxvnementssontvotredisposition:
q

focusGainedindiquequuncomposantparticulierareulefocus. focusLostindiquequuncomposantaperdulefocus.

Parexemple,pourbienvisualiserquuncomposantdtientlefocus,onpeututiliserlecodesuivantquimodifiela couleurdutextelorsquelecomposantreoitouperdlefocus : lstPolices.addFocusListener(new FocusListener() { public void focusGained(FocusEvent arg0) { lstPolices.setForeground(Color.RED); } public void focusLost(FocusEvent arg0) { lstPolices.setForeground(Color.BLACK); } });

b.Affichagedinformations
LecomposantJLabel LecomposantJLabelestutilispouraffichersurunformulaire,untextequineserapasmodifiableparlutilisateur. Ilsertessentiellementfournirunelgendedescontrlesquinenpossdentpas(zonesdetexteparexemple, listedroulante...).Danscecas,ilpermettragalementdefournirunraccourciclavierpouratteindrececomposant. Le texte affich par le composant est indiqu lors de sa cration ou par la mthode setText. Par dfaut, le composant JLabel na pas de bordure . Vous pouvez en ajouter une en appelant la mthode setBorder en lui passantlabordureutiliser. JLabel legende; legende=new JLabel("nom"); legende.setBorder(BorderFactory.createEtchedBorder()); Vous avez aussi la possibilit dindiquer la position du texte dans le composant par lintermdiaire des mthodes setHorizontalAlignmentetsetVerticalAlignmentenspcifiantunedesconstantesprdfinies. SwingConstants.RIGHT : alignement sur la droite SwingConstants.CENTER : alignement sur le centre SwingConstants.LEFT : alignement sur la gauche

- 36 -

ENI Editions - All rigths reserved

SwingConstants.TOP : alignement sur le haut SwingConstants.BOTTOM : alignement sur le bas Ces mthodes nont aucun effet visible si le composant est dimensionn automatiquement par son conteneur puisquedanscecassatailleestautomatiquementajustesoncontenu.Pourquecesmthodesaientuneffet visible,vousdevezindiquerunetailleprfrepourlecomposant. legende=new JLabel("nom"); legende.setBorder(BorderFactory.createEtchedBorder()); legende.setPreferredSize(new Dimension(200,50)); legende.setHorizontalAlignment(SwingConstants.LEFT); legende.setVerticalAlignment(SwingConstants.TOP);

LescomposantsJLabelpeuventgalementafficherdesimages.Vouspouvezindiquerlimageafficherlaidede la mthode setIcon. Limage doit bien sr tre cre au pralable. Si du texte est galement affich sur le composant, sa position peut tre spcifie par rapport limage en utilisant les mthodes setHorizontalTextPosition et setVerticalTextPosition, ainsi que lespace entre le texte et limage avec la mthodesetIconTextGap. JLabel legende; legende=new JLabel("nom"); legende.setBorder(BorderFactory.createEtchedBorder()); legende.setPreferredSize(new Dimension(200,200)); legende.setIcon(new ImageIcon("duke.gif")); legende.setHorizontalTextPosition(SwingConstants.LEFT); legende.setVerticalTextPosition(SwingConstants.BOTTOM); legende.setIconTextGap(40);

NousavonsindiququelecomposantJLabelpouvaittreutiliscommeraccourciclavierpourunautrecomposant. Pourcela,deuxprcautionssontprendre.
q

Vousdevezindiquer,aveclamthodesetDisplayedMnemonic,lecaractreutiliscommeraccourciclavier. Vous devez galement indiquer au JLabel pour quel composant il joue le rle de lgende en utilisant la mthodesetLabelFor.

legende.setDisplayedMnemonic(n); legende.setLabelFor(lstPolices);

LecomposantJProgressBar Cecomposantestutilispourinformerlutilisateursurlaprogressionduneactionlancedanslapplication.Ilaffiche cette information sous la forme dune zone rectangulaire, qui sera plus ou moins remplie en fonction de ltat davancementdelactionexcute. LapositiondelabarredeprogressionestcontrleparlamthodesetValue.Cettemthodeaccepteunargument pouvantvoluerentrelesdeuxextrmesindiqusparlesmthodessetMinimumetsetMaximum.

ENI Editions - All rigths reserved

- 37 -

Unelgendepeutgalementtreafficheenincrustationsurlabarredeprogression.Letextedelalgendeest indiquparlamthodesetStringetsonaffichageestcontrlparlamthodesetStringPainted. Sil est impossible dvaluer la progression dune opration et donc dobtenir une valeur fournir la barre de progression,cellecipeuttreplacedansuntatindterminaveclamthodesetIndeterminate.Uncurseurse dplaantenpermanenceentrelesdeuxextrmesestdanscecasaffich. LexemplesuivantprsenteunehorlogeoriginaleolheureestaffichepartroisJProgressBar: package fr.eni;

import import import import

java.util.GregorianCalendar; javax.swing.JFrame; javax.swing.JPanel; javax.swing.JProgressBar;

public class Ecran13 extends JFrame { JPanel pano; JProgressBar pgbHeure,pgbMinutes,pgbSeconde,pgbDefil; public Ecran13() { setTitle("horloge"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des composants pgbHeure =new JProgressBar(); pgbMinutes=new JProgressBar(); pgbSeconde=new JProgressBar(); pgbDefil=new JProgressBar(); pgbHeure.setMinimum(0); pgbHeure.setMaximum(23); pgbMinutes.setMinimum(0); pgbMinutes.setMaximum(59); pgbSeconde.setMinimum(0); pgbSeconde.setMaximum(59); pgbHeure.setString("heure"); pgbHeure.setStringPainted(true); pgbMinutes.setString("minute"); pgbMinutes.setStringPainted(true); pgbSeconde.setString("seconde"); pgbSeconde.setStringPainted(true); pgbDefil.setString("le temps passe"); pgbDefil.setStringPainted(true); pgbDefil.setIndeterminate(true); pano=new JPanel(); pano.add(pgbHeure); pano.add(pgbMinutes); pano.add(pgbSeconde); pano.add(pgbDefil); getContentPane().add(pano); Thread th; th=new Thread() { public void run() { while (true) { GregorianCalendar d; d=new GregorianCalendar(); pgbHeure.setValue(d.get(GregorianCalendar.HOUR)); pgbMinutes.setValue(d.get(GregorianCalendar.MINUTE)); pgbSeconde.setValue(d.get(GregorianCalendar.SECOND)); try {

- 38 -

ENI Editions - All rigths reserved

sleep(500); } catch (InterruptedException e) { } } }}; th.start(); } }

c.Lescomposantsdditiondetexte
JTextField Le composant JTextField est utilis pour permettre lutilisateur de saisir des informations. Ce composant ne permet que la saisie de texte sur une seule ligne. Ce composant est galement capable de grer la slection de texteetlesoprationsaveclePressepapiers.Denombreusesmthodessontdisponiblespourtravailleravecce composant.Pardfaut,cecomposantadapteautomatiquementsataillesoncontenucequipeutprovoquerun raffichage permanent du composant. Pour pallier ce problme, il est prfrable de spcifier une taille pour le composant soit en utilisant sa mthode setPreferedSize soit en indiquant le nombre de colonnes dsir pour laffichagedutextedanscecomposant.Cecinelimiteabsolumentpaslenombredecaractrespouvanttresaisis maisuniquementlalargeurducomposant.Letexteaffichdanslecomposantpeuttremodifiourcuprparles mthodessetTextougetText. Lagestiondelaslectiondutextesefaitautomatiquementparlecomposant.LamthodegetSelectedTextpermet dercuprerlachanedecaractresactuellementslectionnedanslecontrle.LesmthodesgetSelectionStart etgetSelectionEndindiquentrespectivementlecaractrededbutdelaslection(lepremiercaractrealindice0) etlederniercaractredelaslection. Laslectiondetextepeutgalementseffectueraveclamthodeselect,enindiquantlecaractrededbutdela slectionetlecaractredefinlaslection. LaslectiondelatotalitdutextepeuttreeffectueaveclamthodeselectAll.Parexemple,onpeutforcerla slectiondetoutletextelorsquelecomposantreoitlefocus. txt=new JTextField(10); txt.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { txt.selectAll(); } public void focusLost(FocusEvent e) { txt.setSelectionStart(0); txt.setSelectionEnd(0); } }); Pour la gestion du Pressepapiers, le composant JTextField gre automatiquement les raccourcisclavier du systme pour les oprations de copier, couper, coller. Vous avez cependant la possibilit dappeler les mthodes copy,cutetpastepourgrerlesoprationsdecopier,couper,collerduneautremanire,parexempleparunmenu delapplicationouunmenucontextuelcommedanslexemplecidessous: txt=new JTextField(10);

ENI Editions - All rigths reserved

- 39 -

mnu=new JPopupMenu(); JMenuItem mnuCopier; JMenuItem mnuCouper; JMenuItem mnuColler; mnuCopier=new JMenuItem("Copier"); mnuCouper=new JMenuItem("Couper"); mnuColler=new JMenuItem("Coller"); mnuCopier.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.copy(); } } ); mnuCouper.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.cut(); } } ); mnuColler.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.paste(); } } ); mnu.add(mnuCopier); mnu.add(mnuCouper); mnu.add(mnuColler); txt.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.getButton()==MouseEvent.BUTTON3) { mnu.show((Component)e.getSource(), e.getX(),e.getY()); } } } ); } Les oprations couper et coller ne seront cependant pas possibles si le composant JTextField est configur en lectureseuleaveclamthodesetEditable(false),lamodificationdutexteparlutilisateurestbiensrdanscecas galementimpossible. Toutlemondeayantdroitlerreur,ilestpossibledeprovoquerlannulationdeladerniremodificationdetexte effectuesurlecontrle.Pourcela,nousdevonsnousadjoindrelaidedunobjetUndoManager.Cestcedernierqui prend effectivement en charge lannulation de la dernire modification grce sa mthode undo. Cette mthode peuttreappeleparuneoptiondumenucontextuelouparleraccourciclavier[Ctrl]Z.Ilnyaquunseulniveau deUndo,vousnepourrezrevenirautextequevousavezsaisi,ilyadeuxheures! // cration du UndoManager UndoManager udm ; udm=new UndoManager(); // association avec le JTextField txt.getDocument().addUndoableEditListener(udm); // ajout dun couteur pour intercepter le ctrl Z txt.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyChar()==z & e.isControlDown()) {

- 40 -

ENI Editions - All rigths reserved

udm.undo(); } } }); JPasswordField CecomposantestlabaseunJTextFieldnormallgrementmodifipourtrespcialisdanslasaisiedemotde passe. Les deux seuls ajouts rellement utiles sont la mthode setEchoChar permettant dindiquer le caractre utiliscommecaractredesubstitutionlorsdelaffichageetlamthodegetPasswordpermettantdobtenirlemotde passesaisiparlutilisateur. JTextArea CecomposantoffredesfonctionnalitsplusvoluesquunsimpleJTextField.Lapremireamliorationimportante apporteparcecomposantrsidedanssacapacitgrerlasaisiesurplusieurslignes.Cestdailleurspourcette raisonquelorsdelaconstructiondunobjetdunobjetJTextAreanousdevonsspcifierlenombredelignesetle nombredecolonnesquilvacomporter.Cesdeuxinformationssontutilisesuniquementpourledimensionnement ducomposantetninfluencentpaslaquantitdetextequepeutcontenirlecomposant.Parcontre,cecomposant negrepasluimmeledfilementdutextequonluiconfie.Pourluiadjoindrecettefonctionnalit,celuicidoittre placsurunconteneurdetypeJScrollPanequivaprendreenchargeledfilementducontenuduJTextArea. Sicettesolutionnestpasutilise,lecomposantJTextAreapeuttreconfigurpourscinderautomatiquementune ligne lors de son affichage. La mthode setLineWrap permet dactiver ce mode de fonctionnement. Par dfaut le dcoupage se produit sur le dernier caractre visible dune ligne avec le risque de voir certains mots affichs sur deuxlignes.Pourviterceproblme,lecomposantJTextAreapeuttreconfigurpoureffectuersondcoupagesur lesespacessparantlesmotsaveclamthodesetWrapStyleWord.Lessautsdeligneajoutsparlecomposantne fontpaspartiedutexteetsontutilissuniquementpourlaffichagedeceluici. package fr.eni; import import import import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JCheckBox; javax.swing.JFrame; javax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JTextArea;

public class Ecran extends JFrame { JPanel pano; JTextArea txt; JCheckBox chkWrap,chkWrapWord; JScrollPane defil; public Ecran() { setTitle("diteur de texte"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des composants pano=new JPanel(); txt=new JTextArea(10,40); defil=new JScrollPane(txt); pano.add(defil); chkWrap=new JCheckBox("retours la ligne automatique"); chkWrapWord=new JCheckBox("retours entre deux mots"); chkWrap.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setLineWrap(chkWrap.isSelected()); } }); chkWrapWord.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

ENI Editions - All rigths reserved

- 41 -

txt.setWrapStyleWord(chkWrapWord.isSelected()); } }); pano.add(chkWrap); pano.add(chkWrapWord); getContentPane().add(pano); } } Avec les options par dfaut les lignes trop longues ne sont pas visibles entirement et la barre de dfilement horizontaleestactiveautomatiquement.

AvecloptionLineWrap,leslignessontdcoupesautomatiquementlalargeurducomposant.Ilnyaplusbesoin debarrededfilementhorizontal.Parcontreunebarrededfilementverticalestmaintenantncessairepuisquele nombredelignesestmaintenantsuprieurlacapacitducomposant.

Pouramliorerlalisibilitdutexte,ledcoupagepeuttrefaitsurdesmotsentiersavecloptionWrapStyleWord.

- 42 -

ENI Editions - All rigths reserved

Lagestiondutextecontenudanscecomposantestgalementfacilitegrceplusieursmthodesspcifiques.
q

append(String chane) : ajoute la chane de caractres passe comme argument au texte dj prsent danslecomposant. insert(String chane, int position) :insrelachanedecaractrespassecommepremierargument lapositionindiqueparledeuximeargument. replaceRange(String chane, int debut, int fin) :remplacelaportiondetextecompriseentrelavaleur fournieparledeuximeargumentetcellefournieparletroisimeargumentparlachaneindiquecomme premierargument.

d.Lescomposantsdedclenchementdactions
JButton Le composantJButton est principalement utilis dans une application, pour lancer lexcution dune action. Cette action peut tre lexcution dune portion de code ou la fermeture dune bote de dialogue. Comme pour les contrles vus jusqu prsent, le libell du bouton est modifiable par la mthode setText du composant. Ce composant peut galement contenir une image. Celleci est gre exactement de la mme faon que pour le composant JLabel. Ce composant est pratiquement toujours associ un couteur implmentant linterface ActionListenerafindegrerlesclicssurlebouton. JMenuBarJMenuJMenuItemJPopupMenuJSeparator Cet ensemble de composants va permettre la gestion des menus dapplication ou des menus contextuels. Le composantJMenuBar constitue le conteneur qui va accueillir les menus reprsents par desJMenu qui euxmmes vontcontenirdeslmentsdemenusreprsentspardesJMenuItem.LecomposantJMenuBarsecomportecomme unconteneurpourlesJMenu.LesJMenuvonteuxaussisecomportercommeunconteneurpourdesJMenuItemou dautresJMenu.Laconceptiondunmenuvadoncconsistercrerdesinstancesdecesdiffrentesclassespuisde les associer les unes aux autres. Au final le JMenuBar obtenu est plac sur son conteneur qui nest autre que la JFrame de lapplication. Il faut bien sr galement penser traiter les vnements dclenchs par ces diffrents lments.Engnral,seulslesJMenuItemsontassocisdescouteurs.IlssecomportentcommedesJButton.Ils ontdailleursunanctrecommunpuisquetousdeuxhritentdelaclasseAbstractButton.Laconceptiondunmenu nest pas trs complexe. La seule difficult rside dans la quantit de code relativement importante ncessaire. Pourillustrercela,voicilecodedunditeurdetexterudimentairepossdantlesmenussuivants :

package fr.eni;

ENI Editions - All rigths reserved

- 43 -

import import import import import import import import import import import import import import import import import import import import import

java.awt.event.ActionEvent; java.awt.event.ActionListener; java.io.BufferedReader; java.io.File; java.io.FileInputStream; java.io.FileNotFoundException; java.io.FileOutputStream; java.io.IOException; java.io.InputStream; java.io.InputStreamReader; java.io.PrintWriter; javax.swing.JCheckBox; javax.swing.JFileChooser; javax.swing.JFrame; javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JSeparator; javax.swing.JTextArea;

public class Ecran14 extends JFrame { JPanel pano; JTextArea txt; JScrollPane defil; JMenuBar barre; JMenu mnuFichier,mnuEdition,mnuSauvegarde; JMenuItem mnuNouveau, mnuOuvrir,mnuEnregister,mnuEnregistrerSous, mnuQuitter; JMenuItem mnuCopier,mnuCouper,mnuColler; File fichier; public Ecran14() { setTitle("diteur de texte"); setBounds(0,0,300,100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // cration des composants pano=new JPanel(); pano.setLayout(new BorderLayout()); txt=new JTextArea(); defil=new JScrollPane(txt); pano.add(defil,BorderLayout.CENTER); getContentPane().add(pano); // cration des composants des menus barre=new JMenuBar(); mnuFichier=new JMenu("Fichier"); mnuEdition=new JMenu("Edition"); mnuSauvegarde=new JMenu("Sauvegarde"); mnuNouveau=new JMenuItem("Nouveau"); mnuOuvrir=new JMenuItem("Ouvrir"); mnuEnregister=new JMenuItem("Enregistrer"); mnuEnregister.setEnabled(false); mnuEnregistrerSous=new JMenuItem("Enregistrer sous"); mnuCopier=new JMenuItem("Copier"); mnuCouper=new JMenuItem("Couper"); mnuColler=new JMenuItem("Coller"); mnuQuitter=new JMenuItem("Quitter"); // association des lments barre.add(mnuFichier); barre.add(mnuEdition); mnuFichier.add(mnuNouveau); mnuFichier.add(mnuOuvrir); mnuFichier.add(mnuSauvegarde); mnuSauvegarde.add(mnuEnregister); mnuSauvegarde.add(mnuEnregistrerSous);

- 44 -

ENI Editions - All rigths reserved

mnuFichier.add(new JSeparator()); mnuFichier.add(mnuQuitter); mnuEdition.add(mnuCopier); mnuEdition.add(mnuCouper); mnuEdition.add(mnuColler); // association du menu avec la JFrame setJMenuBar(barre); // les couteurs associs aux diffrents menus mnuNouveau.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { fichier=null; txt.setText(""); mnuEnregister.setEnabled(false); } }); mnuOuvrir.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { JFileChooser dlg; dlg=new JFileChooser(); dlg.showDialog(null,"Ouvrir"); fichier=dlg.getSelectedFile(); FileInputStream in; try { in=new FileInputStream(fichier); BufferedReader br; br=new BufferedReader(new InputStreamReader(in)); String ligne; txt.setText(""); while ((ligne=br.readLine())!=null) { txt.append(ligne+"\r\n"); } br.close(); mnuEnregister.setEnabled(true); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); mnuQuitter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); mnuCopier.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.copy(); } }); mnuCouper.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

ENI Editions - All rigths reserved

- 45 -

txt.cut(); } }); mnuColler.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.paste(); } }); mnuEnregister.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { try { PrintWriter pw; pw=new PrintWriter(fichier); pw.write(txt.getText()); pw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }); mnuEnregistrerSous.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { try { JFileChooser dlg; dlg=new JFileChooser(); dlg.showDialog(null,"enregistrer sous"); fichier=dlg.getSelectedFile(); PrintWriter pw; pw=new PrintWriter(fichier); pw.write(txt.getText()); pw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }); } } JToolBar Ce composant sert en fait de conteneur pour les lments constituant une barre doutils. Ces lments sont ajoutsaucomposantJToolBarcommepournimportequelautreconteneur.DesJButtonsanslibellmaisaffichant des images sont gnralement placs sur ce composant. Ils fournissent un accs une fonctionnalit dj disponible par un menu. ce titre, ils partagent gnralement le mme couteur. Ce composant prsente la particularitdepouvoirtredplacparlutilisateur sur nimportelaquelledesborduresdelafentre,voiredans certainscaslextrieurdelafentre.Pourquecemcanismefonctionnecorrectement,lecomposantJtoolBardoit tre plac dans un conteneur utilisant unBorderLayout comme gestionnaire de mise en page. Il est dans ce cas plac sur une des bordures (NORTH, SOUTH, WEST, EAST) et doit tre le seul composant plac dans cette zone. CettefonctionnalitpeuttredsactiveenappelantlamthodesetFloatable(false).Labarredoutilsrestealors sapositiondorigine.Lecodesuivantajouteunebarredoutilsnotrediteurdetexte. JToolBar tlbr; tlbr=new JToolBar(); JButton btnNouveau,btnOuvrir,btnEnregister; JButton btnCopier,btnCouper,btnColler; // cration des boutons

- 46 -

ENI Editions - All rigths reserved

btnNouveau=new JButton(new ImageIcon("new.jpg")); btnOuvrir=new JButton(new ImageIcon("open.jpg")); btnEnregister=new JButton(new ImageIcon("save.jpg")); btnCopier=new JButton(new ImageIcon("copy.jpg")); btnColler=new JButton(new ImageIcon("paste.jpg")); btnCouper=new JButton(new ImageIcon("cut.jpg")); // ajout des boutons la barre doutils tlbr.add(btnNouveau); tlbr.add(btnOuvrir); tlbr.add(btnEnregister); tlbr.addSeparator(); tlbr.add(btnCopier); tlbr.add(btnCouper); tlbr.add(btnColler); // ajout de la barre doutils sur son conteneur pano.add(tlbr,BorderLayout.NORTH); // rutilisation couteurs dj associs aux menus btnNouveau.addActionListener(mnuNouveau.getActionListeners()[0]); btnOuvrir.addActionListener(mnuOuvrir.getActionListeners()[0]); btnEnregister.addActionListener(mnuEnregister.getActionListeners()[0]); btnCopier.addActionListener(mnuCopier.getActionListeners()[0]); btnCouper.addActionListener(mnuCouper.getActionListeners()[0]); btnColler.addActionListener(mnuColler.getActionListeners()[0]);

e.Lescomposantsdeslection
JCheckBox Le composant JCheckBox est utilis pour proposer lutilisateur diffrentes options, parmi lesquelles il pourra en choisir aucune, une, ou plusieurs. Le composant JCheckBox peut prendre deux tats : coch lorsque loption est slectionneounoncochlorsqueloption nestpasslectionne.Ltat de la case cocher peut tre vrifi ou modifiparlesmthodesisSelectedetsetSelected.Commebeaucoupdautrescomposants,celuicipeutavoirun libelle et une image. La gestion de limage est cependant un petit peu diffrente des JLabel puisquelle vient remplacerledessindelacasecocher.PourpouvoirdanscecasfaireunedistinctionentreuneJChecBoxcocheet unenoncoche,vousdevezluiassocierunedeuximeimagecorrespondantltatcoch.Cettedeuximeimage estindiqueparlamthodesetSelectedIcon. Lecodesuivantpermetdechoisirlestyledelapoliceutilisedansnotrediteurdetexte. JPanel options; GridLayout gl; options=new JPanel(); gl=new GridLayout(2,1); options.setLayout(gl); chkGras=new JCheckBox("Gras"); chkItalique=new JCheckBox("Italique"); options.add(chkGras); options.add(chkItalique); chkGras.addActionListener(new ActionListener()

ENI Editions - All rigths reserved

- 47 -

{ public void actionPerformed(ActionEvent e) { changePolice(); } }); chkItalique.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changePolice(); } }); pano.add(options,BorderLayout.SOUTH); } public void changePolice() { int attributs; attributs=0; if (chkGras.isSelected()) { attributs=attributs+Font.BOLD; } if (chkItalique.isSelected()) { attributs=attributs+Font.ITALIC; } Font police; police=new Font(txt.getFont().getName(),attributs,txt.getFont().getSize()); txt.setFont(police); } JRadioButton LecomposantJRadioButtonpermetgalementdeproposerlutilisateurdiffrentesoptionsparmilesquellesilne pourra en slectionner quune seule. Comme son nom lindique, ce contrle fonctionne comme les boutons permettantdeslectionnerunestationsurunpostederadio(vousnepouvezpascoutertroisstationsderadio en mme temps !). Les caractristiques de ce composant sont identiques celles disponibles dans le composant JCheckBox. Pour pouvoir fonctionner correctement, les composants JRadioButton doivent tre regroups logiquement. La classeButtonGroupfournitcettefonctionnalit.EllefaitensortequeparmitouslesJRadioButton quiluisontconfis,grcesamthodeadd,unseuldentreeuxpourratreslectionnlafois.Pourregrouper physiquementdesJRadioButonceuxcidoiventtreplacssurunconteneurtelquunJPanel.Pourbienvisualiserce regroupement, on ajoute gnralement une bordure sur le JPanel et ventuellement une lgende. Cest ce que nousallonsfaireenajoutantdeuxensemblesdeboutonspermettantdechoisirlacouleurdutexteetlacouleurde fonddenotrediteur. JRadioButton optFondRouge,optFondVert,optFondBleu; JRadioButton optRouge,optVert,optBleu; JPanel couleur,couleurFond; ButtonGroup grpCouleur,grpCouleurFond; // cration des boutons optRouge=new JRadioButton("Rouge"); optVert=new JRadioButton("Vert"); optBleu=new JRadioButton("Bleu"); optFondRouge=new JRadioButton("Rouge"); optFondVert=new JRadioButton("Vert"); optFondBleu=new JRadioButton("Bleu"); // regroupement logique des boutons grpCouleur=new ButtonGroup(); grpCouleur.add(optRouge); grpCouleur.add(optVert); grpCouleur.add(optBleu); grpCouleurFond=new ButtonGroup(); grpCouleurFond.add(optFondRouge); grpCouleurFond.add(optFondVert);

- 48 -

ENI Editions - All rigths reserved

grpCouleurFond.add(optFondBleu); // regroupement physique des boutons couleur=new JPanel(); couleur.setLayout(new GridLayout(0,1)); couleur.add(optRouge); couleur.add(optVert); couleur.add(optBleu); couleurFond=new JPanel(); couleurFond.setLayout(new GridLayout(0,1)); couleurFond.add(optFondRouge); couleurFond.add(optFondVert); couleurFond.add(optFondBleu); // ajout dune bordure avec titre couleur.setBorder(BorderFactory.createTitledBorder (BorderFactory.createEtchedBorder(),"couleur police")); couleurFond.setBorder(BorderFactory.createTitledBorder (BorderFactory.createEtchedBorder(),"couleur fond")); // rfrencement des couteurs optBleu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setForeground(Color.BLUE); } }); optVert.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setForeground(Color.GREEN); } }); optRouge.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setForeground(Color.RED); } }); optFondBleu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setBackground(Color.BLUE); } }); optFondRouge.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setBackground(Color.RED); } }); optFondVert.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { txt.setBackground(Color.GREEN); } }); JList LecomposantJListproposelutilisateurunelistedechoixdanslaquelleilpourraenslectionnerunouplusieurs. Le composant gre automatiquement laffichage des lments cependant, il nest pas capable den assurer le dfilement.Cecomposantdoitdonctreplacsurunconteneurprenantenchargecettefonctionnalitcommeun JScrollPane.Leslmentsaffichsdanslalistepeuventtrefournisaumomentdelacrationducomposanten indiquantcommeargumentauconstructeuruntableaudobjetouunVector.LesmthodestoStringdechacundes objetsserontutilisesparlecomposantJListpourpouvoirafficherllment.Aveccettesolution,lalisteestcre

ENI Editions - All rigths reserved

- 49 -

enlectureseuleetilnestpaspossibledyajouterdautreslmentsparlasuite.Pouravoirunelistedanslaquelle ilserapossibledajouterdautreslments,ilfaututiliserunobjetdetypeDefaultListModelquilonvaconfierle soin de grer les lments de la liste. Cet objet possde de nombreuses mthodes, similaires aux mthodes disponibles pour un Vector, permettant la gestion des lments. Si vous souhaitez utiliser une liste dynamique, vousdevezpasserauconstructeurdelaclasseJListunobjetdecetype. Lalistepeuttreconuepourautoriserdiffrentstypesdeslection.Lechoixdutypedeslectionseffectueavec lamthodesetSelectionModelaquellelonpassecommeargumentunedesconstantessuivantes:
q

ListSelectionModel.SINGLE_SELECTION :unseullmentdelalistepeuttreslectionnlafois. ListSelectionModel.SINGLE_INTERVAL_SELECTION : plusieurs lments peuvent tre slectionns mais ils doiventsesuivredanslaliste. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : plusieurs lments peuvent tre slectionns dans la listeetilsnesontpasforcmentcontigus.

Larcuprationdellment ou des lments slectionns peut tre effectue avec deux techniques diffrentes. Vous pouvez obtenir lindex ou les index des lments slectionns avec les mthodes getSelectedIndex ou setSelectedIndices.Cesmthodesretournentunentierouuntableaudentiersreprsentantlindexoulesindex des lments slectionns. Lobjet ou les objets slectionns sont eux disponibles grce aux mthodes getSelectedValueetgetSelectedValues.Demaniresimilaire,cesdeuxmthodesretournentlobjetslectionnou untableaucontenantlesobjetsslectionns.Laprsencedunlmentslectionndanslalistepeuttreteste aveclamthodeisSelectionEmpty.LaslectionpeuttreannuleaveclamthodeclearSelection.Lamodification de la slection dans la liste dclenche un vnement de type valueChanged. Cet vnement peut tre gr en associantlalisteuncouteurdetypeListSelectionListeneraveclamthodeaddListSelectionListener.Ilfaut tre vigilant avec cet vnement car il se produit plusieurs fois de suite lorsquun lment est slectionn. Le premiervnementcorrespondladslectiondellmentprcdentetledeuximelaslectiondellment actuel.Cestdonccedernierquilfautprendreencompte.Pourcela,largumentListSelectionEventdisponibleavec cetvnementdisposedelamthodegetValueIsAdjustingpermettantdesavoirsilaslectionesttermineousi ellesetrouvedansuntattransitoire.Pourtesterlefonctionnement,nousallonsajouternotrediteurdetexte unelisteproposantlechoixdunepolicedecaractres. JList polices ; JScrollPane defilPolices; String[] nomsPolices={"Dialog","DialogInput","Monospaced","Serif", "SansSerif"}; polices=new JList(nomsPolices); polices.setSelectedIndex(0); defilPolices=new JScrollPane(polices); defilPolices.setPreferredSize(new Dimension(100,60)); options.add(defilPolices); polices.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { changePolice(); } } }); ... ... ... public void changePolice() { int attributs; attributs=0; if (chkGras.isSelected()) { attributs=attributs+Font.BOLD; } if (chkItalique.isSelected()) { attributs=attributs+Font.ITALIC; }

- 50 -

ENI Editions - All rigths reserved

Font police; police=new Font(polices.getSelectedValue().toString(),attributs,txt.getFont().getSize( )); txt.setFont(police); } JCombobox Cecomposantpeuttreassimillassociationdetroisautrescomposants :


q

unJTextField unJButton unJList

Lutilisateurpeutchoisirunlmentdanslalistequiapparatlorsquilcliquesurleboutonoubiensaisirdirectement dans la zone de texte linformation attendue si celleci nest pas disponible dans la liste. Deux modes de fonctionnementsontdisponibles.Vouspouveznautoriserquelaslectiondunlmentdanslalisteenconfigurant lazonedetexteenlectureseuleaveclamthodesetEditable(false)ouautorisersoitlaslectiondanslaliste, soit la saisie dans la zone de texte avec la mthode setEditable(true). La cration dune instance de ce composant suit les mmes principes que la cration dun JList. La rcupration de llment slectionn est effectuedemaniresemblableuneJList.Attentiontoutdemmecarilnyapasdeslectionsmultiplesdansce type de composant. La dtection de la slection dun nouvel lment peut tre faite en grant lvnement actionPerformed.Cetvnementsedclenchelorsdelaslectiondunlmentdanslalisteoulorsquelutilisateur valide la saisie avec la touche Enter. Nous terminons notre diteur de texte en proposant lutilisateur le choix dunetailledepolicedecaractres. JComboBox cboTaille ; String tailles[]={"10","12","14","16","20"}; cboTaille=new JComboBox(tailles); cboTaille.setEditable(true); options.add(cboTaille); cboTaille.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changePolice(); } }); ... ... ... public void changePolice() { int attributs; attributs=0; if (chkGras.isSelected()) { attributs=attributs+Font.BOLD; } if (chkItalique.isSelected()) { attributs=attributs+Font.ITALIC; } Font police; System.out.println(cboTaille.getSelectedItem().toString()); police=new Font(polices.getSelectedValue().toString(),attributs,Integer.parseInt (cboTaille.getSelectedItem().toString())); txt.setFont(police); }

ENI Editions - All rigths reserved

- 51 -

Principedefonctionnement
UneappletestuntypedapplicationJavaspcifiquepermettantdexcuterducodeJavalintrieurdunepageweb. Le but principal des applets est dajouter interactivit et dynamisme dans une page web. Lappel de lapplet est incorpor dans le code html de la page. Lorsque le navigateur analyse la page html que le serveur web vient de lui transmettreetrencontreunebalisecorrespondantuneapplet,iltlchargelecodedelappletetdmarrelexcution de ce code. Lavantage principal dune applet par rapport une application est incontestablement labsence dinstallation ncessaire sur les postes clients. Dautres avantages sont galement apprciables lors de lutilisation duneapplet :
q

Lesclientsdisposeronttoujoursdeladernireversionducode.chaquechargementdelapagewebparle navigateur,lecodedelappletestgalementtlchargpartirduserveurweb.Siunenouvelleversiondu code est disponible, celleci doit uniquement tre dploye sur le serveur web pour que tous les clients puissentenbnficier. Touteslesressourcesutilespourlebonfonctionnementdelapplicationserontdisponibles.Commelecodede lapplet,lesressourcesdontelleabesoinsontgalementtransfresduserveurwebverslenavigateur.Elles doiventdoncuniquementtreprsentessurleserveurweb. Lexcutionducodedelappletnerisquepasdeprovoquerdedgtssurleposteclient.Lorsquelamachine virtuelle Java du navigateur prend en charge lexcution du code elle le considre comme potentiellement dangereuxetlexcuteavecunensemblelimitdedroits.

Les applets comportent cependant un petit dsavantage puisquelles ne peuvent pas tre excutes de manire autonomeparlamachinevirtuelleJavadujdk.Ellesdoiventobligatoirementtreincorporesdansunepagehtmlpour tre prises en charge par la machine virtuelle Java dun navigateur. Le navigateur doit bien sr disposer dune telle machinevirtuelle.

ENI Editions - All rigths reserved

- 1-

Crationduneapplet
Pourquuneappletpuissetrepriseenchargeparunnavigateur,elledoitdisposerdecaractristiquesbienprcises. Lasolutionutilisepourtrecertainquelappletdisposedecescaractristiquesconsistecreruneclassehritant dune classe disposant dj de ces caractristiques. La personnalisation est ralise en substituant dans la classe ainsicre,certainesmthodeshritesdelaclassedebase.Lesclasses AppletetJAppletsontutilisablescomme classes de base pour la cration dune applet. La classe JApplet dfinie dans le package javax.swing permet lutilisation de composants de ce mme package pour la construction de linterface utilisateur de lapplet. Pour les appletsassurantellesmmeslagestiondeleuraspectgraphiqueouutilisantlescomposantsdelabibliothqueawt,la classe Applet doit tre utilise. La classe JApplet hrite de la classe Applet, elle tend donc ces fonctionnalits. La classeAppletfaitgalementpartieduneimportantehirarchie.

Dufaitdecettehirarchie,uneappletestdoncunobjetgraphiquequiestprisenchargeparlenavigateurquilaffiche.

1.Cycledevieduneapplet
Lorsque le navigateur prend en charge une applet, il excute certaines de ces mthodes en fonction des circonstances.Cesmthodespeuventtreclassesendeuxcatgories.
q

mthodesliesaucycledeviedelapplet. mthodesdegestiondelaspectgraphiquedelapplet.

Pourconcevoirdesappletsperformantesilfautbiencomprendrequandsontappelescesmthodesetquestceque lon peut en attendre. Limplmentation de certaines de ces mthodes dans la classe Applet est vide. Il est donc indispensabledelessubstituerdansnotreclasse.

a.Mthodesliesaucycledeviedelapplet
public void init() Cette mthode est excute ds la fin du chargement ou du rechargement de lapplet partir du serveur web. Cestenfaitlapremiremthodedelappletquiestexcuteparlenavigateur.Ellepermetdinitialiserlecontexte danslequelvafonctionnerlapplet.Oneffectuenotammentdanscettemthodelestraitementssuivants :
q

crationdesinstancesdesautresclassesutilesaufonctionnementdelapplet initialisationdesvariables crationdesthreads chargementdesimagesutilisesparlapplet rcuprationdesparamtrespasssdepuislapagehtml.

Dansuneapplicationclassique,cesoprationssontengnralexcutesdansleconstructeurdelaclasse. public void start() Cettemthodeestappeleparlenavigateuraprslaphasedinitialisationdelappletraliseparlamthodeinit. Elleestgalementappeleparlasuitechaquefoisquelapagesurlaquelleelleestinsreestrafficheparle navigateur.Cestparexemplelecassilutilisateurchangedepageetrevientensuitesurlapageprcdente(celle

ENI Editions - All rigths reserved

- 1-

contenantlapplet).Certainsnavigateursappellentgalementnouveaulamthodeinit.Ellecorrespondltape de dmarrage ou de redmarrage de lapplet. On y trouve par exemple le code permettant de dmarrer ou redmarrerlesthreadscrsdanslamthodeinit. public void stop() Cette mthode est utilise lors de la phase darrt de lapplet. Cette phase intervient principalement lorsque lutilisateur change de page. Elle peut galement tre excute lorsque lexcution de lapplet se termine normalement. Cest dans ce cas lapplet ellemme qui doit appeler cette mthode. La fermeture du navigateur provoquegalementlexcutiondecettemthodejusteavantlappeldelamthodedestroy. public void destroy() Cettemthodeestladernireducycledevieduneapplet.Lenavigateurlappellejusteavantsafermeture.Ellea lemmerlequeledestructeurduneclasse(mthodefinalize).Elleestutilisepourliminerdelammoireles objetsayanttcrspendantlefonctionnementdelappletetprincipalementceuxayanttcrsaucoursde lexcutiondelamthodeinit.Lasurchargedecettemthodenestabsolumentpasobligatoirecardetoutefaon legarbagecollectorintervientpourlibrerlesressourcesmmoireutilisesparlapplet.Ilnestdailleursmmepar certainquecettemthodepuissetreexcutecompltementavantquelenavigateurnarrtelamachinevirtuelle java.

b.Mthodesdegestiondelaspectgraphiquedelapplet
Ilfautconsidrerdeuxcasdefigure : Sivousutilisezdescomposantsgraphiques,telsqueceuxdisponiblesdanslesbibliothquesawtetswing,lerendu de linterface de lapplet est assur automatiquement. Cette possibilit provient des classes prsentes dans la hirarchie de la classe Applet ou JApplet. Cest dans ce cas la classe container dont hritent entre autres les appletsquieffectuentcetravailaveclamthodepaintComponents. Si vous assumez entirement la reprsentation graphique de lapplet, vous devez surcharger la mthode paint pourquellesoitcapabledegrerlaffichagedelappletchaquefoisquecellecidoittreredessinedanslapage web. Pour visualiser lordre dexcution de ces diffrentes mthodes, nous allons crire notre premire applet. Nous devonscreruneclassehritantdelaclasseApplet.DanscetteclassenousdclaronsunevariabledetypeString pourmmoriserlespassagesdanslesdiffrentesmthodes.Danslamthodepaint,nousaffichonslachanede caractressurlecontextegraphiquedelapplet. import java.applet.Applet; import java.awt.Graphics;

public class TestApplet extends Applet { private String message=""; public void destroy() { message=message + "mthode destroy \r\n"; } public void init() { message=message + "mthode init \r\n"; } public void start() { message=message + "mthode start \r\n"; } public void stop() { message=message + "mthode stop \r\n"; } public void paint(Graphics g) { message=message + "mthode paint \r\n";

- 2-

ENI Editions - All rigths reserved

g.drawString(message, 10, 20); } } Pourvrifierlebonfonctionnementdelapplet,nousdevonsinsrercellecidansunepagehtmletvisualisercette derniredansunnavigateurouavecloutilappletViewerdujdk. <html> <head> <title> premire applet </title> </head> <body> <h1>visualisation des appels des mthodes dune applet</h1> <applet code="TestApplet"></applet> </body> </html> La balise <applet> indique au navigateur quil doit, lors de lanalyse de la page html, charger la classe correspondant lapplet dont le nom est spcifi par lattribut code de la balise. Cette balise dispose de nombreusesautrespossibilitsquiserontdtaillesplusloindanscechapitre. Laffichagedelapagehtmlparunnavigateurestprsentcidessous.

Nousconstatonsquelamthodeinitpuislamthodestartonttexcutes.Ilsemblegalementquaumoins uneautremthodeaittexcutemaisnousnepouvonspasvisualiserdanssonintgralitletexteaffich.Ce problmeestliaufaitquelenavigateurrserveunespacepourlappletdansledocument.Lespacencessaire pour laffichage de la chane tant suprieur la largeur de lapplet, nous obtenons cet affichage tronqu. Nous verronsquenouspouvonsagirsurlesdimensionsdelespacealloulappletdanslapagehtmlaveclesattributs heightetwidthdelabalisemaiscettesolutionneferaqueretarderleproblmecarnousauronsforcmentun moment ou un autre une chane de caractres ncessitant une largeur plus importante que celle dont dispose lapplet. Nous devons donc apporter plus dattention, lors de la conception de lapplet, sa reprsentation graphique.

ENI Editions - All rigths reserved

- 3-

2.Construirelinterfaceutilisateurduneapplet
Pourconcevoirlinterfaceutilisateurdelappletnousavonsdeuxsolutions.Nouspouvonsutiliserunebibliothquede composants graphiques (awt ou swing) et utiliser ses composants pour dfinir laspect visuel de lapplet. Cette solutionprsentelavantagedtrerapidemettreen uvreetconvientdanslamajoritdescas.Leseulreproche quelon puisse lui faire est justement dutiliserdescomposantsclassiquespourlaffichageetdenepaspermettre desprsentationsspcifiques.Toutefoislamliorationetlvolutiondesbibliothquesgraphiquesprocurentdeplus en plus de possibilits. Si toutefois vous ne trouvez pas le composant correspondant vos besoins, vous pouvez assumercompltementlareprsentationgraphiquedelappletensurchargeantsamthodepaint.Nousallonsdans un premier temps utiliser cette solution en essayant dliminer les problmes rencontrs lors de notre exprimentation prcdente. Nous devons veiller ne pas dessiner audel des limites de lapplet.Pourcelanous allonsadopterladmarchesuivante :
q

Crerunepolicedecaractrespourlaffichage Obtenirlesdimensionsdelazonerservelapplet Dessiner les caractres les uns la suite des autres en vrifiant chaque fois que lespace disponible est suffisant Silespacenestpassuffisantsurlaligneactuelle,nousdevonsgrerlechangementdeligne.

Essayonsdersoudrelesproblmespartapes.

a.Crationdunepolicedecaractres
Unepolicedecaractresestdfinieparsonnometparsataille.Ilexisteunemultitudedepolicesdecaractreset rien ne nous garantit que celle que nous allons choisir sera disponible sur lordinateursurlequelnotreappletva tre excute. Pour pallier ce problme, Java propose des polices logiques qui sont au moment de lexcution convertiesenpolicesdisponiblessurleposteclient.Lespoliceslogiquessuivantessontdisponibles :
q

SansSerif Serif Monospaced Dialog DialogInput

La police relle utilise sera dtermine au moment de lexcution en fonction des disponibilits. Par exemple, la policelogiqueSansSerifseraconvertieenpoliceArialsurunsystmeWindows. La cration de la police est effectue en appelant le constructeur de la classe Font et en lui passant comme paramtreslenomdelapolice,lestyledelapolice(gras,italique),latailledelapolice. Font police=null; police =new Font("SansSerif",Font.PLAIN,14);

b.Obtenirlesdimensionsdelapplet
Lesdimensionsdelappletpeuventtrefixesparlenavigateurouparleconcepteurdelapagehtmllorsquecelui ci y insre lapplet. Ces dimensions peuvent tre obtenues au moment de lexcution en utilisant les mthodes getHeightetgetWidth. int largeur; int hauteur; largeur=getWidth(); hauteur=getHeight();

- 4-

ENI Editions - All rigths reserved

c.Dessinerlescaractres
LamthodedrawStringdelaclasseGraphicspermetlaffichagedunechanedecaractresaveclapolicespcifie aupralableparlamthodesetFont.LamthodedrawStringattendcommeparamtres:
q

lachanedecaractres lapositionhorizontaleoesteffectulaffichage lapositionverticaleoesteffectulaffichage.

Cettemthodenegrepasdenotiondecurseuretilnousincombedonclobligationdefournirchaqueappelune positioncorrectepourlaffichage. g.drawString(texte,positionX,positionY);

d.Dterminerlesdimensionsdunechane
Pourpouvoirgrercorrectementlaffichage,nousdevonsvrifierquilrestesuffisammentdespacedisponiblepour lachaneafficher.Cetespacedpendbiensrdunombredecaractresdelachaneetgalementdelapolice utilise. De plus, certaines polices ayant un espacement proportionnel, il faut plus despace pour afficher le caractreWquepourafficherlecaractrei.Ilnestdoncpasenvisageabledesebasersurunelargeurconstante pour chaque caractre. La classe FontMetrics nous apporte une aide prcieuse pour rsoudre ce problme. Un objetdeFontMetricspeuttreobtenuenutilisantlamthodegetFontMetricsducontextegraphiquedelapplet. Cette mthode attend comme paramtre la police de caractres avec laquelle elle va effectuer ses calculs. La largeur ncessaire pour afficher une chane de caractres donne est ensuite obtenue en appelant la mthode stringWidth laquelle il faut fournir la chane de caractres "mesurer". La hauteur est elle obtenue avec la mthodegetHeight.Lahauteurtantuniquementlielapolicedecaractres,ilnestpasncessairedefournirla chanedecaractrespourobtenircetteinformation. Maintenantquenousavonstousleslmentsutiles,voicicommentlesutiliserpourrsoudrenotreproblme. import import import import java.awt.Font; java.awt.FontMetrics; java.awt.Graphics; javax.swing.JApplet;

public class TestApplet2 extends JApplet { private String message=""; public void destroy() { message=message + "mthode destroy \r\n"; } public void init() { message=message + "mthode init \r\n"; } public void start() { message=message + "mthode start \r\n"; } public void stop() { message=message + "mthode stop \r\n"; } public void paint(Graphics g) { // cration de la police de caractres Font police=null; police =new Font("SansSerif",Font.PLAIN,14);

ENI Editions - All rigths reserved

- 5-

// affectation de la police au contexte graphique g.setFont(police); // dtermination de la largeur et de la hauteur de lapplet int largeurApplet; int hauteurApplet; largeurApplet=getWidth(); hauteurApplet=getHeight(); // cration dun objet FontMetrics pour obtenir des informations // sur la taille des caractres FontMetrics fm; fm=g.getFontMetrics(police); int hauteurPolice; int largeurCaractere; hauteurPolice=fm.getHeight(); // dclaration des variables pour grer la position daffichage int curseurX; int curseurY; curseurX=0; curseurY=hauteurPolice; message=message + "methode paint \r\n"; // boucle de traitement des caractres un un for (int i=0;i<message.length();i++) { // rcupration du caractre traiter et de sa largeur String caractereCourant; caractereCourant=message.substring(i,i+1); largeurCaractere=fm.stringWidth(caractereCourant); // vrification sil reste de la place sur la ligne if (curseurX+largeurCaractere>largeurApplet) { // passage au dbut de la ligne suivante curseurY=curseurY+hauteurPolice; curseurX=0; } // affichage du caractre la position courante g.drawString(caractereCourant,curseurX,curseurY); // mise jour de la position du curseur curseurX=curseurX+largeurCaractere; } } } Envrifiantlefonctionnementdelapplet,nousconstatonsquilyaunenetteamliorationparrapportlaversion prcdente.

- 6-

ENI Editions - All rigths reserved

Ilyabienencorequelquesamliorationsapporternotammentpourlagestiondudfilementverticalmaisnous allons plutt essayer une autre solution en confiant laspect graphique de lapplet des composants spcialiss. Laffichage avec dfilement de texte est une fonctionnalit courante que doit proposer une application et les concepteursdesbibliothquesgraphiquesdeJavaontbiensrconusdescomposantsadaptscesbesoins.Les classes TextArea et ScrollPane vont nous permettre de rsoudre notre problme. La mise en uvre est extrmement simple puisquil suffit de crer une instance de la classe TextArea en indiquant dans lappel du constructeurlesdimensionssouhaites.CetteinstancedoitensuitetreconfieaucomposantScrollPane qui va assurer le dfilement du texte. Lensemble est ensuite ajout sur lapplet. Lajout de texte est effectu trs simplement en appelant la mthode append de la classeTextArea. Notre nouvelle version dapplet prend donc la formesuivante. import import import import java.applet.Applet; java.awt.Graphics; java.awt.ScrollPane; java.awt.TextArea;

public class TestApplet3 extends Applet { ScrollPane defil; TextArea txt; private String message=""; public void destroy() { message=message + "mthode destroy \r\n"; } public void init() { txt=new TextArea(50,50); defil=new ScrollPane(); defil.add(txt); add(defil); txt.append("mthode init \r\n"); } public void start() { txt.append("mthode start \r\n"); }

ENI Editions - All rigths reserved

- 7-

public void stop() { txt.append("mthode stop \r\n"); } public void paint(Graphics g) { txt.append("mthode paint \r\n"); } } Le code est nettement plus simple que celui de la version prcdente et pourtant le rsultat est beaucoup plus professionnel.

3.Lesimagesdanslesapplets
Laffichageduneimagedansuneappletseffectueentroisoprationsdistinctes:
q

lechargementdelimagepartirdunfichier letraitementventueldelimage letraagedelimagesurlecontextegraphiquedelapplet.

Nousallonsdtaillerchacunedecesoprations.

a.Chargementduneimage
La classe Applet propose deux versions de la mthode getImage permettant le chargement dune image partir

- 8-

ENI Editions - All rigths reserved

dunfichiergifoujpeg.LapremireversionattendantcommeparamtrelURLcompltedufichiercontenantlimage. LasecondeattendcommepremierparamtregalementuneURLetcommedeuximeparamtreunnomrelatif cetteURLpermettantlaccsaufichiercontenantlimage.Lesdeuxsolutionssuivantessontutilisables. private Image img; img=getImage(new URL("http://www.eni-ecole.fr/images/ecole.jpg"));

private Image img; img=getImage(new URL("http://www.eni-ecole.fr/"),"images/ecole.jpg"); CesdeuxsolutionsontpournormeinconvnientdutiliserdescheminsabsoluspourlesURLs.Ilesttrsprobable quau moment de la conception de lapplet, on ne sache pas encore sur quel serveur et sous quel nom va tre dployelapplication.Ilestdoncimpossibledutiliserdirectementcetteinformationdanslecode.Parcontre,nous pouvons tre certains que si notre code sexcute cest que le navigateur la tlcharg. Nous pouvons donc questionner lapplet pour quelle nous indique lemplacement partir duquel le navigateur la tlcharg. La mthode getCodeBase nous permet dobtenir lURL du rpertoire contenant lapplet sur le serveur. Il ne faut cependantpasoublierquesilappletestdisponibledanslenavigateurcestqueceluiciaaupralabletlcharg unepagehtmlcontenantlapplet.LURLdecettepageestobtenueparlamthodegetDocumentBase. Il est donc possible dadresser le fichier contenant limage partir de lun ou lautre de ces emplacements. Cest lorganisationdelapplicationquivanousdicterlabonnemthode.
q

Silimagesetrouvedanslerpertoire,ouunsousrpertoire,oestplacelapagehtmlvousdevezutiliser lamthodegetDocumentBase. Silimagesetrouvedanslerpertoire,ouunsousrpertoire,oestplacelecodedelappletvousdevez utiliserlamthodegetCodeBase.

Aveclorganisationsuivante :

Limageestaccessibledanslappletaveclecodesuivant : img=getImage(getDocumentBase(),"images/duke.gif"); Aveccetteautreorganisation :

Limageestaccessibleaveccecode : img=getImage(getCodeBase(),"images/duke.gif");

b.Traitementdelimage
Si des traitements spcifiques doivent tre effectus avec limage avant son affichage, vous pouvez obtenir des

ENI Editions - All rigths reserved

- 9-

informationssurcelleciparlintermdiairedesmthodesdelaclasseImage.

c.Traagedelimage
Cestenfaitlecontextegraphiquedelappletquivarellementprendreenchargelaffichagedelimagesurlapplet. Pourcela,laclasseGraphicsfournitsixversionsdiffrentesdelamthodedrawImage. public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer) Affichelimageauxcoordonnesxety. public abstract boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) Affichelimageauxcoordonnesxetyetremplitlesportionstransparentesdelimageaveclacouleurspcifiepar bgcolor.Lersultatestquivalentunaffichagedelimagesurunrectangleayantpourcouleurbgcolor. public abstract boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) Affichelimageauxcoordonnesxetyetredimensionnelimageaveclalargeurwidthetlahauteurheight. public abstract boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) Affichelimageauxcoordonnesxetyetredimensionnelimageaveclalargeurwidthetlahauteurheightetremplit lesportionstransparentesdelimageaveclacouleurspcifieparbgcolor. public abstract boolean drawImage(Image img, int dx1, int dy1,

- 10 -

ENI Editions - All rigths reserved

int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) Affichelapartiedelimagedlimiteparlerectangleformpar(sx1,sy1)et(sx2,sy2)danslerectangleformpar (dx1, dy1) et (dx2, dy2). La partie de limage dessiner est redimensionne automatiquement pour remplir exactementlerectanglededestination. public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) Affichelapartiedelimagedlimiteparlerectangleformpar(sx1,sy1)et(sx2,sy2)danslerectangleformpar (dx1, dy1) et (dx2, dy2). La partie de limage dessiner est redimensionne automatiquement pour remplir exactementlerectanglededestinationetremplitlesportionstransparentesdelimageaveclacouleurspcifiepar bgcolor. Pourtoutescesmthodes,uneinstancedeclasseimplmentantlinterfaceImageObserverdoittrefournie.Cette instancedeclasseestutilisepoursuivrelvolutionduchargementdelimage. Voicicidessousquelquesexemplesdecodeetlaffichagecorrespondant. img=getImage(getCodeBase(),"images/duke.gif"); g.drawImage(img,0,0,this);

img=getImage(getCodeBase(),"images/duke.gif"); g.drawImage(img,0,0,20,20,this); g.drawImage(img,30,0,50,50,this); g.drawImage(img,90,0,100,100,this);

ENI Editions - All rigths reserved

- 11 -

img=getImage(getCodeBase(),"images/duke.gif"); g.drawImage(img,0,0,100,100,30,30,50,50,this);

4.Lesthreadsdanslesapplets
Avant dtudier comment crer un Thread, nous allons tout dabord dfinir ce terme. La majorit des machines disposentdunseulprocesseurpourassurerleursfonctionnements.Ceprocesseurnepeutbiensrraliserquune seuleoprationlmentairelafoisetpourtantaveclaplupartdessystmesdexploitationnouspouvonsexcuter plusieurs applications simultanment. En fait nous avons limpression que plusieurs applications sexcutent simultanmentmaisenralitilnennestrien.Poursimulercettesimultanit,lesystmedexploitation"dcoupe" le temps processeur disponible en trs fines tranches et distribue ces tranches aux diffrentes applications. La commutation tant trs rapide nous avons limpression que toutes les applications sexcutent simultanment. La programmationmultithreadappliquecemmeprincipeuneapplication.Sinousprenonslexempleduntraitement de texte, celuici peut par exemple effectuer plusieurs oprations simultanment (saisie de texte, vrification de lorthographe, mise en page, impression). Pour pouvoir effectuer tous ces traitements, lapplication ralise nouveauundcoupagedechaquetranchedetempsprocesseurqueluifournitlesystmedexploitationetaffecte chaquetcheraliseruneportiondecettetranche.

- 12 -

ENI Editions - All rigths reserved

Pardfaut,uneapplicationouuneappletcomporteunThreadresponsabledelexcutiondevotrecode.Celuiciest parfoisnommthreadprincipal.Lajoutdunoudeplusieursthreadssupplmentairesestparfoisutilepourconserver une bonne ractivit de lapplication. Dans le cas dune applet, nous pouvons par exemple ajouter un thread pour effectueruneoprationdinitialisationrelativementlongue.Sicetteoprationesteffectueparlamthodeinitde lapplet,lenavigateurdevraattendrelafindecettemthodepourpoursuivreledmarragedelapplet.Parcontre,si dans la mthode init nous dmarrons un nouveau thread pour effectuer lopration dinitialisation, la suite du dmarrage de lapplet sera excute plus rapidement pendant que le thread continuera deffectuer linitialisation. Cettetechniqueesttrsutilepouruneappletutilisantdesfichierssons.Lefichierpeutainsitretlchargpendant quesepoursuitlinitialisationdelapplet. Lesthreadssontgalementtrsutileslorsquuneappletdoitraliseruntraitementrptitif.Nouspouvonsconfier unnouveauthreadlesoindexcutercetraitementsansperturberlefonctionnementdurestedelapplet. Lutilisationdesthreadsncessitetroistapesdanslaconceptiondelapplication:
q

crerunnouveauthread dfinirletraitementquedoiteffectuerlenouveauthread grerlesdmarragesetarrtsduthread.

Voiciledtaildecestroistapes.

a.Crationdunnouveauthread
La classe Thread permet la cration et la gestion dun thread. Comme pour nimporte quelle autre classe, il faut crer une instance par lintermdiaire dun des constructeurs disponibles. Il est noter que la cration dune instancedelaclasseThreadnedclenchepasledmarragedelexcutionduthread.

b.Dfinirletraitementeffectuer
Lorsquunthreadestdmarr,ilexcuteautomatiquementsamthoderun.Pardfautcettemthodeestdfinie danslaclasseThreadmaisnecontientaucuncode.Ilestdoncobligatoirederedfinircettemthode.Cecipeuttre
ENI Editions - All rigths reserved - 13 -

faitencrantuneclassehritantdelaclasseThreadetenredfinissantdanscellecilamthoderun. public class ThreadPerso extends Thread { public void run() { // code excuter par le thread } } Cestbiensrdanscecasuneinstancedecetteclassequilfaudracrer. Vouspouvezgalementobtenirlemmersultatencrantuneinstancedeclasseinterneanonyme. Thread t; t=new Thread(){ public void run() { // code excuter par le thread } }; Laderniresolutionconsisteindiquerauthreadquelamthoderunquildoitexcutersetrouvedansuneautre classe.IlfautdanscecasfourniruneinstancedecetteclasselorsdelappelduconstructeurdelaclasseThread. Pour tre certain que la classe utilise contienne bien une mthode run, celleci devra implmenter linterface Runnable.Cecipeuttreprisenchargeparlaclassedelapplet. public class TestApplet5 extends Applet implements Runnable { Thread th; public void run() { // code excuter par le thread }

public void start() { th=new Thread(this); } } Ilrestemaintenantdfinirlecontenudelamthoderun.Deuxcasdefiguresontpossibles :


q

Lamthoderunexcuteuntraitementuniquedanscecaselleestconuecommeunemthodeclassiqueet sonexcutionsetermineraavecladernireinstructiondecettemthode. Lamthoderunexcuteuntraitementcycliqueetdanscecaselledoitconteniruneboucleseterminantla disparitionduthreadlexcutant.Onpeutparexempleutiliserlasyntaxesuivantepourcetteboucle.

public void run() { Thread t ; t= Thread.currentThread() ; while(th==t) { // code excuter par le thread } } La mthode statique currentThread permettant dobtenir une rfrence sur le thread courant, cette boucle se termineradsquelavariablethnerfrencerapluslethreadcourant.Ceseraparexemplelecassilonaffectela
- 14 ENI Editions - All rigths reserved

valeurnullcettevariable. Ilestparfoisncessairedecontrlerlafrquencedexcutiondesinstructionsdelaboucleenyinsrantunappel la mthode statique sleep de la classeThread. Cette mthode "endort" le thread courant pendant le nombre de millisecondesquiluiestpasscommeparamtre.Lappeldecettemthodedoittreprotgparunbloctry catch. Thread t ; t= Thread.currentThread() ; while(th==t) { // code excuter par le thread // endort le thread pendant 500 ms try { Thread.sleep(500); } catch (InterruptedException e){} }

c.Dmarreretarrterunthread
Ledmarragedunthreadestdclenchparunappelsamthodestart.Cestcetappelquiprovoquelexcution de la mthoderunduthread.Ilnefautsurtoutpasappelerdirectementlamthoderunduthreadcarelleserait alors excute par le thread courant (le principal) de lapplet. Ceci rduirait nant tous nos efforts et pourrait mmeprovoquerleblocagedelappletsilamthoderuncontientuneboucle(lecodepermettantdefairevoluerla condition de sortie de boucle ne pouvant plus sexcuter puisque dans ce cas, lexcution de la mthode run monopoliselethreadprincipal). Larrt du thread est provoqu par la fin de lexcution de sa mthode run soit parce que la dernire instruction quelle contient est termine ou parce que la boucle quelle contient est termine. La mthode stop, pourtant prsentedanslaclasseThread,nedoitpastreutilisecarelleprsentedesrisquesdeblocagedelapplication. PourillustrerlutilisationdesthreadsvoiciuneappletpermettantdefairegrossirpuismaigrirDukeencontinu. import java.applet.Applet; import java.awt.Graphics; import java.awt.Image; public class TestApplet5 extends Applet implements Runnable { Thread th; final int MAXI=100; final int MINI=10; int largeur=MINI; int hauteur=MINI; Image img; public void run() { boolean grossir=true; Thread t; t=Thread.currentThread(); while (th==t) { if(largeur>MAXI & grossir) { grossir=false; } if (largeur<MINI & !grossir) { grossir=true; } if (grossir) { largeur++; hauteur++; } else

ENI Editions - All rigths reserved

- 15 -

{ largeur--; hauteur--; } repaint(); try { th.sleep(10); } catch (InterruptedException e) {} } } public void init() { img=getImage(getCodeBase(),"images/duke.gif"); } public void start() { th=new Thread(this); th.start(); } public void stop() { th=null; } public void paint(Graphics g) { g.drawImage(img,30,0,largeur,hauteur,this); } }

5.Lessonsdanslesapplets
La classe Applet propose deux mthodes permettant le chargement dun fichier audio. La mthode getAudioClip nest utilisable qu partir dune applet, alors que la mthode newAudioClip peut tre utilise dans nimporte quel typedapplicationpuisquelleestdclarestaticdanslaclasseAppletetdecefaitaccessiblesansquuneinstance delaclasseAppletexiste.CesdeuxmthodesacceptentcommeargumentunobjetURLreprsentantlemplacement du fichier audio. Une surcharge de la mthode getAudioClip acceptant comme deuxime paramtre une chane de caractres est galement disponible. Ce deuxime paramtre reprsente le chemin relatif lURL passe comme premier paramtre pour obtenir le fichier audio. Cette mthode est trs utile puisquelle permet demployer les mthodes getCodeBase ou getDocumentBase pour obtenir lURL de lapplet ou lURL de la page html et de spcifier ensuite le chemin daccs vers le fichier audio par rapport cette URL. Ces mthodes retournent une instance de classeimplmentantlinterfaceAudioClip.Cetteinterfacedfinitlesmthodesplay,loopetstoppermettantdejouer lefichieraudiounefois,enboucleoudelarrter.Lessonsdanslesappletsdoiventtreutilissavecmodrationet prcautionsouspeinednerver rapidement lutilisateurdelapplet.Ilfautparexempleprendreencomptequeles fichiersaudiosontparfoisassezvolumineuxdoncassezlongstlcharger.SilamthodegetAudioClipestutilise danslamthodeinitdelapplet,ilfaudraattendrelafindutlchargementdufichieraudiopourquelappletpuisse treutilise.Ilestprfrablededmarrer,danscettemthodeinit,unthreadchargdetlchargerlefichieraudio etdelancersarestitutionlafindutlchargement. Il faut galement garder prsent lesprit que la machine virtuelle Java du navigateur conserve les instances des appletscresjusqulafermeturedunavigateur.SiuneappletaexcutlamthodeloopsurunobjetAudioClip, lefichierserarestituenbouclejusqulafermeturedunavigateur,mmesilutilisateurnaviguesuruneautrepage quecellecontenantlapplet.IlestdoncprudentdappelerlamthodestopdelobjetAudioClipdanslamthodestop delapplet. import java.applet.Applet; import java.applet.AudioClip; public class TestAppletAudio extends Applet implements Runnable { AudioClip ac;
- 16 ENI Editions - All rigths reserved

public void init() { Thread th; th=new Thread(this); th.start(); } public void start() { if (ac!=null) { ac.loop(); } } public void stop() { if (ac!=null) { ac.stop(); } } public void run() { ac=getAudioClip(getCodeBase(),"son.wav"); ac.loop(); } }

ENI Editions - All rigths reserved

- 17 -

Dploiementduneapplet
La solution utilise pour le dploiement duneappletdansunepagehtmlpeuttredpendantedelemplacement partir duquel est accessible la page html. Si la page est accessible partir dInternet, il faut utiliser une technique permettantpratiquementnimportequelnavigateurdevisualiserlapagecontenantlapplet. Silapagehtmlestaccessibleuniquementpartirdunintranetetquelesnavigateursdesmachinesdelintranetsont tous du mme type, vous pouvez utiliser une technique spcifique ce type de navigateur. Si la page html est accessibleuniquementpartirdunintranetetquelesnavigateursdesmachinesdelintranetsontdetypediffrents, vousdevezsoitutiliserlammetechniquequepourlesaccspartirdInternet,soitpersonnaliserlapagehtmlpour quellesadapteaunavigateurclient.

1.Insertiondansunepagehtml
Troisbalisessontdisponiblespourlinsertionduneappletdansunepagehtml: <applet> :baliseuniverselleinterprtepartouslesnavigateurs. <object> :balisespcifiquepourInternetExplorer. <embed> :anciennebalisespcifiquepourunnavigateurNetscape. Voicilemodedemploidecestroisbalises.

a.Balise<applet>
Cette balise est la balise standard du html pour linsertion dune applet. La configuration de lapplet se fait par lintermdiairedesnombreuxattributsdelabalise.Certainsdecesattributssontobligatoires.
q

code="nom de la classe de lapplet" : cet attribut permet dindiquer au navigateur le nom du fichier contenantlaclasseprincipaledelapplet.Noubliezpasenindiquantlenomdecefichierquenoussommes dans le monde Java et quil y a distinction entre minuscules et majuscules. Respectez donc bien la casse pourcenomdefichier.dfautdautresinformations,lenavigateuressaiedechargercefichierpartirdu mmecheminqueceluidoprovientlapagehtml. width="largeur en pixels" : cet attribut indique au navigateur la largeur de la surface quil doit rserver surlapagehtmlpourlaffichagedelapplet. height="hauteur en pixels" :cetattributindiqueaunavigateurlahauteurdelasurfacequildoitrserver surlapagehtmlpourlaffichagedelapplet.

Lasyntaxeminimaledebasedelabaliseappletestdonclasuivante : <applet code= "duke.class" width="200" height="200"> </applet> Lesattributssuivantssontgalementdisponiblespourlabaliseapplet :


q

codebase="chemin daccs" : cet attribut indique au navigateur le chemin daccs au fichier contenant la classe principale de lapplet si celuici nest pas dans le mme rpertoire que la page html contenant lapplet.Silappletfaitpartiedunpackagelenomdeceluicidoittreindiquaveclenomdelaclasseet nonaveccetattribut. archive="nom dun fichier jar" : si lapplet ncessite plusieurs fichiers pour pouvoir fonctionner il est souventplusefficacedelesregrouperdansunearchiveJava.Lenavigateurnadanscecasquecefichier tlcharger pour obtenir tout ce quil lui faut pour faire fonctionner lapplet. Sinon il doit tlcharger les fichiersununaveclacrationchaquetlchargementdefichierdunenouvelleconnexionhttpversle serveur.Lefichierdoittregnraveclutilitairejardontlefonctionnementestdtailldanslechapitre consacraudploiementdapplications. align="constante dalignement" :cetattributindiquecommentlappletestaligneparrapportllment quilasuitdanslapagehtml.Huitvaleursdeconstantessontdisponibles :
q

left :lappletestalignegauchedellmentquilasuit.

ENI Editions - All rigths reserved

- 1-

right:lappletestalignedroitedellmentquilasuit. texttop :lehautdelappletestalignsurlehautdellmenttextequisuitlapplet. top :lehautdelappletestalignsurlehautdellmentquilasuit. absmiddle :lemilieudelappletestalignsurlemilieudellmentquisuitlapplet. middle :lemilieudelappletestalignsurlemilieudelalignedebasedutextequisuitlapplet. bottom :lebasdelappletestalignsurlalignedebasedutextequisuitlapplet. absbottom :lebasdelappletestalignsurllmentleplusbasquisuitlapplet.

vspace="espace vertical en pixels" :cetattributindiqueaunavigateurlespacequildoitlaisserlibreau dessusetaudessousdelapplet. hspace="espace horizontal" :cetattributindiqueaunavigateurlespacequildoitlaisserlibregaucheet droitedelapplet.

Labaliseappletpeutellemmecontenirdutexte.Celuicinapparatradanslenavigateurquesilnestpascapable deprendreenchargelexcutiondelappletJava. Exempledebalise<applet> : <applet code="TestApplet4" width="150" height="150" align="left" vspace="50" hspace="50" codebase="appletsApplication" archive="data.jar" > Votre navigateur ne gre pas les applets </applet>

b.Balise<object>
CettebaliseestspcifiqueInternetExplorer.Lesattributssuivantssontreconnusparcettebalise :
q

classid="identifiant du plug-in" :cetattributpermetdindiquercommentsecomporteInternetExplorer pourlagestiondesdiffrentesversionsdepluginjava.Cettegestionpeuttredynamiqueetdanscecas lidentifiantdupluginesttoujourslesuivant : clsid:8AD9C840-044E-11D1-B3E9-00805F499D93 Aveccettesolution,InternetExplorervrifiesildisposeduneversiondeplugingaleousuprieurecelle spcifieparlattributcodebase.Sicestlecas,laversiondisponibleestutilisepourexcuterlapplet.Sila version prsente sur le navigateur est infrieure la version ncessaire ou si aucun plugin java nest installalorslutilisateurestsollicitpourinstallerlaversionrequise. Pourutiliserlagestionstatique,lidentifiantduplugindoitavoirlaformesuivante : clsid:CAFEEFAC-AAAA-BBBB-CCCC-ABCDEFFEDCBA LestroisgroupesAAAA,BBBBetCCCCidentifientlaversiondupluginrequisepourlexcutiondelapplet. Parexemple,pourlepluginjavaversion1.6.0,leclassidestlesuivant : clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA

- 2-

ENI Editions - All rigths reserved

Silenavigateurnedisposepasdecetteversionexacte,lutilisateurestsollicitpourlinstaller.
q

codebase="url de tlchargement # version requise" :cetattributindiquequelleversiondupluginjava estncessairepourquInternetExplorerpuisseexcuterlapplet.Sicetteversionnestpasdisponiblesurle navigateur, lURL du fichier dinstallation est alors utilise pour proposer le tlchargement de la version requise.Pourexigerlaversion1.6.0,lattributcodebasedoitavoirlaformesuivante : codebase="http://java.sun.com/update/1.6.0/jinstall-6windows-i586.cab#version=6.0.0.99" Lesattributsheight,widthetalignsontidentiquesceuxdelabaliseapplet.Parcontre,lesinformations liesaucodedelappletnesontpasindiquespardesattributsdelabalise<object>maispardesbalises <param> imbriques dans cette balise. Chacune de ces balises comporte un attribut name et un attribut value.Lesattributssuivantssontdfinispourcesbalises<param>.

type :dtermineletypedellmentinsrdanslapageparcettebalise.Cetattributprcisegalementla version du JRE ncessaire pour le bon fonctionnement de llment insr sur la page et comment se comportelenavigateursicetteversionnestpasdisponible.Cetattributprenddonclaformesuivantepour unegestionstatiquedesversionsduJRE. <PARAM name="type" value="application/x-java-applet;jpi-version=1.6.0_01"> Danscecaslaversion1.6.0_01estexigepourlefonctionnementdelapplet.Siellenestpasdisponible, lutilisateurestinvitlatlcharger. Aveclaformesuivantelaversionindiqueouuneversionultrieurepeuttreutilisesielleestdisponible. Lutilisateur nest invit tlcharger la version correcte que sil dispose dune version infrieure ou bien daucunJRE. <PARAM name="type" value="application/x-java-applet;version=1.6.0">

java_codebase :dterminelURLpartirdelaquellelenavigateurdoittlchargerlapplet.CetteURLpeut tre absolue ou relative. Cette balise est facultative si lapplet se trouve dans le mme rpertoire que la pagehtmlsurlaquelleelleestinsre. <PARAM name="java_codebase" value="/appli/code">

code :indiquelenomdufichiercontenantlecodedelapplet. <PARAM name="code" value="duke.class">

archive :indiquelenomdufichierarchiveassocilapplet. <PARAM name="archive" value="duke.jar">

Exempledebaliseobject: <object classid="clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA" codebase="http://java.sun.com/update/1.6.0/jinstall-6-windowsi586.cab#version=6.0.0.99" width="150" height="150" > <PARAM name="type" value="application/x-java-applet;jpiversion=1.6.0_01"> <PARAM name="java_codebase" value="appletsApplication"> <PARAM name="code" value="TestApplet4.class"> </object>

c.Balise<embed>
Cette balise est spcifique Netscape. Elle ne doit plus tre utilise puisque maintenant tous les navigateurs modernesreconnaissentlabaliseobject.Ellenestprsenteiciquepourvousaiderlorsdelamiseniveaudune

ENI Editions - All rigths reserved

- 3-

application.Lesattributssuivantssontreconnusparcettebalise:
q

type :dtermineletypedellmentinsrdanslapageparcettebalise.Cetattributprcisegalementla version du JRE ncessaire pour le bon fonctionnement de llment insr sur la page et comment se comportelenavigateursicetteversionnestpasdisponible.Cetattributprenddonclaformesuivantepour unegestionstatiquedesversionsduJRE. <embed type="application/x-java-applet;jpi-version=1.6.0_01" ... Danscecas,laversion1.6.0_01estexigepourlefonctionnementdelapplet.Siellenestpasdisponible, lutilisateurestinvitlatlcharger. Aveclaformesuivante,laversionindiqueouuneversionultrieurepeuttreutilisesielleestdisponible. Lutilisateur nest invit tlcharger la version correcte que sil dispose dune version infrieure ou bien daucunJRE. <embed type="application/x-java-applet;version=1.6.0" ...

codebase : dtermine lURLpartirdelaquellelenavigateurdoittlchargerlapplet.CetteURLpeuttre absolueourelative.Cettebaliseestfacultativesilappletsetrouvedanslemmerpertoirequelapage htmlsurlaquelleelleestinsre. <embed codebase="/appli/code" ...

code :indiquelenomdufichiercontenantlecodedelapplet. <embed code="duke.class" ...

archive :indiquelenomdufichierarchiveassocilapplet. <embed archive="duke.jar" ...

2.Paramtrageduneapplet
Les applications classiques peuvent recevoir des informations au moment de leur excution par lintermdiaire des paramtrespassssurlalignedecommande.Cesparamtressontutilisablesdanslecodedelapplicationgrceau tableaudechanesdecaractresreucommeargumentdanslamthode maindelapplication.Lesappletsntant pas excutes partir de la ligne de commande mais par le navigateur qui analyse une page html, cest donc lintrieurdecelleciquevonttredfinislesparamtres.Ceuxcisontensuitercuprsparlecodedelapplet.

a.Dfinirlesparamtres
Les paramtres sont dfinis par des balises <param> imbriques lintrieur de la balise <applet>. Ces balises doiventavoirobligatoirementdeuxattributs.Lepremier, name,permetdidentifier le paramtre. Le second,value, correspondlavaleurduparamtre.

b.Rcuprationdesparamtresdanslapplet
La valeur dun paramtre est obtenue par la mthode getParameter de la classe applet. Celleci attend comme argument une chane de caractres reprsentant le nom du paramtre dont on souhaite obtenir la valeur. Cette mthoderetournetoujoursunechanedecaractres.Siunparamtrereprsenteunautretypededonne,ildevra treconvertiexplicitementparlecodedelappletenutilisantparexemplelesclasseswrapper(Integer,Float,Long, ).Sil nexistepasdanslabalise<applet>deparamtreaveclenomindiqu,lamthode getParameterretourne unevaleurnull. Lexcutiondelappletnedoitbiensrpastreperturbeparcettesituationetdoitfournirune valeur par dfaut pour le paramtre manquant. La rcupration des paramtres peut tre faite dans la mthode initdelappletcommedanslexemplesuivant : import java.applet.Applet; import java.awt.Graphics; import java.awt.Image; public class TestApplet5 extends Applet implements Runnable

- 4-

ENI Editions - All rigths reserved

{ Thread th; int MAXI=100; int MINI=10; int largeur=MINI; int hauteur=MINI; Image img;

public void init() { String min; String max; min=getParameter("minimum"); if(min!=null) { MINI=Integer.parseInt(min); } max=getParameter("maximum"); if(max!=null) { MAXI=Integer.parseInt(max); } MAXI=Integer.parseInt(max); img=getImage(getCodeBase(),"images/duke.gif"); } ... } Lecodesuivantpermetdinsrercetteappletsurunepagehtmlenspcifiantunevaleurpourlesdeuxparamtres attendusparlapplet. <applet code="TestApplet5" width="250" height="250"> <param name="minimum" value="20"> <param name="maximum" value="250"> </applet>

3.Scuritdansuneapplet
LemondedInternetnedisposepasdunerputationdescuritabsolue.Cestencoreplussensiblelorsquilsagit de code provenant dInternet comme cest le cas pour une applet. Pour garantir la scurit du systme sur lequel sexcute une applet, les navigateurs instaurent une politique de scurit assez stricte visvis dune applet. Chaquenavigateurimplmentesaproprepolitiquedescuritmaisenprincipelesrestrictionssuivantessappliquent uneapplet.
q

Une applet ne peut pas charger de bibliothque ni appeler de mthode native comme par exemple une fonction du systme dexploitation. Les applets doivent donc se contenter de leur propre code et des fonctionnalitsmisesleurdispositionparlamachinevirtuelleJavaquiassureleurexcution. Une applet ne peut pas lire un fichier existant sur la machine sur laquelle elle sexcute. Cette limitation sappliquebiensraussipourlcrituredunfichieretsasuppression. Uneappletnepeutpastablirdeconnexionrseauavecuneautremachinesaufaveclamachinedoelle provient. Uneappletnepeutpaslancerlexcutionduneapplicationsurlamachinesurlaquelleellemmesexcute. Uneappletdisposedunaccslimitauxpropritsdusystme. Lorsquuneappletafficheunefentrependantsonexcution,cettefentreestmarquepourbiensignaler lutilisateurquelleprovientdelexcutiondelappletetnonduneapplicationlocale.

ENI Editions - All rigths reserved

- 5-

4.Communicationentreapplets
Lesappletsprsentessurunepagehtmlontlapossibilitdedialoguerentreelles.Cedialoguenestpossiblequ certainesconditionsimposesparlenavigateur.
q

Lesappletsdoiventtoutesprovenirdummeserveur Ellesdoiventgalementprovenirdummerpertoiresurceserveur(codebaseidentique) Ellesdoiventaussitreexcutessurlammepage,dansunemmefentredenavigateur.

Pourquuneappletpuissetablirundialogueavecuneautreapplet,cellecidoitobtenirunerfrenceverslapplet contacter.CetterfrencepeuttreobtenueenutilisantlamthodegetAppletetenfournissantcommeargument cettemthodelenomdelappletconcerne.Ilfautbiensrquelappletsoitnommeaumomentdesoninsertionsur la page html. Un nom peut tre affect une applet en ajoutant lattribut name sa balise ou en ajoutant un paramtreappelnamesabalise.Lesdeuxsyntaxessuivantessontidentiques : <applet code="TestApplet5" width="250" height="250"> <param name="minimum" value="20"> <param name="maximum" value="250"> <param name="name" value="duke"> </applet>

<applet code="TestApplet4" width="250" height="250" name="duke"> </applet> La mthode getApplet est associe au contexte de lapplet sur lequel vous pouvez obtenir une rfrence par lintermdiairedelamthodegetAppletContext. Ilestprudentdevrifierlavaleurrenvoyeparcettemthodepoursassurerquelappletabienttrouvesurla pageavantdessayerdyaccder. Applet ap; ap=getAppletContext().getApplet("duke1"); if (ap!=null) { ap.setBackground(Color.CYAN); } Cettesolutionexigebiensrdeconnatrelenomaveclequellappletestinsresurlapagehtml. Unedeuximesolutionpermetdesaffranchirdecettecontrainteenobtenantlalistedetouteslesappletsprsentes sur la page html. Cest dans ce cas la mthode getApplets qui permet dobtenir une numration sur la liste des applets. Applet ap; Enumeration e; e=getAppletContext().getApplets();

- 6-

ENI Editions - All rigths reserved

while (e.hasMoreElements()) { ap=(Applet)e.nextElement(); if (ap!=this) { ap.setBackground(Color.CYAN); } else { ap.setBackground(Color.PINK); } } Ilconvientdtreprudentaveccettesolutioncarlappletpartirdelaquellesexcutececodefaitbiensrpartiede laliste(elleestelleaussisurlapagehtml !).Ilfautdanscecaseffectueruntestsilonneveutpasqueletraitement sappliquelappletactuelleousilonsouhaiteeffectueruntraitementdiffrent.

5.Interactionaveclenavigateuretlesystme
Les applets sont gres par le navigateur qui analyse la page html sur laquelle elles sont insres, elles peuvent doncavoiruneinteractionavecceluici.Ellesontgalementdroitunaccslimitcertainespropritsdusystme.

a.Affichagesurlaconsole
Au cours du dveloppement dune applet, vous allez vous apercevoir rapidement quun lment fait cruellement dfaut : la console. Elle nous rend en effet de grands services en phase de test dune application en y faisant afficherdesmessagespourindiquerquuneportiondecodeabientexcute,ouencore,enyfaisantafficherle contenudecertainesvariables.Enfaitcetteconsoleestbiendisponiblemmepouruneappletmaiselleestdans cecaspriseenchargeparlenavigateur.Cestdoncparsonintermdiairequevouspouvezobtenirsonaffichage. Le moyen dafficher la console est spcifique chaque navigateur. Pour Internet Explorer, elle est affiche par lintermdiairedumenuOutils.

Laspectdelaconsoledpendgalementdunavigateur.Ellepeuttreunesimplefentredinvitedecommandeen mode texte ou une application graphique comme avec Internet Explorer. Quel que soit son aspect, les deux flux System.out et System.err sont toujours dirigs vers cette console. Pour notre premire applet, nous aurions pu utiliserlecodesuivant : import java.applet.Applet; import java.awt.Graphics;

public class TestApplet extends Applet {

ENI Editions - All rigths reserved

- 7-

public void destroy() { System.out.println("mthode destroy); } public void init() { System.out.println("mthode init); } public void start() { System.out.println("mthode start); } public void stop() { System.out.println("mthode stop"); } public void paint(Graphics g) { System.out.println("mthode paint"); } } Etainsiobtenirlersultatsuivantsurlaconsole :

- 8-

ENI Editions - All rigths reserved

b.Utilisationdelabarredtatdunavigateur
Vouspouvezgalementutiliserlabarredtatdunavigateurpourlaffichagedemessagesdestinslutilisateurde lapplet.LaccslabarredtatsefaitgrcelamthodeshowStatus.Cettemthodereoitcommeargumentla chane de caractres afficher. Cette barre dtatnest parfois pas trs visible et surtout son contenu peut tre modifitoutmomentparuneautreappletouparlenavigateurluimme.

c.Affichagedunepagehtml
Laffichagedundocumenthtmlestbiensrlaspcialitdunnavigateur.Cestdoncluiquedoitsadresserlapplet sielleabesoindevisualiserunteldocument.LamthodeshowDocumentducontextedelappletpermetdeffectuer cetteopration.Cettemthodeestdisponiblesousdeuxformes.LapremireformeattendcommeparamtrelURL dudocumentafficher.Ledocumentestaffichlaplacedelapagehtmlosetrouvelapplet. Try { getAppletContext().showDocument(new URL("http://www.eni.fr")); } catch (MalformedURLException e) { e.printStackTrace(); }

Cette mthode nacceptepascommeparamtreunechanedecaractresmaisuneinstancedelaclasse URL. Cette instance doit tre cre partir de la chane de caractres reprsentant lURL de la page afficher. Lutilisation du constructeur de la classe URL exige la prsence du bloctry catch ou dune instruction throws.

Ladeuximeformeattendunechanedecaractrescommedeuximeparamtrepouridentifierlemplacemento seraaffichelapage.Lesvaleurssuivantessontacceptespourcettechane. _blank :ledocumentestaffichdansunenouvellefentredunavigateur. _self :ledocumentestaffichlaplacedelapageosetrouvelapplet. _parent :ledocumentestaffichdanslafentreparentedecelleoestaffichelapagecontenantlapplet. _top :ledocumentestaffichdanslecadredeplushautniveau. nomDeCadre : le document est affich dans le cadre dsign par le nom spcifi. Si ce cadre nexiste pas, une nouvellefentreestcrepourafficherledocument.

d.Obtenircertainespropritsdusystme
Pourquelapplet puisse sadapteraumieuxlenvironnementdanslequelellesexcute,elleaaccscertaines proprits du systme. Ces proprits sont accessibles par la mthode getProperty de la classe System. Cette mthode accepte comme paramtre une chane de caractres indiquant le nom de la proprit dont on souhaite obtenirlavaleur.Lespropritssuivantessontaccessiblesdepuisuneapplet : Nomdelaproprit file.separator path.separator Valeurobtenue Caractreutiliscommesparateurdanslescheminsdaccsauxfichiers Caractreutiliscommesparateurentredeuxcheminsdaccs(variable denvironnementpath) NomdufournisseurduJRE URLdusitewebdufournisseurduJRE VersionduJRE Caractredesparationdelignes

java.vendor java.vendor.url java.version line.separator

ENI Editions - All rigths reserved

- 9-

os.arch os.name

Plateformedusystmedexploitation Nomdusystmedexploitation

LappletsuivanteaffichecesdiffrentespropritsdanslaconsoleJavadunavigateur: import java.applet.Applet;

public class Proprietes extends Applet { public void start() { System.out.print("version du jre \t"); System.out.println(System.getProperty("java.version")); System.out.print("fournisseur du jre \t"); System.out.println(System.getProperty("java.vendor")); System.out.print("site web du fournisseur du jre \t"); System.out.println(System.getProperty("java.vendor.url")); System.out.print("nom du systme dexploitation \t"); System.out.println(System.getProperty("os.name")); System.out.print("plateforme du systme dexploitation \t"); System.out.println(System.getProperty("os.arch")); System.out.print("sparateur dans les chemins daccs \t"); System.out.println(System.getProperty("file.separator")); System.out.print("sparateur dans la variable PATH \t"); System.out.println(System.getProperty("path.separator")); } }

- 10 -

ENI Editions - All rigths reserved

Principedefonctionnementdunebasededonnes
Les bases de donnes sont devenues des lments incontournables de la majorit des applications. Elles se substituent lutilisation de fichiers grs par le dveloppeur luimme. Cet apport permet un gain de productivit important lors du dveloppement et une amlioration significative des performances des applications. Elles facilitent galement le partage dinformations entre utilisateurs. Pour pouvoir utiliser une base de donnes, vous devez connatreunminimumdevocabulairelicettetechnologie.

1.Terminologie
Danslecontextedesbasesdedonneslestermessuivantssontfrquemmentutiliss :
q

Base de donnes relationnelle : une base de donnes relationnelle est un type de base de donnes qui utilise des tables pour le stockage des informations. Elles utilisent des valeurs issues de deux tables pour associer les donnes dune table aux donnes dune autre table. En rgle gnrale, dans une base de donnesrelationnelle,lesinformationsnesontstockesquuneseulefois. Table : une table est un composant dune base de donnes qui stocke les informations dans des enregistrements (lignes) et dans des champs (colonnes). Les informations sont en gnral regroupes par catgorie au niveau dune table. Par exemple, nous aurons la table des Clients, des Produits, ou des Commandes. Enregistrement : lenregistrement est lensemble des informations relatives un lment dune table. Les enregistrements sont les quivalents au niveau logique des lignes dune table. Par exemple un enregistrementdelatableClientscontientlescaractristiquesdunclientparticulier. Champ :unenregistrementestcomposdeplusieurschamps.Chaquechampdunenregistrementcontient une seule information sur lenregistrement.ParexempleunenregistrementClientpeutcontenirleschamps CodeClient,Nom,Prnom Clprimaire :uneclprimaireestutilisepouridentifierdemanireuniquechaquelignedunetable.Lacl primaireestunchampouunecombinaisondechampsdontlavaleurestuniquedanslatable.Parexemplele champ CodeClient est la cl primaire de la table Client. Il ne peut pas y avoir deux clients ayant le mme code. Cl trangre : une cl trangre reprsente un ou plusieurs champs dune table qui font rfrence aux champs de la cl primaire dune autre table. Les cls trangres indiquent la manire dont les tables sont lies. Relation :unerelationestuneassociationtablieentredeschampscommunsdansdeuxtables.Unerelation peuttredeunun,unplusieursouplusieursplusieurs.Grceauxrelations,lesrsultatsderequtes peuventcontenirdesdonnesissuesdeplusieurstables.UnerelationdeunplusieursentrelatableClient etlatableCommandepermetunerequtederenvoyertouteslescommandescorrespondantunclient.

2.LelangageSQL
AvantdepouvoircrireuneapplicationJavautilisantdesdonnes,vousdeveztrefamiliarisaveclelangageSQL (StructuredQueryLanguage).Celangagepermetdedialogueraveclabasededonnes.Ilexistediffrentesversions du langage SQL en fonction de la base de donnes utilise. Cependant SQL dispose galement dune syntaxe lmentairenormaliseindpendantedetoutebasededonnes.

a.Recherchedinformations
LelangageSQLpermetdespcifierlesenregistrementsextraireainsiquelordredanslequelvoussouhaitezles extraire.VouspouvezcreruneinstructionSQLquiextraitdesinformationsdeplusieurstablessimultanment,ou vous pouvez crer une instruction qui extrait uniquement un enregistrement spcifique. Linstruction SELECT est utilisepourrenvoyerdeschampsspcifiquesduneoudeplusieurstablesdelabasededonnes. LinstructionsuivanterenvoielalistedesnomsetprnomsdetouslesenregistrementsdelatableClient.

ENI Editions - All rigths reserved

- 1-

SELECT Nom,Prenom FROM Client Vouspouvezutiliserlesymbole*laplacedelalistedeschampspourlesquelsvoussouhaitezlavaleur. SELECT * FROM Client Vous pouvez limiter le nombre denregistrements slectionns en utilisant un ou plusieurs champs pour filtrer le rsultatdelarequte.Diffrentesclausessontdisponiblespourexcutercefiltrage. ClauseWHERE Cetteclausepermetdespcifierlalistedesconditionsquedevrontremplirlesenregistrementspourfairepartiedes rsultatsretourns.LexemplesuivantpermetderetrouvertouslesclientshabitantNantes. SELECT * FROM Client WHERE Ville=Nantes Lasyntaxedelaclausencessitelutilisationdesimplecotepourladlimitationdeschanesdecaractres. ClauseWHEREIN Vous pouvez utiliser la clause WHERE IN pour renvoyer tous les enregistrements qui rpondent une liste de critres.Parexemple,vouspouvezrecherchertouslesclientshabitantenFranceouenEspagne. SELECT * FROM Client WHERE Pays IN (France,Espagne)

ClauseWHEREBETWEEN Vous pouvez galement renvoyer une slection denregistrements qui se situent entre deux critres spcifis. La requtesuivantepermetdercuprerlalistedescommandespassesaumoisdenovembre2005. SELECT * from Commandes WHERE DateCommande BETWEEN 01/11/05 AND 30/11/05

ClauseWHERELIKE Vous pouvez utiliser la clause WHERE LIKE pour renvoyer tous les enregistrements pour lesquels il existe une condition particulire pour un champ donn. Par exemple, la syntaxe suivante slectionne tous les clients dont le nomcommenceparund : SELECT * FROM Client WHERE Nom LIKE d% Danscetteinstruction,lesymbole%estutilispourremplacerunesquencedecaractresquelconque. ClauseORDERBY Vous pouvez utiliser la clause ORDER BY pour renvoyer les enregistrements dans un ordre particulier. LoptionASC indique un ordre croissant, loption DESC indique un ordre dcroissant. Plusieurs champs peuvent tre spcifis comme critre de tri. Ils sont analyss de la gauche vers la droite. En cas dgalit sur la valeur dun champ, le champsuivantestutilis. SELECT * FROM Client ORDER BY Nom DESC,Prenom ASC Cetteinstructionretournelesclientstrisparordredcroissantsurlenometencasdgalitparordrecroissant surleprnom.

b.Ajoutdinformations
La cration denregistrementsdansunetablesefaitparlacommande INSERT INTO.Vousdevezindiquerlatable danslaquellevoussouhaitezinsreruneligne,lalistedeschampspourlesquelsvousspcifiezunevaleuretenfin lalistedesvaleurscorrespondantes.Lasyntaxecomplteestdonclasuivante: INSERT INTO client (codeClient,nom,prenom) VALUES (1000,Dupond,Pierre) Lorsdelajoutdecenouveauclient,seullenometleprnomserontrenseignsdanslatable.Lesautreschamps prendrontlavaleurNULL.Silalistedeschampsnestpasindique,linstructionINSERTexigequevousspcifiezune valeurpourchaquechampdelatable.Voustesdoncobligdutiliser le mot clNULLpourindiquerquepourun

- 2-

ENI Editions - All rigths reserved

champ particulier il ny a pas dinformation. Si la table Client est compose de cinq champs (codeClient,nom,prenom,adresse,pays)linstructionprcdentepeuttrecriteaveclasyntaxesuivante : INSERT INTO client VALUES (1000,Dupond,Pierre,NULL,NULL) noterquedanscecaslesdeuxmotclsNULLsontobligatoirespourleschampsadresseetpays.

c.Misejourdinformations
LamodificationdeschampspourdesenregistrementsexistantsseffectueparlinstructionUPDATE.Cetteinstruction peutmettrejourplusieurschampsdeplusieursenregistrementsdunetablepartirdesexpressionsquiluisont fournies.Vousdevezfournirlenomdelatablemettrejourainsiquelavaleuraffecterauxdiffrentschamps. La liste est indique par le mot cl SET suivi de laffectation de la nouvelle valeur aux diffrents champs. Si vous voulez que les modifications ne portent que sur un ensemble limit denregistrements, vous devez spcifier la clauseWHEREafindelimiterlaportedelamisejour.SiaucuneclauseWHEREnestindiquelamodificationsefera surlensembledesenregistrementsdelatable. Parexemplepourmodifierladressedunclientparticulier,vouspouvezutiliserlinstructionsuivante : UPDATE Client SET adresse= 4 rue de Paris 44000 Nantes WHERE codeClient=1000 Silamodificationportesurlensembledesenregistrementsdelatable,laclause WHEREestinutile.Parexemplesi voussouhaitezaugmenterleprixunitairedetousvosarticles,vouspouvezutiliserlinstructionsuivante : UPDATE CATALOGUE SET prixUnitaire=prixUnitaire*1.1

d.Suppressiondinformations
Linstruction DELETE FROM permet de supprimer un ou plusieurs enregistrements dune table. Vous devez au minimumfournirlenomdelatablesurlaquellevasefairelasuppression.Sivousnindiquezpasplusdeprcisions, dans ce cas toutes les lignes de la table sont supprimes. En gnral une clause WHERE est ajoute pour limiter ltenduedelasuppression.LacommandesuivanteeffacetouslesenregistrementsdelatableClient : DELETE FROM Client Lacommandesuivanteestmoinsradicaleetnesupprimequunenregistrementparticulier : DELETE FROM Client WHERE codeClient=1000 Le langage SQL est bien sr beaucoup plus complet que cela et ne se rsume pas ces cinq instructions. Nanmoins,ellessontsuffisantespourlamanipulationdedonnespartirdeJava.Sivoussouhaitezapprofondir lapprentissagedulangageSQLjevousconseilledeconsulterundesouvragesdisponiblesdanslammecollection traitantdecesujetdemanirepluspousse.

ENI Editions - All rigths reserved

- 3-

Accsunebasededonnespartirdejava
Lorsque lon souhaite manipuler une base de donnes partir dun langage de programmation, deux solutions sont disponibles :
q

Communiquerdirectementaveclabasededonnes. Utiliserunecouchelogicielleassurantledialogueaveclabasededonnes.

Lapremiresolutioncomporteplusieursexigences.
q

Vousdevezparfaitementmatriserlaprogrammationrseau. Vousdevezgalementconnatreendtailleprotocoleutilisparlabasededonnes. Ce type de dveloppement est souvent trs long et parsem dembches. Par exemple les spcifications du protocolesontellesaccessibles ? Toutvotretravaildevratrerecommencsivouschangezdetypedebasededonnescarlesprotocolesne sontbiensrpascompatiblesdunebasededonneslautre.Pireparfoismmeduneversionlautredune mmebasededonnes.

La deuxime solution est bien sr prfrable et cest celleci que les concepteurs de Java ont choisie. Ils ont donc dvelopplabibliothquejdbcpourlaccsunebasededonnes.Plusprcismentlabibliothquejdbcestcompose dedeuxparties.Lapremirepartiecontenuedanslepackagejava.sqlestessentiellementcomposedinterfaces.Ces interfaces sont implmentes par le pilote jdbc. Ce pilote nest pas dvelopp par Sun mais en gnral par le concepteurdelabasededonnes.Cesteffectivementcedernierquimatriselemieuxlatechniquepourcommuniquer avec la base de donnes. Il existe quatre types de pilotes jdbc avec des caractristiques et des performances diffrentes.
q

Type1 :Pilotejdbcodbc Cetypedepilotenestpasspcifiqueunebasededonnesmaisiltraduitsimplementlesinstructionsjdbcen instructions odbc. Cest ensuite le pilote odbc qui assure la communication avec la base de donnes. Cette solution noffre que des performances mdiocres. Ceci est principalement li au nombre de couches logicielles mises en uvre. Les fonctionnalits jdbc sont galement limites par les fonctionnalits de la couche odbc. Cependant cette solution vous permet daccder pratiquement nimporte quelle base de donnes. Elle doit treenvisagelorsquilnexistepasdautrepilotedisponible.

Type2 :Pilotenatif CetypedepilotenestpasentirementcritenJava.LapartiedecepilotecriteenJavaeffectuesimplement desappelsversdesfonctionsdupilotenatif.CesappelssonteffectusgrcelAPIJNI(JavaNativeInterface). Comme pour les pilotes de type 1, il y a donc une traduction ncessaire entre le code Java et la base de donnes.Cependant,cetypedepiloteesttoutdemmeplusefficacequelespilotesjdbcodbc.

Type3 :piloteutilisantunserveurintermdiaire Ce pilote dvelopp entirement en Java ne communique pas directement avec la base de donnes mais sadresseunserveurintermdiaire.Ledialogueentrelepiloteetleserveurintermdiaireeststandardquel que soit le type de base de donnes. Cest ensuite ce serveur intermdiaire qui transmet les requtes en utilisantunprotocolespcifiquelabasededonnes.

Type4 :piloteentirementcritenjava Ce type de pilote reprsente la solution idale puisquil ny a aucun intermdiaire. Le pilote transmet directement les requtes la base de donnes en utilisant le protocole propre la base de donnes. La majoritdespilotessontmaintenantdecetype.

1.Prsentationdejdbc

ENI Editions - All rigths reserved

- 1-

Labibliothquejdbcfournitunensembledeclassesetsurtoutdinterfacespermettantlamanipulationdunebasede donnes. Ces lments reprsentent tout ce dont vous avez besoin pour accder aux donnes partir dune applicationjava.Leschmacidessousreprendlecheminementlogiquedepuislepilotejusquauxdonnes.

La classe DriverManager est notre point de dpart. Cest elle qui assure la liaison avec le pilote. Cest par son intermdiaire que nous pouvons obtenir une connexion vers la base de donnes. Celleci est reprsente par une instance de classe implmentant linterface Connection. Cette connexion est ensuite utilise pour transmettre des instructions vers la base. Les requtes simples sont excutes grce linterface Statement, les requtes avec paramtreslesontaveclinterfacePreparedStatementetlesprocduresstockesaveclinterfaceCallableStatement. Les ventuels enregistrements slectionns par linstruction SQL sont accessibles avec un lment Resultset.Nous allonsdtaillercesdiffrentestapesdanslesparagraphessuivants.

2.Chargementdupilote
Lapremiretapeindispensableestdobtenirlepilotejdbcadaptvotrebasededonnes.Engnral,cepiloteest disponibleentlchargementsurlesiteduconcepteurdelabasededonnes.Pournosexemples,nousutiliseronsle pilotefourniparMicrosoftpouraccderunserveurdebasededonnesSQLServer2005.Ilpeuttretlcharg ladressesuivante :http://msdn.microsoft.com/enus/data/aa937724.aspx Aprs dcompression du fichier, vous devez obtenir un rpertoire contenant le pilote luimme sous forme dune archive java (sqljdbc.jar) et de nombreux fichiers daide sur lutilisation de ce pilote. Le fichier archive contient les classes dveloppes par Microsoft qui implmentent les diffrentes interfaces jdbc. Ce fichier devra bien sr tre accessibleaumomentdelacompilationetdelexcutiondelapplication. Ce pilote doit ensuite tre charg grce la mthode forName de la classe Class. Cette mthode attend comme paramtre une chane de caractres contenant le nom du pilote. Il est ce niveau indispensable de parcourir la documentationdupilotepourobtenirlenomdelaclasse.Dansnotrecas,cetteclasseportelenomsuivant: com.microsoft.sqlserver.jdbc.SQLServerDriver Lenregistrementdupilotesefaitdoncaveclinstructionsuivante: Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Le pilote permettant laccs une source de donnes ODBC est lui directement disponible avec le JDK. Il peut tre chargaveclasyntaxesuivante : Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Leschanesdecaractrespassescommeparamtresreprsententdesnomsdeclasses,ellessontdoncsensibles

- 2-

ENI Editions - All rigths reserved

lacasse.LinstructionforNamedoitdailleurstreprotgeparunbloctry catchcarelleestsusceptiblededclencher uneexceptiondetypeClassNotFoundException.

3.tabliretmanipulerlaconnexion
Aprs son chargement, le pilote est maintenant capable de nous fournir une connexion vers le serveur de base de donnes.

a.tablirlaconnexion
LamthodegetConnectiondelaclasseDriverManagersechargedecetravail.Celleciproposetroissolutionspour tablir la connexion. Chacune des versions de cette mthode attend comme paramtre une chane de caractres reprsentantuneURLcontenantlesinformationsncessairespourtablirlaconnexion.Lecontenudecettechane decaractresestspcifiquechaquepiloteetilfautnouveauconsulterladocumentationpourobtenirlabonne syntaxe. Le dbut de cette chane de caractres est cependant standard avec la forme suivante jdbc :nomDuProtocole. Le nom du protocole est propre chaque pilote et cest grce ce nom que la mthode getConnectionestcapabledidentifierlebonpilote.Lerestedelachaneestluicompltementspcifiquechaque pilote.Ilcontientengnrallesinformationspermettantdidentifierleserveuretlabasededonnessurceserveur verslaquellelaconnexiondoittretablie.PourlepiloteMicrosoft,lasyntaxedebaseestlasuivante : jdbc:sqlserver://localhost;databaseName=northwind; user=thierry;password= secret; PourlepiloteODBC,lasyntaxeestplussimplepuisquilsuffitsimplementdespcifierlenomdelasourceODBC laquellevousvoulezvousconnecter.CettesourceODBCdoitbiensravoirtcreaupralable. jdbc:odbc:nwd Encasdesuccs,lamthode getConnection retourne une instance de classe implmentant linterfaceConnection. Dans certains cas, il est prfrable dutiliser la deuxime version de la mthode getConnection car celleci permet dindiquer le nom et le mot de passe utiliss pour tablir la connexion comme paramtres spars de lURL de connexion. Voici deux exemples permettant dtablir une connexion vers une mme base de donnes. Le premier utiliselepiloteMicrosoft. import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnexionDirecte { public static void main(String[] args) { try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch (ClassNotFoundException e) { System.out.println("erreur pendant le chargement du pilote"); } Connection cnxDirect=null; try { cnxDirect=DriverManager.getConnection("jdbc:sqlserver: //localhost;databaseName=northwind; user=thierry;password=secret;"); } catch (SQLException e) { System.out.println("erreur pendant la connexion"); } } } LesecondutiliselepiloteODBC. import java.sql.Connection;

ENI Editions - All rigths reserved

- 3-

import java.sql.DriverManager; import java.sql.SQLException; public class ConnexionDirecte { public static void main(String[] args) { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch (ClassNotFoundException e) { System.out.println("erreur pendant le chargement du pilote"); } Connection cnxOdbc=null; try { cnxOdbc=DriverManager.getConnection("jdbc:odbc:nwd","thierry","secret"); } catch (SQLException e) { System.out.println("erreur pendant la connexion"); } } }

b.Manipulerlaconnexion
Une connexion est ouverte ds sa cration. Il ny a donc pas de mthode permettant douvrir une connexion. Par contre,uneconnexionpeuttrefermeenappelantlamthodeclose.Aprslafermetureduneconnexion,ilnest pluspossibledelutiliseretelledoittrerecrepourpouvoirtrenouveauutilisable.LafonctionisClosedpermet de vrifier si une connexion est ferme. Si cette fonction retourne un boolean qui est gal false, on peut donc lgitimementpenserquelaconnexionestouverteetpermetdoncdedialogueraveclabasededonnes.Cenest enfaitpastoujourslecas.Laconnexionpeutparfoistredansuntatintermdiaire :ellenestpasfermemaiselle ne peut pas tre utilise pour transfrer des instructions vers le serveur. Pour vrifier la disponibilit de la connexion,vouspouvezutiliserlamthodeisValid.Cettemthodetesterellementladisponibilitdelaconnexion en essayant denvoyer une instruction SQL et en vrifiant quelle obtient bien une rponse de la part du serveur. Cettemthodenestpasimplmentedanstouslespilotesetsiellenelestpas,sonappeldclencheuneexception dutypejava.lang.UnsupportedOperationExceptionouuneerreurdutypejava.lang.AbstractMethodError. Si vous effectuez uniquement des oprations de lecture sur la base de donnes vous pouvez optimiser la communicationenprcisantquelaconnexionestenlectureseule.LamthodesetReadOnlypermetdemodifierce paramtragedelaconnexion.LtatpeutensuitetretestenutilisantlamthodeisReadOnly.Pourcertainspilotes cettefonctionnalitnestpasimplmenteetlamthodesetReadOnlynaaucuneffet.Lafonctionsuivantevrifiesi cettefonctionnalitestdisponiblepourlaconnexionquiluiestpassecommeparamtre. public static void testLectureSeule(Connection cnx) { boolean etat; try { etat = cnx.isReadOnly(); cnx.setReadOnly(!etat); if (cnx.isReadOnly() != etat) { System.out .println("le mode lecture seule est pris en charge par ce pilote"); } else { System.out .println("le mode lecture seule n\est pas pris en charge par ce pilote"); } cnx.setReadOnly(etat); } catch (SQLException e)

- 4-

ENI Editions - All rigths reserved

{ e.printStackTrace(); } } Lors de lexcution dune instruction SQL, le serveur peut dtecter des problmes et de ce fait gnrer des avertissements. Ces avertissements peuvent tre rcuprs par la mthode getWarnings de la connexion. Cette mthoderetourneunobjetSQLWarningreprsentatifduproblmerencontrparleserveur.Siplusieursproblmes sontrencontrsparleserveurceluicignreplusieursobjetsSQLWarningchanslesunsauxautres.Lamthode getNextWarning permet dobtenirllment suivant ou null si la liste est termine. La liste peut tre vide avec la mthodeclearWarnings.Lafonctionsuivanteaffichetouslesavertissementsreusparlaconnexion. public static void affichageWarnings(Connection cnx) { SQLWarning avertissement; try { avertissement=cnx.getWarnings(); if (avertissement==null) { System.out.println("il n\y a pas d\avertissement "); } else { while (avertissement!=null) { System.out.println(avertissement.getMessage()); System.out.println(avertissement.getSQLState()); System.out.println(avertissement.getErrorCode()); avertissement=avertissement.getNextWarning(); } } cnx.clearWarnings(); } catch (SQLException e) { e.printStackTrace(); } } Engnral,lorsdelacrationdelurldeconnexion,lundesparamtresdecetteURLdterminelenomdelabase verslaquellevoussouhaiteztabliruneconnexion.DanslecasovousutilisezunesourcededonnesODBC,cest le nom de cette source de donnes qui doit tre indiqu, le nom de la base de donnes devant tre prcis au momentdelacrationdelasourcededonnes.Danscecas,lenomdelabasededonnespeuttreobtenuparla mthodegetCatalog.Lamodificationdunomdelabasededonneslaquellevoustesconnectseraliseavecla mthodesetCataloglaquelleilfautfournirlenomduneautrebaseprsentesurlemmeserveur.Ilfautbiensr quelecompteaveclequelvousavezouvertlaconnexiondisposedesdroitsdaccssuffisantspourcettebasede donnes.noterquaveccettemthode,nouschangeonsdebasededonnesmaislaconnexionconcernetoujours lemmeserveur.Ilnyaaucunmoyendechangerdeserveursanscrerunenouvelleconnexion. Lecodesuivant: System.out.println("base actuelle : " +cnxDirect.getCatalog()); System.out.println("changement de base de donnes"); cnxDirect.setCatalog("garage"); System.out.println("base actuelle : " +cnxDirect.getCatalog()); nousaffiche: base actuelle : northwind changement de base de donnes base actuelle : garage La structure de la base peut galement tre obtenue avec la mthode getMetaData. Cette mthode retourne un objet DataBaseMetaData fournissant de trs nombreuses informations sur la structure de la base. La fonction suivanteafficheuneanalyserapidedecesinformations. public static void infosBase(Connection cn) { ResultSet rs;

ENI Editions - All rigths reserved

- 5-

DatabaseMetaData dbmd; try { dbmd=cn.getMetaData(); System.out.println("type de base : " + dbmd.getDatabaseProductName()); System.out.println("version: " + dbmd.getDatabaseProductVersion()); System.out.println("nom du pilote : " + dbmd.getDriverName()); System.out.println("version du pilote : " + dbmd.getDriverVersion()); System.out.println("nom de l\utilisateur : " + dbmd.getUserName()); System.out.println("url de connexion : " + dbmd.getURL()); rs=dbmd.getTables(null,null,"%",null); System.out.println("structure de la base"); System.out.println("base\tschema\tnom table\ttype table"); while(rs.next()) { for (int i = 1; i <=4 ; i++) { System.out.print(rs.getString(i)+"\t"); } System.out.println(); } rs.close(); rs=dbmd.getProcedures(null,null,"%"); System.out.println("les procdures stockes"); System.out.println("base\tschema\tnom procedure"); while(rs.next()) { for (int i = 1; i <=3 ; i++) { System.out.print(rs.getString(i)+"\t"); } System.out.println(); } rs.close(); } catch (SQLException e) { e.printStackTrace(); } } Toutes ces mthodes peuvent un jour ou lautre vous rendre service mais le but principal dune connexion est de permettrelexcution dinstructionsSQL.Cestdoncellequivanousfournirlesobjetsncessairespourlexcution decesinstructions.TroistypesdinstructionsSQLpeuventtreexcuts :
q

Lesrequtessimples Lesrequtesprcompiles Lesprocduresstockes.

chacundecestypescorrespondunobjetJDBC:
q

Statementpourlesrequtessimples PreparedStatementpourlesrequtesprcompiles CallableStatementpourlesprocduresstockes.

Etenfinchacundescesobjetspeuttreobtenuparunemthodediffrentedelaconnexion:
q

createStatementpourlesobjetsStatement

- 6-

ENI Editions - All rigths reserved

prepareStatementpourlesobjetsPreparedStatement prepareCallpourlesobjetsCallableStatement.

Lutilisationdecesmthodesetdecesobjetsestdtailledansleparagraphesuivant.

4.ExcutiondinstructionsSQL
Avant lexcution dune instruction SQL vous devez choisir le type dobjet JDBC le plus appropri. Les rubriques suivantesdcriventlestroistypesdobjetsdisponiblesetleurutilisation.

a.ExcutiondinstructionsdebaseaveclobjetStatement
Cet objet est obtenu par la mthode createStatement de la connexion. Deux versions de cette mthode sont disponibleslapremirenattendaucunparamtre.Danscecas,silobjetStatementestutilispourexcuterune instructionSQLgnrantunjeudenregistrements(select),celuiciseraenlectureseuleetavecundfilementen avant.Lesinformationsprsentesdanscejeudenregistrementsnepourrontpastremodifiesetleparcoursdu jeudenregistrementsnepourrasefairequedupremierenregistrementversledernierenregistrement.Ladeuxime version permet de choisir les caractristiques du jeu denregistrements gnr. Elle accepte deux paramtres. Le premierdtermineletypedujeudenregistrements.Lesconstantessuivantessontdfinies :
q

ResultSet.TYPE_FORWARD_ONLY :lejeudenregistrementsseradfilementenavantseulement. ResultSet.TYPE_SCROLL_INSENSITIVE : le jeu denregistrements pourra tre parcouru dans les deux sens maisserainsensibleauxchangementseffectusdanslabasededonnespardautresutilisateurs. ResultSet.TYPE_SCROLL_SENSITIVE : le jeu denregistrements pourra tre parcouru dans les deux sens et serasensibleauxchangementseffectusdanslabasededonnespardautresutilisateurs.

Leseconddterminelespossibilitsdemodificationdesinformationscontenuesdanslejeudenregistrements.Les deuxconstantessuivantessontdfinies :
q

ResultSet.CONCUR_READ_ONLY :lesenregistrementssontenlectureseule. ResultSet.CONCUR_UPDATABLE :lesenregistrementspeuventtremodifisdanslejeudenregistrements.

CetobjetestlepluslmentairepermettantlexcutiondinstructionsSQL.Ilpeutprendreenchargelexcutionde nimporte quelle instruction SQL. Vous pouvez donc excuter aussi bien des instructions DDL (Data Definition Language) que des instructions DML (Data Manipulation Language). Il faut simplement choisir dans cet objet la mthodelaplusadaptepourlexcutionducodeSQL.Lechoixdecettemthodeestdictparletypedersultat quedoitfournirlinstructionSQL.Quatremthodessontdisponibles :
q

public boolean execute(String sql) :cettemthodepermetlexcutiondenimportequelleinstructionSQL. Le boolean retourn par cette mthode indique si un jeu denregistrements a t gnr (true) ou si simplement linstruction a modifi des enregistrements dans la base de donnes (false). Si un jeu denregistrementsestgnr,ilpeuttreobtenuparlamthodegetResultSet.Sidesenregistrementsont t modifis dans la base de donnes, la mthode getUpdateCount retourne le nombre denregistrements modifis.Lafonctionsuivanteillustrelutilisationdecesmthodes.

public static void testExecute(Connection cnx) { Statement stm; BufferedReader br; String requete; ResultSet rs; boolean resultat; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_ READ_ONLY); br=new BufferedReader(new InputStreamReader(System.in));

ENI Editions - All rigths reserved

- 7-

System.out.println("saisir votre instruction SQL :"); requete=br.readLine(); resultat=stm.execute(requete); if (resultat) { System.out.println("votre instruction a gnr un jeu d\enregistrements"); rs=stm.getResultSet(); rs.last(); System.out.println("il contient " + rs.getRow() + " enregistrements"); } else { System.out.println("votre instruction a modifi des enregistrements dans la base"); System.out.println("nombre denregistrements modifis :" + stm.getUpdateCount()); } } catch (SQLException e) { System.out.println("votre instruction n\a pas fonctionn correctement"); } catch (IOException e) { e.printStackTrace(); } }

public Resultset executeQuery(String requete) :cettemthodeestconuespcialementpourlexcution dinstructions select. Le jeu denregistrements est disponible directement comme valeur retourne par la fonction. public int executeUpdate(String requte) : cette mthode est parfaitement adapte pour lexcution dinstructions modifiant le contenu de la base de donnes comme les instructions insert, update, delete. Lentierretournparcettefonctionindiquelenombredenregistrementsaffectsparlamodification. public int[] executeBatch() :cettemthodepermetdexcuterunensembledinstructionsSQLparlot.Le lot dinstructions excuter doit tre prpar au pralable avec les mthodes addBatch etclearBatch. La premirereoitcommeparamtreunechanedecaractresreprsentantuneinstructionSQLajouterau lot.Lasecondepermetderinitialiserlelotdinstructions.Ilnestpaspossibledesupprimeruneinstruction particuliredulot.VousnedevezpasajouteraulotdinstructionSQLgnrantunjeudersultats,cardans ce cas la mthode updateBatch dclenche une exception de type BatchUpdateException. Cette fonction retourneuntableaudentierspermettantdobteniruneinformationsurlexcutiondechacunedesrequtes du lot. Chaque case du tableau contient un entier reprsentatif du rsultat de lexcution de la requte correspondante dans le lot. Une valeur suprieure ou gale 0 indique un fonctionnement correct de linstruction et reprsente le nombre denregistrements modifis. Une valeur gale la constante Statement.EXECUTE_FAILED indique que lexcution de linstruction a chou. Dans ce cas, certains pilotes arrtentlexcutiondulotalorsquedautrescontinuentaveclinstructionsuivantedulot.Unevaleurgale la constanteStatement.SUCCESS_NO_INFO indique que linstruction a t excute correctement mais que le nombre denregistrements modifis ne peut pas tre dtermin. Cette mthode est trs pratique pour excuter des modifications sur plusieurs tables lies. Ce pourrait par exemple tre le cas dans une applicationdegestiondecommercialeavecunetablepourlescommandesetunetablepourleslignesde commande.Lasuppressiondunecommandedoitdanscecasentranerlasuppressiondetoutesleslignes correspondantes. La fonction suivante vous permet de saisir plusieurs instructions SQL et de les excuter parlot.

public static void testExecuteBatch(Connection cnx) { Statement stm; BufferedReader br; String requete=""; int[] resultats; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_

- 8-

ENI Editions - All rigths reserved

READ_ONLY); br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir vos instructions SQL puis run pour excuter le lot :"); requete=br.readLine(); while (!requete.equalsIgnoreCase("run")) { stm.addBatch(requete); requete=br.readLine(); } System.out.println("excution du lot d\instructions"); resultats=stm.executeBatch(); for (int i=0; i<resultats.length;i++) { switch (resultats[i]) { case Statement.EXECUTE_FAILED: System.out.println("l\excution de linstruction " + i + " a chou"); break; case Statement.SUCCESS_NO_INFO: System.out.println("l\excution de linstruction " + i + " a russi"); System.out.println("le nombre d\enregistrements modifis est inconnu"); break; default: System.out.println("l\excution de linstruction " + i + " a russi"); System.out.println("elle a modifi " + resultats[i] + " enregistrements"); break; }

} } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } PlusieursautresmthodesvontintervenirsurlecomportementdelobjetStatement:


q

public void setQueryTimeOut(int duree) : cette mthode indique la dure maximale alloue pour lexcutionduneinstructionSQLavantledclenchementduneexception. public void close() :lorsquunobjetStatementnestplusutiledansuneapplication,ilestprfrabledele fermer explicitement en appelant cette mthode. Celleci provoque la libration de toutes les ressources utilises par cet objet. La fermeture dun objet statement provoque galement la fermeture du jeu denregistrementsassoci. public void setMaxRows(int nombre) :cettemthodelimitelenombredelignesdesjeuxdenregistrements gnrsparcetobjetStatement.SiuneinstructionSQLgnreunjeudenregistrementscomportantplusde lignes,leslignesexcdentairessonttoutsimplementignores(sansplusdinformation). public void setMaxFieldSize(int taille) :cettemthodelimitelatailledecertainstypesdechampsdans lejeudenregistrements.Lestypesdechampsconcernssontleschampsdunebasededonnespouvant avoirunetaillevariablecommeparexempleleschampscaractresoubinaires.Lesdonnesexcdentaires sontsimplementignores.Leschampsconcernspeuventdecefaittreinutilisablesdanslapplication. public void setFetchSize(int nbLignes) :lorsquuneinstructionSQLgnreunjeudenregistrements,les donnescorrespondantessonttransfresduserveurdebasededonnesverslammoiredelapplication
ENI Editions - All rigths reserved - 9-

Java.Cetransfertesteffectuparblocsenfonctiondelutilisationdesdonnes.Cettemthodeindiqueau pilotelenombredelignesdechaquebloctransfrdelabasededonnesverslapplication.
q

public boolean getMoreResults() : si la mthode execute est utilise pour excuter plusieurs instruction SQL,parexempledeuxinstructionsselect,ilyadanscecasgnrationdedeuxjeuxdenregistrements.Le premier est obtenu par la mthode getResultSet. Le second ne sera accessible quaprs avoir appel la mthodegetMoreResults.Cettefonctionpermetdedplacerlepointeursurlersultatsuivantetretourne un boolean gal true si le rsultat suivant est un jeu denregistrements. Si cest le cas, il est lui aussi accessibleparlamthodegetResultSet.SilafonctiongetMoreResultsretourneunbooleanfalse,cestquele rsultat suivant nestpasunjeudenregistrements ou quilnyasimplementpasdersultatsuivant.Pour lever le doute, il faut donc appeler la fonction getUpdateCount et vrifier la valeur retourne par cette fonction. Si cette valeur est gale 1 cest quil ny a pas de rsultat suivant sinon la valeur retourne reprsentelenombredenregistrementsmodifisdanslabasededonnes.

LafonctionsuivantepermetlexcutiondeplusieursinstructionsSQLsparespardespointsvirgules : public static void testExecuteMultiple(Connection cnx) { Statement stm; BufferedReader br; String requete; ResultSet rs; boolean resultat; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_ READ_ONLY); br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir vos instruction SQL spares par ; :"); requete=br.readLine(); resultat=stm.execute(requete); int i=1; // traitement du rsultat gnr par la premire instruction if (resultat) { System.out.println("votre instruction N " + i + " a gnr un jeu d\enregistrements"); rs=stm.getResultSet(); rs.last(); System.out.println("il contient " + rs.getRow() + " enregistrements"); } else { System.out.println("votre instruction N " + i + " a modifi des enregistrements dans la base"); System.out.println("nombre denregistrements modifis :" + stm.getUpdateCount()); } i++; // dplacement du pointeur sur un ventuel rsultat suivant resultat=stm.getMoreResults(); // boucle tant quil y a encore un rsultat de type jeu denregistrement -> resultat==true // ou quil y a encore un resultat de type nombre denregistrements modifis -> getUpdateCount != -1 while (resultat || stm.getUpdateCount()!=-1) { if (resultat) { System.out.println("votre instruction N " + i + " a gnr un jeu d\enregistrements"); rs=stm.getResultSet(); rs.last(); System.out.println("il contient " + rs.getRow() + " enregistrements"); } else {

- 10 -

ENI Editions - All rigths reserved

System.out.println("votre instruction N " + i + " a modifi des enregistrements dans la base"); System.out.println("nombre denregistrements modifis :" + stm.getUpdateCount()); } i++; // dplacement du pointeur sur un ventuel rsultat suivant resultat=stm.getMoreResults(); } } catch (SQLException e) { System.out.println("votre instruction n\a pas fonctionn correctement"); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

b.ExcutiondinstructionsparamtresaveclobjetPreparedStatement
IlarrivefrquemmentdavoirfaireexcuterplusieursfoisunerequteSQLavecjusteunepetitemodificationentre deuxexcutions.Lexempleclassiquecorrespondunerequtedeslectionavecunerestriction. stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_ READ_ONLY); resultat=stm.execute("select * from customers where customerId=ALFKI"); La valeur sur laquelle porte la restriction est en gnral saisie par lutilisateur de lapplication et dans ce cas disponible dans une variable. La premire solution qui vient lesprit consiste construire la requte SQL par concatnationdeplusieurschanesdecaractres. public static void testRequeteConcat(Connection cnx) { Statement stm; BufferedReader br; String requete; String code; ResultSet rs; boolean resultat; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_ READ_ONLY); br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir le code du client recherch :"); code=br.readLine(); requete="select * from customers where customerID=\" + code + "\"; resultat=stm.execute(requete); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { // TODO Bloc catch auto-gnr e.printStackTrace(); } } Cettesolutionprsenteplusieursinconvnients :
q

Laconcatnationdechanesdecaractresconsommebeaucoupderessources.

ENI Editions - All rigths reserved

- 11 -

Leserveurdoitanalyserchaquefoisunenouvellerequte. Lasyntaxevarapidementdevenircomplexesiplusieurschanesdoiventtreconcatnes.Ilfauttoujours conserverlespritquaufinalnousdevonsobteniruneinstructionSQLcorrecte.

Les concepteurs de JDBC ont prvu une solution efficace pour pallier ces inconvnients. LobjetPreparedStatement apporteunesolutionefficaceceproblmeennouspermettantlacrationderequtesavecparamtres.Dansce type de requte, les paramtres sont remplacs par des points dinterrogation. Avant lexcution de la requte, il faut fournir lobjet PreparedStatement les valeurs quil doit utiliser pour remplacer les diffrents points dinterrogation. Un objetPreparedStatement peut tre cr en utilisant le mme principe que pour la cration dun objet Statement. La mthode prepareStatement accessible partir dune connexion retourne un objet PreparedStatement. Cette mthode est disponible sous deux formes. La premire attend comme argument une chanedecaractresreprsentantlarequteSQL.Danscetterequte,lemplacementdesparamtresdoiventtre rservpardespointsdinterrogation.Siunjeudenregistrementsestcrparlexcutiondecetterequte,celuici sera en lecture seule et dfilement en avant seulement. La deuxime forme de la mthode prepareStatement attend en plus de la chane de caractres un argument indiquant le type de jeu denregistrements et un autre dterminantlespossibilitsdemodificationdesinformationscontenuesdanslejeudenregistrements. Les mmes constantesquepourlamthodecreateStatementpeuventtreutilises. stm=cnx.prepareStatement("select * from customers where customerID=?",ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); Avant lexcution de linstruction SQL, vous devez fournir une valeur pour chacun des points dinterrogation reprsentant un paramtre. Pour cela, lobjet PreparedStatement dispose de nombreuses mthodes permettant laffectationdunevaleurunparamtre.ChacunedecesmthodescorrespondautypededonnesSQLinsrer la place dun point dinterrogation. Ces mthodes sont nommes selon le mme schma : setXXXX ou XXXX reprsentant un type de donnes SQL. Chacune de ces mthodes attend comme premier argument un entier correspondantaurangduparamtredanslinstructionSQL.Lepremierparamtreestsituaurang1.Ledeuxime argumentcorrespondlavaleurtransfrerdansleparamtre.Letypedecetargumentcorrespondbiensrau typededonnesSQLtransfrerversleparamtre.LepilotejdbcconvertitensuiteletypeJavaentypeSQL. Parexemplelamthode setInt (int indiceParam, int value)effectueuneconversiondutype intjavaentype INTEGER sql. Les valeurs stockes dans les paramtres sont conserves dune excution lautre de linstruction SQL.LamthodeclearParameterspermetderinitialiserlensembledesparamtres. Les paramtres peuvent tre utiliss dans une instruction SQL en remplacement de valeurs mais jamais pour remplacerunnomdechamp,encoremoinsunoprateur.Lasyntaxesuivanteestbiensrinterdite : stm=cnx.prepareStatement("select * from customers where ?=?",ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); stm.setString(1,"customerID"); stm.setString(2,"ALFKI"); rs=stm.executeQuery(); Les autres mthodes disponibles avec un objet PreparedStatement sont parfaitement identiques celles dfinies pourunobjetStatementpuisquelinterfacePreparedStatementhritedirectementdelinterfaceStatement. public static void testPreparedStatement(Connection cnx) { { PreparedStatement stm; BufferedReader br; String code; ResultSet rs; try { stm=cnx.prepareStatement("select * from customers where customerID like ?",ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir le code du client recherch :"); code=br.readLine(); stm.setString(1,code); rs=stm.executeQuery(); while (rs.next()) { for (int i = 1; i <=rs.getMetaData().getColumnCount(); i++) { System.out.print(rs.getString(i)+"\t");

- 12 -

ENI Editions - All rigths reserved

} System.out.println(); } } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

c.ExcutiondeprocduresstockesaveclobjetCallableStatement
UneprocdurestockereprsenteducodeSQLstocksurleserveur.Cetteapprocheprocureplusieursavantages :
q

Lestraitementsetlestempsderponsesontamliors. LecodeSQLpeuttrepartagentreplusieursapplications.

Parcontre,lesapplicationsdeviennentbeaucoupplusdpendantesduserveurdebasededonnes.Lechangement deserveurvousobligeracertainementrcrirevosprocduresstockescarlasyntaxedune procdure stocke est propre chaque serveur. Les procdures stockes sont accessibles partir de Java grce lobjet CallableStatement.CommepourlesobjetsStatementet PreparedStatement,cestencoreunefoislaconnexionqui va nous fournir une instance de classe correcte. Cest dans ce cas la mthode prepareCall qui doit tre utilise. Cette mthode attend comme argument une chane de caractres identifiant la procdure stocke appeler. Par contrelasyntaxedecettechanedecaractresestunpetitpeuspcialepuisquilnesuffitpasdindiquerlenomde laprocdurestocke.Deuxcasdefiguressontprendreencomptesuivantquelaprocdurestockeretourneou nonunevaleur.Silaprocdurestockeneretournepasdevaleur,lasyntaxedecettechanedecaractresestla suivante : {call nomProcedure( ?, ?,....)} Dans cette syntaxe, les points dinterrogation reprsentent les paramtres attendus par la procdure stocke. Comme pour lobjet PreparedStratement les valeurs de ces paramtres doivent tre fournies par les mthodes setXXXXcorrespondantesautypeduparamtre. Si la procdure stocke retourne une valeur, il faut utiliser la syntaxe suivante qui ajoute un paramtre supplmentairepouraccueillirleretourdelaprocdurestocke. { ?=call nomProcedure( ?, ?,....)} Lepremierparamtretantutilisensortiedelaprocdurestocke,cestlexcutiondelaprocdurestockequiva y stocker une valeur, vous devez en informer lobjet CallableStatement en appelant la mthode registerOutParameter. Cette mthode attend comme premier argument, lindice du paramtre 1 pour la valeur de retour de la procdure stocke, mais nimporte quel autre paramtre peut tre utilis en sortie, puis comme deuxime argument le type SQL du paramtre. Ce type peut tre indiqu avec une des constantes dfinies dans linterfacejava.sql.Types.Aprsexcutiondelaprocdurestocke,lavaleurdesparamtresutilissensortieest accessibleparlesmthodesgetXXXXoXXXXreprsenteletypeSQLduparamtre.Cesmthodesattendentcomme argumentlindiceduparamtredanslappeldelaprocdurestocke. Comme pour les mthodes createStatement et prepareStatement, la mthode prepareCall propose une deuxime syntaxepermettantdindiquerlescaractristiquesdunventueljeudenregistrementsgnrparlexcutiondela procdurestocke. PourillustrerlutilisationdelobjetCallableStatement,nousallonsutiliserlesdeuxprocduresstockessuivantes : create PROCEDURE commandesParClient @code nchar(5) AS SELECT OrderID, OrderDate, RequiredDate, ShippedDate FROM Orders WHERE CustomerID = @code

ENI Editions - All rigths reserved

- 13 -

ORDER BY OrderID CREATE procedure nbCommandes @code nchar(5) as declare @nb int select @nb=count(*) from orders where customerid=@code return @nb La premire retourne la liste de toutes les commandes du client dont le code est pass comme paramtre. La deuximeretourneunentiercorrespondantaunombredecommandespassesparleclientdontlecodeestfourni commeparamtre. public static void testProcedureStockee(Connection cnx) { CallableStatement cstm1,cstm2; BufferedReader br; String code; ResultSet rs; int nbCommandes; try { br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir le code du client recherch :"); code=br.readLine(); cstm1=cnx.prepareCall("{ ?=call nbCommandes ( ? )}"); cstm1.setString(2,code); cstm1.registerOutParameter(1,java.sql.Types.INTEGER); cstm1.execute(); nbCommandes=cstm1.getInt(1); System.out.println("nombre de commandes passes par le client " + code + " : " + nbCommandes ); cstm2=cnx.prepareCall("{ call commandesParClient ( ? )}",ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); cstm2.setString(1,code); rs=cstm2.executeQuery(); System.out.println("dtail des commandes"); System.out.println("numro de commande\tdate de commande"); while (rs.next()) { System.out.print(rs.getInt("OrderID") + "\t"); System.out.println(new SimpleDateFormat("dd/MM/yy").format(rs.getDate("OrderDate"))); } } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

5.UtilisationdesjeuxdenregistrementsaveclinterfaceResultset
LorsquuneinstructionSQLselectestexcuteparlamthodeexecuteQuerydunobjetStatement,PreparedStatement ouCallableStatement,celleciretourneunobjetResultSet.CestparlintermdiairedecetobjetResultSetquenous allons pouvoir intervenir sur le jeu denregistrements. Nos possibilits daction sur ce jeu denregistrements sont dterminesparlescaractristiquesdelobjetResultSet.Cescaractristiquessontfixesaumomentdelacration desobjetsStatement,PreparedStatementouCallableStatementenfonctiondesargumentspassslorsdelappeldes mthodescreateStatement,prepareStatementouprepareCall. Lepremierargumentdtermineletypedujeudenregistrements.Lesconstantessuivantessontdfinies :
q

ResultSet.TYPE_FORWARD_ONLY :lejeudenregistrementsseradfilementenavantseulement. ResultSet.TYPE_SCROLL_INSENSITIVE :lejeudenregistrementspourratreparcourudanslesdeuxsensmais

- 14 -

ENI Editions - All rigths reserved

serainsensibleauxchangementseffectusdanslabasededonnespardautresutilisateurs.
q

ResultSet.TYPE_SCROLL_SENSITIVE :lejeudenregistrementspourratreparcourudanslesdeuxsensetsera sensibleauxchangementseffectusdanslabasededonnespardautresutilisateurs.

Le second argument dtermine les possibilits de modification des informations contenues dans le jeu denregistrements.Lesdeuxconstantessuivantessontdfinies :
q

ResultSet.CONCUR_READ_ONLY :lesenregistrementssontenlectureseule. ResultSet.CONCUR_UPDATABLE :lesenregistrementspeuventtremodifisdanslejeudenregistrements.

Ilfautbiensrquelesactionsexcutessurlobjet Resultsetsoitcompatiblesaveccescaractristiquessinonune exception sera dclenche. Il est possible de vrifier les caractristiques dun objet Resultset en utilisant les mthodesgetTypeetgetConcurrency. public static void infosResultset(ResultSet rs) { try { switch (rs.getType()) { case ResultSet.TYPE_FORWARD_ONLY: System.out.println("le Resultset est dfilement en avant seulement"); break; case ResultSet.TYPE_SCROLL_INSENSITIVE: System.out.println("le Resultset peut tre parcouru dans les deux sens"); System.out.println("il n\est pas sensible aux modifications faites par d\autres utilisateurs"); break; case ResultSet.TYPE_SCROLL_SENSITIVE: System.out.println("le Resultset peut tre parcouru dans les deux sens"); System.out.println("il est sensible au modifications faites par d\autres utilisateurs"); break; } switch (rs.getConcurrency()) { case ResultSet.CONCUR_READ_ONLY: System.out.println("les donnes contenues dans le ResulSet sont en lecture seule"); break; case ResultSet.CONCUR_UPDATABLE: System.out.println("les donnes contenues dans le ResulSet sont modifiables"); break; } } catch (SQLException e) { e.printStackTrace(); } }

a.PositionnementdansunResultSet
Lobjet ResultSet gre un pointeur denregistrement dterminant sur quel enregistrement vont intervenir les mthodes excutes sur le ResultSet luimme. Cet enregistrement est parfois appel enregistrement actif ou enregistrement courant. LobjetResultSetcontienttoujoursdeuxenregistrementsfictifsservantdereprepourle dbutduResultSet(BOF)etpourlafinduResultSet(EOF).Lepointeurdenregistrementpeuttrepositionnsur lun de ces deux enregistrements mais jamais avant lenregistrement BOF ni aprs lenregistrement EOF. Ces enregistrementsnecontiennentpasdedonnesetuneoprationdelectureoudcrituresurcesenregistrements dclenche une exception. la cration du ResultSet le pointeur est positionn avant le premier enregistrement (BOF).Denombreusesmthodessontdisponiblespourgrerlepointeurdenregistrements:

ENI Editions - All rigths reserved

- 15 -

boolean absolute(int position) : dplace le pointeur denregistrement sur lenregistrement spcifi. La numrotation des enregistrements dbute 1. Si la valeur de largument position est ngative, le dplacement est effectu en partant de la fin du ResultSet. Si le numro denregistrement nexiste pas le pointeur est positionn sur lenregistrement BOF si la valeur est ngative et infrieure au nombre denregistrements ou sur lenregistrement EOF si la valeur est positive et suprieure au nombre denregistrements.Cettemthoderetournetruesilepointeurestpositionnsurunenregistrementvalide etfalsedanslecascontraire(BOFouEOF). boolean relative(int deplacement) : dplace le curseur du nombre denregistrements spcifi par largument deplacement. Si la valeur de cet argument est positive le curseur descend dans le jeu denregistrements et si la valeur est ngative le curseur remonte dans le jeu denregistrements. Cette mthode retourne true si le pointeur est positionn sur un enregistrement valide et false dans le cas contraire(BOFouEOF). void beforeFirst() :dplacelepointeurdenregistrementsavantlepremierenregistrement(BOF). void afterLast() :dplacelepointeurdenregistrementsaprsledernierenregistrement(EOF). boolean first() : dplace le pointeur denregistrements sur le premier enregistrement. Cette mthode retournetruesilyunenregistrementdansleResultSetetfalsedanslecascontraire. boolean last() : dplace le pointeur denregistrements sur le dernier enregistrement. Cette mthode retournetruesilyunenregistrementdansleResultSetetfalsedanslecascontraire. boolean next() : dplace le pointeur denregistrements sur lenregistrement suivant lenregistrement courant.Cettemthoderetournetruesilepointeurestsurunenregistrementvalideetfalsedanslecas contraire(EOF). boolean previous() :dplacelepointeurdenregistrementssurlenregistrementprcdantlenregistrement courant.Cettemthoderetournetruesilepointeurestsurunenregistrementvalideetfalsedanslecas contraire(BOF).

Pour toutes ces mthodes sauf pour la mthode next, il faut obligatoirement que le ResultSet soit de type SCROLL_SENSITIVEouSCROLL_INSENSIVE.SileResultSetestdetypeFORWARD_ONLY,seulelamthodenextfonctionne et dans ce cas les autres mthodes dclenchent une exception. Les mthodes suivantes permettent de tester la positiondupointeurdenregistrements:
q

boolean isBeforeFirst() :retournetruesilepointeurestplacavantlepremierenregistrement(BOF). boolean isAfterLast() :retournetruesilepointeurestplacaprsledernierenregistrement(EOF). boolean isFirst() :retournetruesilepointeurestplacsurlepremierenregistrement. boolean isLast() :retournetruesilepointeurestplacsurledernierenregistrement. int getRow() :retournelenumrodelenregistrementsurlequelsetrouvelepointeurdenregistrements.La valeur0estretournesilnyapasdenregistrementcourant(BOFouEOF).

public static void positionRs(ResultSet rs) { try { if (rs.isBeforeFirst()) { System.out.println("le pointeur est avant le premier enregistrement"); } if (rs.isAfterLast()) { System.out.println("le pointeur est aprs le dernier enregistrement"); } if (rs.isFirst())

- 16 -

ENI Editions - All rigths reserved

{ System.out.println("le pointeur est sur le premier enregistrement"); } if (rs.isLast()) { System.out.println("le pointeur est sur le dernier enregistrement"); } int position; position=rs.getRow(); if (position!=0) { System.out.println("cest l\enregistrement numro " + position); } } catch (SQLException e) { // TODO Bloc catch auto-gnr e.printStackTrace(); } } }

b.LecturedesdonnesdansunResultSet
LobjetResultSetfournitdenombreusesmthodespermettantlalecturedeschampsdunenregistrement.Chacune decesmthodesestspcifiqueuntypededonnesSQL.Ilfautbiensrutiliserenprioritlamthodeadapteau typeduchampdontonsouhaiteobtenirlavaleur.Cependantcertainesdecesmthodessontrelativementsouples et permettent la lecture de plusieurs types de donnes. Le tableau cidessous reprend les principaux types de donnes SQL et les mthodes en permettant la lecture partir dun ResultSet. Les mthodes marques avec le symboleJ sontlesmthodesconseilles.LesmthodesmarquesaveclesymboleK sontpossiblesmaisavecdes risquesdepertedinformations.

Chacunedecesmthodesestdisponiblesousdeuxformes.Lapremireacceptecommeargumentlenumrodela

ENI Editions - All rigths reserved

- 17 -

colonne dont on souhaite obtenir la valeur. La numrotation commenant 1. La deuxime version accepte une chanedecaractresreprsentantlenomdelacolonnedanslabasededonnes.Silarequteayanttutilise pourcrerleResultSetcontientdesaliasalorslescolonnesportentlenomdelaliasetnonlenomduchampdansla base de donnes. Pour une meilleure lisibilit du code, il est bien sr prfrable dutiliser les noms des colonnes plutt que leurs indices. Lorsque dans la base de donnes un champ ne contient pas de valeur (Dbnull), les mthodesretournentunevaleurgale0pourleschampsnumriques,unevaleurfalsepourleschampsboolens etunevaleur nullpourlesautrestypes.Danscertainscas,ilyadoncundoutepossiblesurlavaleurrellement prsente dans la base. Par exemple, la mthode getInt peut retourner une valeur gale zro parce quil y a effectivement cette valeur dans la base de donnes ou parce que ce champ nest pas renseign dans la base de donnes.Pourlevercedoute,lamthodewasNullretourneunbooleangaltruesilechampsurlequelladernire oprationdelecturedansleResultSetcontenaiteffectivementunevaleurnull. public static void lectureRs(Connection cnx) { Statement stm; String requete; ResultSet rs; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CON CUR_READ_ONLY); requete="select * from products " ; rs=stm.executeQuery(requete); System.out.println("code produit\tdsignation\tprix unitaire\tstock\tpuis\tDLC"); while(rs.next()) { System.out.print(rs.getInt("ProductID")+"\t"); System.out.print(rs.getString("ProductName")+"\t"); System.out.print(rs.getDouble("UnitPrice")+"\t"); rs.getShort("UnitsInStock"); if (rs.wasNull()) { System.out.print("inconnu\t"); } else { System.out.print(rs.getShort("UnitsInStock")+"\t"); } System.out.print(rs.getBoolean("Discontinued")+"\t"); if (rs.getDate("DLC")!=null) { System.out.println(rs.getDate("DLC")); } else System.out.println("non perissable"); } rs.close(); stm.close(); } catch (SQLException e) { e.printStackTrace(); } }

c.ModificationdesdonnesdansunResultSet
La modification des donnes est effectue simplement en utilisant les mthodes updateXXXo XXX correspond au typededonnesdelacolonnemettrejour.CommepourlesmthodesgetXXXcellescisontdisponiblesendeux versions, lune attend comme argument lindice de la colonne mettre jour, la deuxime attend elle comme argumentunechanedecaractresreprsentantlenomdelacolonnedanslabasededonnes.Silarequteayant tutilisepourcrerleResultSetcontientdesalias,alorslescolonnesportentlenomdelaliasetnonlenomdu champdanslabasededonnes.Pourunemeilleurelisibilitducode,ilestbiensrprfrabledutiliserlesnomsdes

- 18 -

ENI Editions - All rigths reserved

colonnespluttqueleursindices.Letypedudeuximeargumentattenduparcesmthodescorrespondbiensrau typededonnesmettrejourdansleResultSet.Lesmodificationsdoiventensuitetrevalidesparlamthode updateRow ou annules par la mthode cancelRowUpdates. Le ResultSet doit obligatoirement tre de type CONCUR_UPDATABLE pour pouvoir tre modifi. Dans le cas contraire, lexcutiondunemthode updateXXXdclenche uneexception. public static void modificationRs(Connection cnx) { Statement stm; String requete; ResultSet rs; int num=0; BufferedReader br; String reponse; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CON CUR_UPDATABLE); requete="select * from products " ; rs=stm.executeQuery(requete); System.out.println("numro de ligne\tcode produit\tdsignation\tprix unitaire\tstock\tpuis\tDLC"); while(rs.next()) { num++; System.out.print(num + "\t"); System.out.print(rs.getInt("ProductID")+"\t"); System.out.print(rs.getString("ProductName")+"\t"); System.out.print(rs.getDouble("UnitPrice")+"\t"); rs.getShort("UnitsInStock"); if (rs.wasNull()) { System.out.print("inconnu\t"); } else { System.out.print(rs.getShort("UnitsInStock")+"\t"); } System.out.print(rs.getBoolean("Discontinued")+"\t"); if (rs.getDate("DLC")!=null) { System.out.println(rs.getDate("DLC")); } else System.out.println("non perissable"); } br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("quelle ligne voulez-vous modifier ? "); reponse=br.readLine(); rs.absolute(Integer.parseInt(reponse)); System.out.println("dsignation actuelle " + rs.getString("ProductName")); System.out.println("saisir la nouvelle valeur ou enter pour conserver la valeur actuelle"); reponse=br.readLine(); if (!reponse.equals("")) { rs.updateString("ProductName",reponse); } System.out.println("prix unitaire actuel " + rs.getDouble("UnitPrice")); System.out.println("saisir la nouvelle valeur ou enter pour conserver la valeur actuelle"); reponse=br.readLine(); if (!reponse.equals("")) {

ENI Editions - All rigths reserved

- 19 -

rs.updateDouble("UnitPrice",Double.parseDouble(reponse)); } rs.getShort("UnitsInStock"); if (rs.wasNull()) { System.out.println ("quantit en stock actuelle inconnue"); } else { System.out.println("quantit en stock actuelle " + rs.getShort("UnitsInStock")); } System.out.println("saisir la nouvelle valeur ou enter pour conserver la valeur actuelle"); reponse=br.readLine(); if (!reponse.equals("")) { rs.updateShort("UnitsInStock",Short.parseShort(reponse)); } System.out.println("voulez-vous valider ces modifications o/n"); reponse=br.readLine(); if (reponse.toLowerCase().equals("o")) { rs.updateRow(); } else { rs.cancelRowUpdates(); } System.out.println("les valeurs actuelles "); System.out.print(rs.getString("ProductName")+"\t"); System.out.print(rs.getDouble("UnitPrice")+"\t"); rs.getShort("UnitsInStock"); if (rs.wasNull()) { System.out.print("inconnu\t"); } else { System.out.print(rs.getShort("UnitsInStock")+"\t"); } rs.close(); stm.close(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

d.SuppressiondedonnesdansunResultSet
Lasuppressionduneligneesteffectuetrssimplementenpositionnantlepointeursurlalignesupprimerpuisen appelantlamthodedeleteRow.LaligneestimmdiatementsupprimeduResultSetetdanslabasededonnes.La positiondupointeurdenregistrementaprslasuppressiondpenddupilotedebasededonnesutilis.Certains pilotes dplacent le pointeur sur lenregistrement suivant, dautres le dplacent sur lenregistrement prcdent et enfin quelquesuns ne modifient pas la position du pointeur. Il faut dans ce cas utiliser une des mthodes de dplacementpourpositionnerlepointeursurunenregistrementutilisable.LeResultSetdoitobligatoirementtrede type CONCUR_UPDATABLE pour pouvoir y supprimer des donnes. Dans le cas contraire, lexcution de la mthode deleteRowdclencheuneexception. public static void suppressionRs(Connection cnx) {

- 20 -

ENI Editions - All rigths reserved

Statement stm; String requete; ResultSet rs; int num=0; BufferedReader br; String reponse; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CON CUR_UPDATABLE); requete="select * from products " ; rs=stm.executeQuery(requete); System.out.println("numro de ligne\tcode produit\tdsignation\tprix unitaire\tstock\tpuis\tDLC"); while(rs.next()) { num++; System.out.print(num + "\t"); System.out.print(rs.getInt("ProductID")+"\t"); System.out.print(rs.getString("ProductName")+"\t"); System.out.print(rs.getDouble("UnitPrice")+"\t"); rs.getShort("UnitsInStock"); if (rs.wasNull()) { System.out.print("inconnu\t"); } else { System.out.print(rs.getShort("UnitsInStock")+"\t"); } System.out.print(rs.getBoolean("Discontinued")+"\t"); if (rs.getDate("DLC")!=null) { System.out.println(rs.getDate("DLC")); } else System.out.println("non prissable"); } br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("quelle ligne voulez-vous supprimer ? "); reponse=br.readLine(); rs.absolute(Integer.parseInt(reponse)); rs.deleteRow(); System.out.println("le pointeur est maintenant sur la ligne " + rs.getRow()); } catch (Exception e) { e.printStackTrace(); } }

e.AjoutdedonnesdansunResultSet
ChaqueobjetResultSetcontientunelignespcialedestinelinsertiondedonnes.Lepointeurdenregistrement doitaupralabletrepositionnsurcettelignespcialeaveclinstructionmoveToInsertRow.Unefoisquelepointeur estpositionnsurcetteligne,cellecipeuttremisejouraveclesmthodesupdateXXX.Linsertiondelalignedoit ensuitetrevalideaveclamthodeinsertRow.Cettemthodeprovoquelamisejourdelabasededonnes.La lignedinsertiondevientcemomentunelignenormaleduResultSetetlepointeurdenregistrementestpositionn sur cette ligne. Vous pouvez revenir sur la ligne sur laquelle vous tiez avant linsertion grce la mthode moveToCurrentRow.Sivousnefournissezpasdevaleurpourtouteslescolonnes,desvaleursnull seront insres danslabasededonnespourlescolonnesnonrenseignes.Labasededonnesdoitaccepterlesvaleursnulles pour ces champs sinon une exception est dclenche. Le ResultSet doit obligatoirement tre de type

ENI Editions - All rigths reserved

- 21 -

CONCUR_UPDATABLE pour pouvoir y insrer des donnes. Dans le cas contraire, lexcution de la mthode moveToInsertRowdclencheuneexception. public static void ajoutRs(Connection cnx) { Statement stm; String requete; ResultSet rs; int num=0; BufferedReader br; String reponse; try { stm=cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CON CUR_UPDATABLE); requete="select * from products " ; rs=stm.executeQuery(requete); br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("saisir les valeurs de la nouvelle ligne"); rs.moveToInsertRow(); System.out.print("code produit : "); reponse=br.readLine(); rs.updateInt ("ProductID",Integer.parseInt(reponse)); System.out.print("Dsignation : "); reponse=br.readLine(); rs.updateString ("ProductName",reponse); System.out.print("Prix unitaire : "); reponse=br.readLine(); rs.updateDouble("UnitPrice",Double.parseDouble(reponse)); System.out.print("Quantit en stock : "); reponse=br.readLine(); rs.updateDouble("UnitsInStock",Short.parseShort(reponse)); rs.insertRow(); } catch (Exception e) { e.printStackTrace(); } }

6.Gestiondestransactions
Les transactions vont permettre de garantir quun ensemble dinstructions SQL sera excut avec succs pour chacunedellesouquaucunedentreellesneseraexcute.Letransfertdunesommedargententredeuxcomptes bancaires reprsente lexemple classique o une transaction est ncessaire. Imaginez la situation suivante : notre banquedoiteffectuerlencaissementdunchquede1000dbitersurlecomptenumro12345etcrditersurle compte67890.Parmesuredescuritaprschaqueoprationeffectuesuruncompte(dbitoucrdit),unrapport estdit.Voicicidessousunextraitducodepouvanteffectuercesoprations. public static void mouvement(String compteDebit,String compteCredit,double somme) { try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Connection cnx=null; cnx=DriverManager.getConnection("jdbc:sqlserver://localhost;database Name=banque; user=sa;password=;"); PreparedStatement stm; stm=cnx.prepareStatement("update comptes set solde=solde + ? where numero=?"); stm.setDouble(1,somme * -1); stm.setString(2,compteDebit); stm.executeUpdate();

- 22 -

ENI Editions - All rigths reserved

impressionRapport(compteDebit, somme); stm.setDouble(1,somme); stm.setString(2,compteCredit); stm.executeUpdate(); impressionRapport(compteCredit, somme); } catch (Exception e) { e.printStackTrace(); } } Pour99,9999%desmouvementseffectusaveccecode,ilnyaaucunproblme,saufquunbeaujourlimprimante chargedesditionssebloqueetceblocagedclencheuneexceptiondanslamthode impressionRapport.Apriori cetteexceptionneposepasdeproblmepuisquelappeldecettemthodeestplacdansunbloctryetquunbloc catchtraitelexception.Ilnefautcependantpasoublierquesiuneexceptionestdclencheetquunbloccatchest excut,lexcutionsepoursuitparlinstructionsuivantlebloccatch.Danscecasdefigure,lesinstructionsplaces entrecelleayantdclenchlexceptionetlafindubloctrynesonttoutsimplementpasexcutes.Dansnotrecas, ceci peut tre trs problmatique si cette exception est dclenche dans la mthode impressionRapport excute aussittaprsloprationdedbit.Loprationdecrditnatoutsimplementpaslieu.Lasommeestdoncperdue.Une solutionconsisteannulerleffetdesinstructionsSQLayantdjtexcuteseneffectuantletraitementinverse, dansnotrecasencrditantlecompte. Cestenfaitcemcanismequiestmisen uvredansunetransactionmaisbiensrdemanireautomatique.Cestau niveaudelaconnexionversleserveurdebasededonnesquesontgreslestransactions.

a.Miseenuvredestransactions
Jusquprsent,nousnenoussommespasproccupsdestransactionsetpourtantnousenralisonsdepuisnotre premireinstructionSQLexcuteviaJDBC.Lefonctionnementpardfautdejdbcconsisteeffectivementinclure chaque instruction excute dans une transaction puis valider la transaction si linstruction a t excute correctement (commit) ou annuler linstruction dans le cas contraire (rollBack). Ce mode de fonctionnement est appel mode autoCommit. Si vous souhaitez grer vousmme la fin dune transaction en validant ou en annulant toutes les instructions quelle contient, vous devez dsactiver le mode autoCommit en appelant la mthode setAutoCommit(false) sur lobjet Connection. Vous tes maintenant responsables de la fin des transactions. Les mthodes commit et rollback de lobjet Connection permettent de valider ou dannuler les instructions excutes depuisledbutdelatransaction.Unenouvelletransactiondbuteautomatiquementdslafindelaprcdenteou ds louverture de la connexion. Le code de notre mthode permettant de transfrer un montant entre deux comptesdoitdoncprendrelaformesuivante. public static void mouvement1(String compteDebit,String compteCredit,double somme) { Connection cnx=null; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); cnx=DriverManager.getConnection("jdbc:sqlserver://localhost;database Name=banque; user=sa;password=;"); cnx.setAutoCommit(false); PreparedStatement stm; stm=cnx.prepareStatement("update comptes set solde=solde + ? where numero=?"); stm.setDouble(1,somme * -1); stm.setString(2,compteDebit); stm.executeUpdate(); impressionRapport(compteDebit, somme); stm.setDouble(1,somme); stm.setString(2,compteCredit); stm.executeUpdate(); impressionRapport(compteCredit, somme); cnx.commit(); } catch (Exception e) { try { cnx.rollback(); }

ENI Editions - All rigths reserved

- 23 -

catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); } }

b.Pointsdesauvegarde
Lorsdelappeldelamthoderollback,lensembledesinstructionsSQLexcutesdepuisledbutdelatransaction sontannules.CettemthodeproposeunedeuximeversionacceptantcommeparamtreunobjetSavePoint.Cet objetreprsenteunrepredanslexcutiondesinstructionsSQL.IlestcrparlamthodesetSavePoint.Lappel delamthoderollbackaveccommeargumentunobjetSavePointprovoquelannulationdetouteslesinstructions excutesjusqucepointdesauvegarde.

c.Niveauxdisolement
Pendant quune transaction est active, les donnes modifies par les instructions excutes au sein de la transactionpeuventtreverrouillesparlabasededonnespourviterlesconflitsetlesincohrences.Diffrents types de verrous sont disponibles pour une transaction. Pour bien comprendre leurs effets, il faut au pralable identifierlestypesdeproblmespouvanttrerencontrslorsquunetransactionestactive.
q

Lectureerrone:cetteanomalieseproduitlorsquuneapplicationaccdedesdonnesquisontentrain dtremodifiesparunetransactionquinapasencoretvalide. Lecture non reproductible : cette anomalie se produit lorsque les excutions successives dune mme instruction select ne produisent pas le mme rsultat. Cest le cas si les donnes que vous lisez sont en coursdemodificationparuneautretransaction. Lecturefantme:cetteanomalieseproduitsidesexcutionssuccessivesdunemmerequterenvoient desdonnesenplusouenmoins.Celapeuttrelecassiuneautretransactionestentraindesupprimerou dajouterdesdonneslatable.

JDBCprvoitplusieursniveauxdisolement.Cesniveauxdisolationdterminentlamaniredontsontverrouillesles donnes durant la transaction. Ce verrouillage peut tre plac en lecture, en criture ou encore en lecture et en crituresurlesdonnesaccdesparlesinstructionsdelatransaction. La mthode setTransactionIsolationLevel permet de fixer les types de problmes pouvant tre vits. Cette mthode accepte comme argument une des constantes prsentes dans le tableau suivant. Ce tableau prsente galementleffetdechaqueniveaudisolementsurlesdonnes. constante Lectureerrone Lecturenon reproductible possible possible impossible impossible Lecturefantme

TRANSACTION_READ_UNCOMMITTED TRANSACTION_READ_COMMITTED TRANSACTION_REPEATABLE_READ TRANSACTION_SERIALIZABLE

possible impossible impossible impossible

possible possible possible impossible

Lefaitdespcifierunniveaudisolementpourunetransactionpeutparfoisavoiruneffetsurlesautresapplications accdant aux donnes manipules dans la transaction puisque cellesci peuvent tre verrouilles et donc tre inaccessiblesauxautresapplications.

- 24 -

ENI Editions - All rigths reserved

ArchivesJava
1.Prsentation
UnearchiveJavaestunformatdefichierparticulierpermettantderegrouperdansunseulfichier(larchive)plusieurs autresfichiers.Engnral,lonregroupeainsitouslesfichiersncessairesaufonctionnementduneapplication.Ceci comprend bien sr les fichiers .class mais galement toutes les autres ressources indispensables au bon fonctionnement de lapplication. Cette possibilit de regroupement procure de nombreux avantages pour le dploiementdapplications.
q

Le premier et certainement le plus apprciable rside dans le fait que le dploiement dune application se rsume la recopie dun seul et unique fichier sur le poste client. Mme si lapplication exige pour son fonctionnement plusieurs ressources organises sous forme dune arborescence bien prcise. Cette arborescenceestcrelintrieurdufichierarchiveetnapasbesoindtrereproduitesurleposteclient. Lesfichiersarchivepeuventtrecompresssafindoptimiserleurstockageetleurtransfertsurunrseau. Cet avantage est encore plus apprciable pour les applets qui peuvent tre ainsi rcupres par le navigateuravecuneseulerequtehttp. Lascuritestgalementamlioreparsignatureetlescellementdelarchive. Leformatdesarchivestantstandard,ilnyaaucunerestrictionvisvisdunsystmespcifique.

2.Manipulationdunearchive
LamanipulationdunearchiveJava(fichierjar)reprendlesmmesprincipesquelamanipulationdunearchivedans le monde unix avec la commande tar. Les options de la commandejar permettant de manipuler une archive Java sontdailleurs trangement ressemblantes celles de la commandetar dunix. Le format utilis en interne par les fichiers archive est galement bien connu puisquilsagit du formatZIP. Les fichiers archive Java peuvent dailleurs tremanipulsavecdesoutilsddislamanipulationdefichiersZIP. Lacommandestandarddemanipulationdarchiveestlacommandejar.Ellefaitpartiedesoutilsfournisaveclejdk.

a.Crationdunearchive
LasyntaxedebasedecrationdunearchiveJavaestlasuivante : jar cf nomDuFichier listeFichier Le paramtre c est bien sr destin indiquer la commande jar que lon souhaite crer une archive. Le paramtref indiquant, quant lui, que la commande doit gnrer un fichier. Le nom du fichier est indiqu par le troisime paramtre de cette commande. Par convention, lextension de ce fichier sera .jar. Le dernier lment reprsente le ou les fichiers inclure dans larchive. Si plusieurs fichiers sont inclure dans larchive, leurs noms doivent tre spars par un espace. Le caractre joker * est galement autoris dans la liste. Si un nom de rpertoireestprsentdanslaliste,soncontenuentierestajoutlarchive. Larchive est gnre dans le rpertoire courant. Un fichier manifest par dfaut est galement ajout larchive. Lesoptionssuivantessontgalementdisponibles.
q

vaffichelenomdesfichiersaufuretmesuredelajoutdanslarchive. 0dsactivelacompressiondufichierarchive. Mdsactivelagnrationdumanifest. majoutelemanifestindiqularchive.

ENI Editions - All rigths reserved

- 1-

-Csupprimelenomderpertoiredanslarchive.

b.Visualisationducontenu
Lecontenudunearchivepeuttrevisualisaveclacommandesuivante : jar tf ardoise.jar Lacommandeaffichesurlaconsolelecontenudelarchive. META-INF/MANIFEST.MF .classpath .project Client$1.class Client$2.class Client$3.class Client$4.class Client$5.class Client$6.class Client.class ClientArdoiseMagique.class PanelDessin.class ThreadEntree.class Des informations supplmentaires peuvent tre obtenues en ajoutant loption v la commande. La date de modificationetlatailledesfichierssontajoutesaursultatdelacommande. jar tvf ardoise.jar 59 247 568 1050 1527 3091 1023 1077 1182 6731 530 5585 3146 Mon Tue Tue Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb Feb 14 08 08 14 14 14 14 14 14 14 14 14 14 11:34:38 19:07:22 19:07:22 08:35:58 08:35:58 08:35:58 08:35:58 08:35:58 08:35:58 08:35:58 08:34:18 08:36:10 08:39:36 CET CET CET CET CET CET CET CET CET CET CET CET CET 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 META-INF/MANIFEST.MF .classpath .project Client$1.class Client$2.class Client$3.class Client$4.class Client$5.class Client$6.class Client.class ClientArdoiseMagique.class PanelDessin.class ThreadEntree.class

Lescheminsdaccsauxfichierssontaffichsaveclecaractre/commesparateuretsontrelatifslaracinede larchive.Lecontenudelarchivenestbiensrpasmodifiparlexcutiondecettecommande.

c.Extraction
Lesfichierspeuventtreextraitsdelarchiveaveclacommandesuivante : jar xvf ardoise.jar Lesfichiersprsentsdanslarchivesontrecrssurledisquedanslerpertoirecourant.Silarchivecontientune portion darborescence, celleci est recre dans le rpertoire courant. Les ventuels fichiers et rpertoires existantssontcrassparceuxprsentsdanslarchive.Lextractiondunearchivepeuttreslectiveenindiquant commeparamtresupplmentairelalistedesfichiersextrairedelarchiveensparantlesnomsdecesfichierspar unespace.LacommandesuivantepermetdextrairedelarchiveuniquementlefichierClientArdoiseMagique.class. jar xvf ardoise.jar ClientArdoiseMagique.class Lecontenudelarchivenestpasmodifiparcettecommande.

d.Misejour

- 2-

ENI Editions - All rigths reserved

Lecontenudunearchivepeuttremisjourparlajoutdefichiersaprssacration.Ilfautdanscecasutiliserla commandesuivante : jar uf ardoise.jar connect.gif Le dernier paramtre de cette commande reprsente la liste des fichiers mettre jour dans larchive. Si ces fichiers nexistentpasdanslarchive, ils sont ajouts sinon ils sont remplacs par la nouvelle version. Si larchive contientdesrpertoires,lechemindaccscompletdoittrespcifidanslalistedesfichiersajouter.

e.Excution
UneapplicationprsentedansunearchiveJavapeuttreexcutedirectementdepuislarchivesansavoirbesoin dextrairelesfichiers.VousdevezindiquerlamachinevirtuelleJavaquelledoitellemmeextrairelesfichiersde larchiveenutilisantloption-jarlorsdulancementdelapplication.Lenomdufichierarchivedoittrespcifila suitedecetteoption. java -jar ardoise.jar La machine virtuelle Java a cependant besoin dune information supplmentaire pour dterminer quel fichier de larchivecontientlamthodemainparlaquelleelledoitdbuterlexcutiondelapplication.Pourcela,ellerecherche lefichiermanifestdelarchivequidoitbiensrcontenircetteinformationpourquelapplicationpuissetreexcute partirdelarchive.

3.Lemanifest
LesfichiersarchivesJavasontbienplusquedessimplesfichierscompressspuisquilsproposentunemultitudede fonctionnalitscomplmentaires :
q

Excutiondirectedepuislarchive. Signatureducontenudelarchive. Scellementdepartiesdelarchive. Gestiondesversions.

Toutescesfonctionnalitssontdisponiblesgrceaufichiermanifestinclusdanslarchive.

a.Prsentation
Lefichiermanifestestunsimplefichiertextecontenantdescouplesnomdeparamtre etvaleurdeparamtre.Ces deuxinformationssontsparsparlecaractre :. CefichieresttoujoursnommMANIFEST.MFetsetrouvedanslerpertoireMETA-INFdelarchive.

b.Cration
lacrationdunfichierarchive,unfichiermanifestestcrpardfaut.Ilcontientlesinformationssuivantes : Manifest-Version: 1.0 Created-By: 1.6.0 (Sun Microsystems Inc.) Lapremireligneindiquelaversiondufichiermanifest,lasecondeindiquelaversiondujdkaveclaquellelefichier archiveatgnr. Pour ajouter dautresinformationsaufichiermanifest,vousdevezprocderendeuxtapes.Vousdevezdansun premiertempsprparerunfichiertextecontenantlesinformationsquevoussouhaitezincluredanslemanifestde larchive.Ladernirelignedecefichierdoitobligatoirementseterminerparuncaractreretourchariotousautde ligne(oulesdeux).Vousdevezensuitefusionnercefichiertexteaveclemanifestpardfautdelarchiveenutilisant loptionmdelacommandejar.Lasyntaxedelacommandeestdonclasuivante :

ENI Editions - All rigths reserved

- 3-

jar cfm ardoise.jar infos.txt * Cettecommandegnreunfichierarchivenommardoise.jarcontenanttouslesfichiersdurpertoirecourantet ajoute au manifest par dfaut les informations contenues dans le fichier infos.txt. Ce fichier peut par exemple contenir une information permettant dindiquer le nom de la classe contenant la mthode main par laquelle doit dbuterlexcutiondelapplication.Lefichierinfos.txtcontientdansnotrecaslalignesuivante : Main-Class: ClientArdoiseMagique Nepasoublierleretourchariotlafindelaligneetlespaceaprslecaractre :. Larchiveestgnreaveclefichiermanifestsuivant : Manifest-Version: 1.0 Created-By: 1.6.0 (Sun Microsystems Inc.) Main-Class: ClientArdoiseMagique La version de la commande jar fournie avec le jdk 6 propose galement loptione permettant dindiquer le point dentredanslapplicationsansavoircrerdefichierintermdiaire.Lasyntaxepeutdonctrelasuivante : jar cvfe ardoise.jar ClientArdoiseMagique.class *

- 4-

ENI Editions - All rigths reserved

JavaWebStart
1.Prsentation
La technologie Java Web Start permet de dmarrer lexcution dune application par un simple clic sur un lien sans aucune installation de lapplication au pralable. Le lien pointe sur un fichier JNLP (Java Network Launching Protocol) contenantlesinformationspourqueJavaWebStarttlchargeetexcutelapplication. Lapplication peut tre dploye sur pratiquement nimporte quelle plateforme et bien sr excute sur une toute autre plateforme. la premire excution, lapplication est stocke dans un cache local du poste client. Cette technique amliore la rapidit des lancements ultrieurs et permet galement lexcution de lapplication mme si aucuneconnexionrseaunestdisponible.SiuneapplicationncessiteuneversionparticuliredelaplateformeJava et que celleci nest pas disponible sur le poste, Java Web Start tlcharge et installe automatiquement la bonne version. La scurit est galement prise en compte puisque Java Web Start nautorise que des accs limits aux ressourcesdisquesetrseauutilisablesparlapplication.

2.Excutionduneapplication
DeuxsolutionssontpossiblespourlexcutionduneapplicationavecJavaWebStart.

a.partirdunnavigateur
Le lancement de lapplication seffectue simplement en cliquant sur un lien pointant vers le fichier JNLP de lapplication. Le fichier est tlcharg puis Java Web Start en extrait toutes les informations ncessaires au fonctionnementdelapplication.

b.partirducachelocal
Une application peut galement tre excute partir des fichiers mis en cache lors dune excution prcdente. VousdevezutiliserlevisionneurdecacheJavapourafficherlalistedesapplicationsayantdjtexcutes.Le visionneurdecacheestdisponiblevialicneJavaduPanneaudeconfiguration.

ENI Editions - All rigths reserved

- 1-

SlectionnezensuiteloptionAfficherdelarubriqueFichiersInternettemporairesdelongletGnral.

- 2-

ENI Editions - All rigths reserved

LevisionneurducacheJavaaffichealorslalistedesapplicationsayantdjtutilises.

Diversesoptionssontalorsdisponiblesvialesboutonssuivantsdelabarredoutils:

ENI Editions - All rigths reserved

- 3-

Excute nouveau lapplication slectionne soit partir du serveur (en ligne), soit partir du cache Java (hors ligne). AffichelefichierJNLPdelapplication. Ajouteunraccourcisurlebureaupermettantdelancerlapplicationcommeuneapplicationclassique. Supprimelapplicationdelaliste.

Affichelapagedaccueildelapplicationdanslenavigateur.

3.Dploiementduneapplication
LedploiementduneapplicationavecJavaWebStartsedcomposeenquatreoprations:
q

ConfigurerleserveurWeb. CrerlefichierJNLP. PlacerlapplicationsurleserveurWeb. CrerlapageWebdaccueil.

Nousallonsdoncdtaillerchacunedecestapes.

a.ConfigurationduserveurWeb
La seule modification ncessaire sur le serveur Web consiste configurer le type MIME associ lextension de fichier .jnlp. Cette configuration est bien sr propre chaque type serveur. Pour un serveur Apache, il suffit simplementdajouteraufichiermime.typeslalignesuivante : application/x-java-jnlp-file JNLP PourunserveurIIS,ilfaututiliserlongletEnttesHTTPdelapagedepropritsduserveurWeb.

- 4-

ENI Editions - All rigths reserved

LeboutonTypesMIMEpermetdaccderlabotededialoguedegestiondestypesMIMEreconnusparleserveur Web.

LeboutonNouveauafficheunebotededialoguepermettantlasaisiedesinformationsconcernantletypeMIME ajouterauserveur.

ENI Editions - All rigths reserved

- 5-

Ilestsouventsouhaitablederedmarrerleserveurpourquilprenneencomptelesmodificationsdeconfiguration.

b.CrationdufichierJNLP
LefichierJNLPestllmentprincipaldudploiementavecJavaWebStart.Cefichierauformatxmlcontienttoutes lesinformationsncessairespourlexcutiondelapplication.LeformatdecefichierdoitrespecterlesJSR56(Java SpecificationRequests). Lediagrammecidessousreprsenteleformatattendupourcefichier.

Llmentjnlpestllmentracinedufichier.Sesattributsdcriventlespropritsdufichierjnlp. Llmentinformationestutilispourfournirlesinformationsconcernantlapplication.Ellesserontutilisespendant linstallationdelapplication. Llmentsecurityestutilispourobtenirunenvironnementscurislorslexcutiondelapplication. Llmentresourcesindiquequellessontlesressourcesfaisantpartiedelapplication. Le fichier jnlp se termine par un lment applicationdesc, appletdesc, componentdesc ou installerdesc en fonctiondutypedapplicationdployer.Unseuldeceslmentsdoittreprsentdanslefichier. Voicicidessousunexempledefichierjnlp: <?xml version="1.0" encoding="utf-8"?> <! fichier de deploiement pour lardoise magique --> <jnlp spec="1.0+" codebase="http://thierry.eni.fr/ardoiseMagique"

- 6-

ENI Editions - All rigths reserved

href="ardoise.jnlp"> <information> <title>ardoise magique</title> <vendor>thierry groussard</vendor> <homepage href="http://thierry.eni.fr/ardoiseMagique/install.html"/> <description kind="short">cette application permet de partager un espace de dessin entre plusieurs utilisateurs</description> <offline-allowed/> </information> <resources> <jar href="ardoise.jar"/> <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/> </resources> <application-desc main-class="ClientArdoiseMagique"/> </jnlp> Nousallonsdtaillerchacunedesinformationsprsentesdanscefichier. <?xml version="1.0" encoding="utf-8"?> : Cetteligneindiquequilsagitdundocumentconformeaustandardxml1.0etquelencodagedescaractresutilis estutf8. <! fichier de deploiement pour lardoise magique --> : Lignedecommentairesdansundocumentxml. <jnlp spec="1.0+" codebase="http://thierry.eni.fr/ardoiseMagique" href="ardoise.jnlp"> : Baliseracinedudocumentjnlp. Lattribut spec indique la version du protocole jnlp que doit accepter le client pour que linstallation soit possible. Dansnotrecas,ilfautqueleclientacceptelaversion1.0ouultrieure.Lapplicationpourradonctreinstallepar nimportequelclient. Lattributcodebaseindiquelemplacementracinedetouslesautresdocumentsrfrencsdanslefichierjnlppardes attributshref. Lattributhrefspcifielurlrelativedufichierjnlp.Cetteinformationestcombineaveclavaleurdelattributcodebase pourobteniruneurlabsolue. <title>ardoisemagique</title> TitredelapplicationutilispourlidentifierdanslevisionneurducacheJava. <vendor>thierrygroussard</vendor> NomdufournisseurdelapplicationaffichdanslevisionneurducacheJava. <homepagehref="http://thierry.eni.fr/ardoiseMagique/install.html"/> URLdelapagedaccueildelapplication.Cestcettepagequidoitcontenirunlienverslefichierjnlp. <description kind= "short">cette application permet de partager un espace de dessin entre plusieurs utilisateurs</description> Textededescriptionrapidedelapplication. <offlineallowed/> Indiquequelapplicationpeuttreexcutemmesiaucuneconnexionrseaunestdisponible.Cestdanscecasla versionmiseencachequiestexcute.Siuneconnexionrseauestdisponible,JavaWebStartvrifiesiuneversion plusrcentedelapplication est disponible sur le serveur. Si cestlecas,cest alors cette nouvelle version qui est excute.Sinoncestlaversionmiseencachequiestexcute.

ENI Editions - All rigths reserved

- 7-

<jarhref="ardoise.jar"/> Nomdufichierarchivecontenantlapplication. <j2seversion="1.6+"href="http://java.sun.com/products/autodl/j2se"/> Versiondujrencessairepourlebonfonctionnementdelapplication.Lesigne+aprslenumrodeversion,indique quilsagitduneversionminimalencessaire.Siuneversionultrieureestdisponiblesurleposteclient,lapplication pourra tre excute. Si le signe + nest pas indiqu, Java Web Start exigera la version exacte. Si elle nest pas disponiblesurleposteclient,lattribut hrefindiqueoellepeuttretlcharge.JavaWebStartproposealors lutilisateurdeffectuercetlchargement. <applicationdescmainclass="ClientArdoiseMagique"/> Indique que lapplication excuter est une application Java autonome et non une applet. Lattribut mainclass indique le nom de la classe contenant la mthode main permettant le dmarrage de lapplication. Cet attribut est optionnelsilefichierarchivedisposedunmanifestcontenantdjcetteinformation.

c.Dployerlapplicationsurleserveur
Cette tape est bien sr spcifique chaque serveur Web. En cas de doute, il est conseill de contacter ladministrateur du serveur. Voici titre dexemple, les oprations effectuer pour dployer lapplication sur un serveurWebIISdeWindowsXP.
s

Ouvrez le Gestionnaire des services Internet par loptionOutils dadministration du Panneau de configuration. AccdezensuiteausiteWebpardfaut.

AjoutezensuiteunrpertoirevirtuelparlemenucontextueldusiteWebpardfaut.Unassistantvousguidepour lacrationdurpertoirevirtuel.

Vousdevezlapremiretapefournirlaliasdurpertoirevirtuel.IlsagitdunomutilisdanslURLpouratteindre cetemplacement.

- 8-

ENI Editions - All rigths reserved

Ladeuximetapevousdemandedefournirlemplacementosetrouventlesfichierspublier.Cestengnralun rpertoiredundesdisquesdelamachine,maiscelapeuttregalementunpartagerseau.

La dernire tape configure les autorisations daccs accordes sur ce rpertoire virtuel. Seule lautorisation de lectureestobligatoire.

ENI Editions - All rigths reserved

- 9-

Aprslacrationdurpertoirevirtuel,ilestrecommanddarrteretderedmarrerleserveurWeb.

d.CrationdelapageWebdaccueil
Pendantcetteultimetape,vouspouvezlaissersexprimervostalentsartistiquespourconcevoirlapagedaccueil. Les seules contraintes sont davoir sur cette page un lien vers le fichier jnlp et de respecter le nom de la page daccueiltelquilestmentionndanslefichierjnlp.Lajoutduliensefaitaveclabalisehtmlsuivante: <a href="ardoise.jnlp">installation de lapplication ardoise magique </a>

- 10 -

ENI Editions - All rigths reserved