Cours Java 2008-2009 SRC Olivier Curé - UMLV [page 1 ] Olivier Curé Contact UMLV, bâtiment Copernic, 4B060 [email protected] URL : www.univ-mlv.fr/~ocure Profil : Thèse dans un laboratoire d'intelligence artificielle (LIAP-5). Mots clés de ma recherche : représentation des connaissances, ontologie, web sémantique, les langages XML, IHM, automédication. Olivier Curé - UMLV [page 2 ] Bibliographie Java in a nutshell 3ème édition française, O'reilly. Thinking in Java 2nde édition française (disponible gratuitement aux formats HTML et PDF sur le web : http://penserenjava.free.fr/). Le site java de Sun : http://java.sun.com et particulièrement le lien sur l'API : http://java.sun.com/j2se/1.5/docs/api/ Olivier Curé - UMLV [page 3 ] 1. Le langage Java Olivier Curé - UMLV [page 4 ] Historique du langage Java Java Javascript A l'origine, le langage Oak développé par SUN au début des 90. En 1994, Oak change de nom pour devenir Java. Les deux premières versions, Java 1.0 (95) et Java 1.1 (97) sont orientées Web. Java 1.2 (98), renommé Java 2 devient généraliste. Java 2 regroupe 3 fois plus de paquetages que Java 1.0. Olivier Curé - UMLV [page 5 ] Caractéristiques du langage Java Java est un langage orienté objet à classes (les objets sont décrits/regroupés dans des classes). dont la syntaxe est très proche de C. fourni avec le SDK (Software Development Kit) outils de développement, paquetages. portable comme l'indique son slogan " write once, run everywhere ". Olivier Curé - UMLV [page 6 ] Premier programme Java Le programme se nomme HelloWorld.java public class HelloWorld { public static void main(String args[]) { System.out.println("HelloWorld "); } } Olivier Curé - UMLV [page 7 ] Compilation Le code source ne peut être exécuté directement. En java, le code source est traduit dans un langage spécifique à Java : le " bytecode ". C'est le langage de la machine virtuelle java (JVM). Ce langage est indépendant de la machine, donc grande portabilité, puisqu'il existe des JVM pour toutes les architectures. Attention à la variable d'environnement CLASSPATH. Olivier Curé - UMLV [page 8 ] Compilation java (suite) Notre programme source se nomme HelloWorld.java. Après la compilation, on obtient un nouveau fichier HelloWorld.class, dont le contenu est du bytecode. HelloWorld.java compilation HelloWorld.class Ligne de commande : javac HelloWorld.java Olivier Curé - UMLV [page 9 ] Exécution du bytecode Le bytecode doit être exécuté par une JVM. Cette machine virtuelle est simulée par un interpréteur, qui lit chaque instruction du programme (bytecode) et le traduit dans le langage du processeur de l'ordinateur et lance son exécution. Ligne de commande : java HelloWorld Olivier Curé - UMLV [page 10 ] Avantages et inconvénients de la JVM Avantages : Portabilité, il existe des JVM pour l'ensemble des OS du marché. Le bytecode exporté est léger. Sécurité, la JVM lance de nombreuses vérifications sur le bytecode. Inconvénients : Lenteur de l'exécution (compilation + interprétation) mais d'autres alternatives existent. Olivier Curé - UMLV [page 11 ] Quelques règles fondamentales Le nom d'une classe commence toujours par une majuscule. Les mots contenus dans un identificateur commencent par une majuscule : HelloWorld. Les constantes sont en majuscules. Les propriétés et les méthodes débutent par une minuscule. Ajouter des commentaires, la syntaxe est identique au C (/* ... */ ou // ). Olivier Curé - UMLV [page 12 ] Eléments du langage Retour sur le langage C(1) Les blocs : Ouverture et fermeture avec "{" et "}". Arithmétiques : +,-,*,/,% (modulo) Logiques : && (et logique), || (ou logique), ! (inverse). Comparaisons : == (égalité), != (différence), >, <, <=, >= Opérateurs unaires : ++, - Assignations : +=, -=, *=, /= a = a + 1; équivalent à a++; équivalent à a+=1 Olivier Curé - UMLV [page 13 ] Eléments du langage Retour sur le langage C(2) Instruction conditionnelle : if (condition) instruction1; else Instruction2; Exemple Java: if(a>=10) System.out.println(" Accepté "); else System.out.println(" Refusé "); Olivier Curé - UMLV [page 14 ] Eléments du langage Retour sur le langage C(3) faux test La boucle while Syntaxe : Instructions while(condition) { instructions } Exemple : i = 0; while(i<10) { System.out.println("Valeur = "+ i); i++; } Remarque : On passe 0 à n fois dans la boucle. Olivier Curé - UMLV [page 15 ] Eléments du langage Retour sur le langage C(4) La boucle do while Syntaxe : Instructions do { test instructions } while(condition); faux Exemple : i = 0; do { System.out.println("Valeur = "+ i); i++; } while(i<10); Remarque : On passe 1 à n fois dans la boucle. Olivier Curé - UMLV [page 16 ] Eléments du langage Retour sur le langage C(5) La boucle for Syntaxe : for(initialisation;condition; pas) { instructions } Exemple : for(i=0; i<10;i++) System.out.println("Val = " + i); Remarques : On passe 0 à n fois dans la boucle. Rédaction plus concise. Olivier Curé - UMLV [page 17 ] Manipulation d'une variable Deux techniques : Par valeur où on utilise directement le nom de la variable. Par adresse (ou référence) où la variable est rangée dans la mémoire. Olivier Curé - UMLV [page 18 ] Types primitifs Déclaration des variables : <type> <identificateur>; Les types simples sont : pour les entiers : byte (1 octet, [-128 à 127]), short (2 octets, [-32768,32767]), int (4 octets,[-22147483648, 2147483647]) et long (8 octets,[-9.1018,9.1018]). pour les réels : float (4 octets en simle précision) et double (8 octets en double précision). le booléen: boolean (true ou false) le type caractère : char (1 seul caractère). Olivier Curé - UMLV [page 19 ] Types non primitifs Et les autres types : Les tableaux int[] tab = new int[10]; Les chaînes de caractères String nom = "Bonjour le monde!"; Les objets class Personne { String nom; int age; } Olivier Curé - UMLV [page 20 ] Variables et Java Les variables de type primitif (booléen, caractère, entier et réel) sont manipulées par valeur. Les variables de type non primitif sont manipulées par référence. Olivier Curé - UMLV [page 21 ] Exemple .. int[] tab = {15,10,5,8}; System.out.println("Tableau = "+ tab); .. Le résultat affiché est : Tableau = [I@ad3ba4 l'adresse du tableau, explication : [ pour un tableau, I pour integer et @xxxx pour l'adresse. Olivier Curé - UMLV [page 22 ] Exemple 2 .. 1:int[] tab = {15,10,5,8}; 2:int[] tab2 = new int[4]; 3:tab2 = tab; 4:tab[1] = 21; .. tab 1 15 10 5 tab2 if(tab==tab2) // vrai 3 8 4 21 Olivier Curé - UMLV [page 23 ] Exemple 3 .. 1:int[] tab = {15,10,5,8}; 2:int[] tab2 = new int[4]; 3:for(int cpt=0; cpt<4;cpt++) 4: tab2[cpt] = tab[cpt]; 5:if(tab==tab2) // faux, car 2 références distinctes. Olivier Curé - UMLV [page 24 ] 2. La programmation orientée objet Olivier Curé - UMLV [page 25 ] Historique de la POO Simula (1966) regroupe données et procédures. Simula I (1972) formalise les concepts d'objet et de classe. Un programme devient une collection d'objets actifs et autonomes. Smalltalk (1972) : généralisation de la notion d'objet. C++ (1983) : Extension du C s'inspirant de Simula. Java (1994) : d'abord pour le web puis généraliste. Autres : C#, eiffel, ada, clu, Object pascal, delphi, python, etc.. Olivier Curé - UMLV [page 26 ] Olivier Curé - UMLV [page 27 ] Motivation et avantages de POO Motivation : concevoir, maintenir et exploiter facilement de gros logiciels. Avantages : modularité, abstraction, productivité et réutilisabilité, sûreté, encapsulation. Les autres approches : structurée impérative (C), fonctionnelle (Lisp) et logique (Prolog). Olivier Curé - UMLV [page 28 ] Modularité et Abstraction Modularité : les objets forment des modules compacts regroupant des données et un ensemble d'opérations. Abstraction : Les entités objets de la POO sont proches de celles du monde réel. Les concepts utilisés sont donc proches des abstractions familières que nous exploitons. Olivier Curé - UMLV [page 29 ] productivité et réutilisabilité, sûreté productivité et réutilisabilité : Plus l'application est complexe et plus l'approche POO est intéressante en terme de productivité. Le niveau de réutilisabilité est supérieur à la programmation impérative. sûreté : L'encapsulation et le typage des classes offrent une certaine robustesse aux applications. Olivier Curé - UMLV [page 30 ] Les concepts fondamentaux Objet, classe et instance les membres de classe et d'instance envoi de message et méthode héritage, encapsulation et polymorphisme Constructeur et destructeur Classe abstraite / concrète Olivier Curé - UMLV [page 31 ] Objet Les objets sont omniprésents (humain, livre,etc.) dans notre monde. En POO : objet = identité + états + comportements L'identité doit permettre d'identifier sans ambiguïté l'objet (adresse/référence ou nom). Modélisation informatique : les états sont stockés dans des propriétés (variables) et les comportements sont implémentés à l'aide de méthodes (procédures / fonctions). Olivier Curé - UMLV [page 32 ] Exemple d'un objet Soit la modélisation d'un objet être humain. Son identité peut être son nom ou bien un numéro. Ses états seront sa taille, son poids, la couleur de ses yeux, etc.. Ses comportements seront respirer, marcher, parler, etc.. Olivier Curé - UMLV [page 33 ] Classe Le monde réel regroupe des objets du même type. Il est pratique de concevoir une maquette (un moule) d'un objet et de produire les objets à partir de cette maquette. En POO, une maquette se nomme une classe. Une classe est donc un modèle de la structure statique (variables d'instance) et du comportement dynamique (les méthodes) des objets associés à cette classe. Olivier Curé - UMLV [page 34 ] Instance Les objets associés à une classe se nomment des instances. Une instance est un objet, occurrence d'une classe, qui possède la structure définie par la classe et sur lequel les opérations définies dans la classe peuvent être appliquées. Olivier Curé - UMLV [page 35 ] Membre Membre = propriété + méthode Membre de classe Propriété de classe Une propriété de classe est associée à sa classe et non à une instance de cette classe. Méthode de classe Une méthode de classe est associée à une classe et non à un objet. Une méthode de classe ne peut exploiter que des membres de classe. Olivier Curé - UMLV [page 36 ] Membre (suite) Membre d'instance Propriété d'instance Une propriété d'instance est associée à une instance de la classe et non à la classe. Chaque objet possède donc sa propre copie de la propriété. Méthode d'instance Une méthode d'instance est associée à une instance d'une classe et non à la classe. Chaque objet possède donc sa propre copie de la méthode. Une méthode d'instance peut utiliser n'importe quel type de membre (classe ou instance). Olivier Curé - UMLV [page 37 ] Notion de message Un objet seul ne permet pas de concevoir une application garantissant les objectifs de la POO. Un programme est constitué d'objets. Ces derniers communiquent à l'aide de messages. Un message est composé : du nom de l'objet recevant le message, du nom de la méthode à exécuter et des paramètres nécessaires à la méthode. Objet A Objet B Olivier Curé - UMLV [page 38 ] Héritage Les objets sont définis à partir de classes. En POO, les classes sont définis à partir d'autres classes. Par exemple : un VTT est une sous-classe de Vélo. sous-classe n'est pas Une limitée aux caractéristiques de sa super-classe. Elle peut étendre cette dernière avec de nouvelles propriétés et méthodes. Vélo VTT Olivier Curé - UMLV [page 39 ] Encapsulation L'encapsulation est un mécanisme consistant à rassembler les données et les méthodes au sein d'une structure en cachant l'implémentation de l'objet, c'est-à-dire en empêchant l'accès aux données par un autre moyen que les services proposés. Ce mécanisme permet donc de garantir l'intégrité des données contenues dans l'objet. Olivier Curé - UMLV [page 40 ] Encapsulation (suite) état (propriété) L'encapsulation permet de définir le niveau de visibilité des éléments de la classe. Ils définissent les droits d'accès : - publique - privée - protégée. comportement (méthode) Olivier Curé - UMLV [page 41 ] Polymorphisme Le polymorphisme désigne un concept de la théorie des types, selon lequel un nom d'objet peut désigner des instances de classes différentes issues d'une même arborescence. Exemple : ObjetGraphique Rectangle Cercle Les classes Rectangle et Cercle héritent de la classe ObjetGraphique. On peut définir une instance Rect1 d'un Rectangle comme un ObjetGraphique. Olivier Curé - UMLV [page 42 ] Constructeur Un constructeur est une opération de classe gérant la construction d'objets. Le nom de cette méthode est identique à celui de sa classe. Olivier Curé - UMLV [page 43 ] Destructeur Un destructeur est une opération de classe qui détruit des objets. Cette méthode libère donc de l'espace mémoire. Olivier Curé - UMLV [page 44 ] Classe concrète/ abstraite Une classe concrète est une classe qu'il est possible d'instancier. Ce n'est pas le cas d'une classe abstraite. Une classe abstraite relève purement de l'organisation et son objectif est uniquement lié à la spécification (description exhaustive d'un élément d'une modélisation). Olivier Curé - UMLV [page 45 ] 3. POO en Java Olivier Curé - UMLV [page 46 ] Déclaration d'une classe Il est préférable de définir une unique classe par fichier java. Cette classe est alors publique et donne son nom au fichier Exemple : public class Cercle { ... // définition des membres } Le nom du fichier est nécessairement Cercle.java (respecter la casse). Olivier Curé - UMLV [page 47 ] Création d'un objet : new La seule manière de créer un objet en Java est d'utiliser l'opérateur new. Cet opérateur doit être suivi du nom de la classe à instancier. Exemple : String chaine = new String(); String salut = new String(" Bonjour "); ParserXML parserXml = new ParserXML(); Syntaxe : <classe> <référence sur objet> = new <constructeur de la classe>; Olivier Curé - UMLV [page 48 ] Opérateur new L'instanciation d'une classe déclenche les actions suivantes : création de l'objet, allocation mémoire nécessaire à cet objet, appel du constructeur de la classe. Olivier Curé - UMLV [page 49 ] Constructeur en Java Toute classe possède un constructeur par défaut, implicite. Un constructeur porte nécessairement le même nom que sa classe, sans type de retour. Il peut y avoir plusieurs constructeurs dans une même classe. Ceux-ci diffèrent par le nombre et la nature de leurs paramètres. Olivier Curé - UMLV [page 50 ] Destructeur en Java En java, la destruction des objets est prise en charge par le garbage collecteur (GC) ou ramasse-miettes. Le GC détruit les objets pour lesquels il n'existe plus de référence. Aucune garantie n'est apportée quant à la destruction des objets. On peut forcer le mécanisme à l'aide de la méthode finalize. Olivier Curé - UMLV [page 51 ] Critéres de visibilité des membres L'accessibilité des membres est pondérée par des critères de visibilité donnés par les modificateurs suivants : public : accessible hors de la classe private : accessible uniquement dans la classe protected: accessible dans toutes les classes du package et ses dérivées (pas spécifié) : accessible dans toutes les classes du package. Olivier Curé - UMLV [page 52 ] Règles d'accès aux membres accessible à : public protected package private Classe de définition Oui Oui oui oui Classe du même package oui oui oui non Sous-classe dans un oui oui non non oui non non oui package différent Classe qui n'est pas une sous-classe dans un package différent Olivier Curé - UMLV [page 53 ] Réflexivité d'un objet : this Tout objet se " voit " lui-même. Le mot clé this permet de montrer qu'une méthode accède à ses propres propriétés et/ou méthodes. Olivier Curé - UMLV [page 54 ] Invocation de méthodes L'invocation d'une méthode s'effectue en nommant l'instance et en la faisant suivre du nom de la méthode avec la liste des paramètres, éventuellement vide. <objet>.methode(parametres); Le passage de paramètres dans les méthodes dépend de la nature des paramètres : - par référence pour les objets. - par copie pour les types primitifs. NB : - Pour être invoquées à l'extérieur de la classe, les méthodes doivent faire partie de l'interface publique de l'instance. Olivier Curé - UMLV [page 55 ] Invocation des attributs Il est possible d'accéder aux attributs à condition que la définition de la classe le permette. <objet>.nom_attribut; La spécification de l'objet n'est pas obligatoire si l'accès est réalisé au sein d'une méthode de la classe courante. Le respect des principes de l'encapsulation impose de fournir des méthodes d'accès aux attributs. Olivier Curé - UMLV [page 56 ] Exemple invocation des attributs public class Exemple { public int x; private int y; ...} public class ExempleTest { public static void main(String args[]) { Exemple ex1 = new Exemple(); ex1.x = 10; ex1.y =5; System.out.println(ex1.x + " } } " + ex1.y); Correct ? Olivier Curé - UMLV [page 57 ] Exemple: classe Cercle 4 méthodes dont 2 constructeurs. 2 propriétés dont une constante. Le fichier se nomme Cercle.java public class Cercle { private double rayon; public static final double PI = 3.14159; public Cercle() { rayon = 1.0; } public Cercle(double rayon) { this.rayon = rayon; } public double circonference() { return 2*PI*rayon; } public double surface() { return PI*rayon*rayon; } } Olivier Curé - UMLV [page 58 ] Exemple: classe CercleTest public class CercleTest { public static void main(String args[]) { Cercle c1 = new Cercle(); System.out.println(" Surface de c1 = " +c1.surface()); Cercle c2 = new Cercle(5.5); System.out.println(" Circonference de c2 = " + c2.circonference()); } } Le fichier CercleTest.java est exécutable (il y a une méthode main). Olivier Curé - UMLV [page 59 ] Les tableaux en Java En java, les tableaux sont considérés comme des objets : - création à l'aide de l'opérateur new, - héritage des méthodes d'instances de Object. - les variables du type tableau manipulent des références aux tableaux, - possèdent une propriété d'instance final int length qui donne la taille du tableau. Olivier Curé - UMLV [page 60 ] Les tableaux en Java (2) Déclaration et création int[] monTableau = new int[10]; Déclaration, création et initialisation int[] monTableau2 = {1,2,3,4,5}; Un tableau en Java s'exploite de la même manière qu'un tableau en C. monTableau[0] = 0; // initialisation de la 1ère cellule Il est possible de manipuler des tableaux multidimensionnés. int[][] monTableau3 = new int[][]; Olivier Curé - UMLV [page 61 ] Membres statiques Rappel : membres = méthodes + attributs En java, on définir un membre de classe à l'aide du mot réservé static. Dans la classe Cercle, PI est statique => Quelque soit le nombre d'instances de Circle, il n'y aura qu'un exemplaire de PI. Pour accéder à un membre statique, il faut le précéder du nom de sa classe. Olivier Curé - UMLV [page 62 ] Membres statiques 2 Explication de "System.out.println(..)" La classe System contient une propriété de classe dont le nom est out. L'objet System.out appelle une méthode objet de nom println(). Olivier Curé - UMLV [page 63 ] Mot réservé : final Le mot réservé final déclare une constante et impose à l'attribut de ne pouvoir être modifié par la suite. Exemple : public static final double PI = 3.14159; Olivier Curé - UMLV [page 64 ] 4. Héritage, classe abstraite, interface et paquetage Olivier Curé - UMLV [page 65 ] Héritage En java, il n'existe que de l'héritage simple. L'héritage multiple est : trop complexe et peut provoquer des problèmes sur les références(C+ +). Le parent commun à toutes les classes est : Object. La définition d'une sous-classe est réalisée à l'aide du mot réservé extends. Cette sous-classe hérite alors des méthodes et attributs de sa super-classe. L'opérateur instanceOf permet de déterminer la classe d'une instance (résultat booléen). Olivier Curé - UMLV [page 66 ] Constructeur d'une sousclasse Le constructeur d'une sous-classe invoque le constructeur de sa super-classe (première instruction). Le désignateur super permet de faire référence à sa super-classe. Olivier Curé - UMLV [page 67 ] Exemple d'héritage public class Ellipse { Ellipse public double r1, r2; public Ellipse(double r1, double r2) {this.r1 = r1; this.r2 = r2;} public double surface() {...} } public class Cercle extends Ellipse { public Cercle(double r) {super(r,r);} public double rayon() {return r1;} } Ellipse e = new Ellipse(2.0, 3.0); Cercle c = new Cercle(4.0); System.out.println(e instanceof Cercle); // false System.out.println(e instanceof Ellipse); // true System.out.println(c instanceof Cercle); // true System.out.println(c instanceof Ellipse); // true:c dérive de Ellipse System.out.println(c instanceof Object); // true Cercle Olivier Curé - UMLV [page 68 ] Redéfinition de méthodes Une méthode héritée peut être redéfinie dans une sous-classe : il faut alors la réécrire en conservant la même signature (paramètres et type de retour). Exemple : Cercle peut redéfinir " surface " de Ellipse. La méthode redéfinie peut exploiter super sur la méthode de sa super-classe. Olivier Curé - UMLV [page 69 ] Exemple de redéfinition de méthodes public class Cercle extends Ellipse { public Cercle(double r) {super(r,r);} public double rayon() {return r1;} public double surface() {... super.surface(); ... } } Olivier Curé - UMLV [page 70 ] Surcharge de méthodes On réalise une surcharge de méthodes lorsque l'on déclare 2 méthodes de même nom mais avec des signatures différentes : par le nombre et/ les types de paramètres. Par contre, le type de retour doit être identique. On retrouve ce mécanisme lors de la définition de constructeurs et lors de l'implémentation de sous-classe (surcharge d'une méthode de la super-classe). Olivier Curé - UMLV [page 71 ] Redéfinition surcharge On surcharge une méthode quand on garde le même nom et le même type de retour mais pas les mêmes paramètres dans la même classe ou sous-classes. Olivier Curé - UMLV [page 72 ] Masquage de variables Une sous-classe peut redéfinir les variables portant le même nom que celles de sa super-classe. Une sous-classe peut accéder aux variables de sa super-classe à l'aide de casting ou bien de super. Olivier Curé - UMLV [page 73 ] Retour sur le mot réservé : final Une classe déclarée final ne peut être étendue. De même, une méthode déclarée comme final ne peut être redéfinie. Enfin, une variable déclarée comme final ne peut être masquée. Olivier Curé - UMLV [page 74 ] Classe abstraite Elle se trouve au sommet de la hiérarchie des classes. Elle définit l'interface des méthodes et ne peut être instanciée. Définir des méthodes abstraites dans une classe impose que la classe soit abstraite et que les sous-classes implémentent ses méthodes pour devenir concrètes. Une classe abstraite contient généralement au moins une méthode abstraite. Une méthode abstraite n'est pas implémentée. Olivier Curé - UMLV [page 75 ] Exemple Classe abstraite abstract class GeometriePlane { static final double PI = 3.14159; abstract double perimetre(); abstract double surface(); } class Disque extends GeometriePlane { float rayon; public double perimetre() {return 2*GeometriePlane.PI*rayon;} public double surface() {return GeometriePlane.PI*rayon*rayon;} } class Rectangle extends GeometriePlane { float largeur, hauteur; public double perimetre() {return 2*(largeur+hauteur);} public double surface() {return largeur*hauteur;} } Olivier Curé - UMLV [page 76 ] Interface Une interface Java ( interface graphique) est une classe où toutes les méthodes sont abstraites. Cette notion "remplace" l'héritage multiple car une classe peut implémenter plusieurs interfaces. Le mot clé abstract n'est pas utilisé. On ne peut pas instancier une interface. Définition d'une interface à l'aide de l'instruction interface. La sous-classe implémente une interface à l'aide de l'instruction implements. Olivier Curé - UMLV [page 77 ] Exemple interface abstract class GeometriePlane { abstract double perimetre(); } interface Dessinable { public void dessiner(); } public class Rectangle extends GeometriePlane implements Dessinable { double largeur, hauteur; public double perimetre() {return 2*(largeur+hauteur);} public void dessiner() {....} } public class Disque extends GeometriePlane implements Dessinable { double rayon; public double perimetre() {return 2*Math.PI*r;} public void dessiner() {....} } Olivier Curé - UMLV [page 78 ] Interface (2) On peut manipuler les rectangles et les disques comme des Dessinable à l'aide du polymorphisme : Dessinable formes[] = {new Disque(5), new Rectangle(2,3)}; for(int i = 0; i < formes.length; i++) { formes[i].dessiner(); } Une interface peut étendre une autre interface à l'aide de l'instruction extends. La hiérarchie des interfaces est différente de celle des classes. Dans la pratique, une interface ne peut contenir que des méthodes publiques et des attributs constants. Olivier Curé - UMLV [page 79 ] Paquetage ou package Un paquetage regroupe un ensemble de classes (et interfaces) liées à un même domaine particulier (par exemple gestion des bases de données, accès au réseau, etc.). Les objectifs sont : - organisation cohérente des classes et interfaces. - facilite le développement de bibliothèques. - protection supplémentaire avec le mode protégé. Olivier Curé - UMLV [page 80 ] Création d'un package Il faut ajouter en tête de l'unité de compilation (du fichier) package NomDuPackage; - indique à quel package appartient la (ou les) classe(s) du fichier. Exemple d'un package d'objets graphiques : package Graphics; interface Dessinable {...} class Disque {...} class Rectangle {...} class Cercle {...} Olivier Curé - UMLV [page 81 ] Utilisation des classes d'un package Les classes (ou interfaces) d'un package peuvent être utilisées (importées) individuellement ou de manière globale (le package entier) par toute autre unité de compilation désirant les utiliser. Seules les classes déclarées publiques (public) dans le package sont accessibles. En dehors du package, les noms des classes sont : NomDuPackage.NomDeLaClasse. L'instruction import NomDuPackage permet d'utiliser (importer) les classes sans les préfixer par leur nom de package - si pas d'importation (import), il faut indiquer le nom complet de la classe NomDuPackage.NomDeLaClasse pour l'exploiter. Olivier Curé - UMLV [page 82 ] Importation des packages et des classes 4 formes pour spécifier l'importation pas d'import : class TestImport1 { public static void main(String args[]) { java.awt.Point p = new java.awt.Point(1,2); } import package.comp1...compn; import java.awt : class TestImport2 { public static void main(String args[]) { awt.Point p = new awt.Point(1,2); } Olivier Curé - UMLV [page 83 ] API : Interface de programmation des applications Core API regroupe un ensemble de classes prédéfinies d'usage général que l'on retrouve sur toutes les platesformes. Core API est découpée en plusieurs packages : java.applet : Gestion des applets java.awt : Gestion du fenêtrage et de son contenu (Cf. swing) java.io : Gestion des entrées-sorties et des fichiers java.lang : Gestion des types et des éléments de base du langage java.net : Gestion de la communication sur le réseau java.util : Structures de données et utilitaires java.rmi : Remote Method Invocation, appli. distribuée java.security : Signatures digitales, contrôle d'accès. Olivier Curé - UMLV [page 84 ] Importation des packages et des classes (2) import package.comp1...compn.Class : import java.awt.Point; class TestImport3 { public static void main(String args[]) { Point p = new Point(1,2); } import package.comp1...compn.*: import java.awt.*; class TestImport4 { public static void main(String args[]) { Point p = new Point(1,2); Rectangle r = new Rectangle(); } Olivier Curé - UMLV [page 85 ] Exception En Java, le traitement de certaines erreurs est automatique. Lorsqu'une méthode détecte une erreur, elle lève une exception. Celle-ci est équivalente à un signal ou à une interruption logicielle. Une exception est un objet Java (instance de la classe Exception) envoyé à la JVM. Olivier Curé - UMLV [page 86 ] Principe des exceptions Le principe des exceptions en java est le suivant : toute méthode qui a un problème lève (throw) une exception . tout code qui appelle cette méthode doit attraper (catch) cette exception. la plupart des exceptions demandent à être "attrapées" faute de quoi le programme s'arrête en cours d'exécution. la recherche se fait en local, puis remonte la liste des appelants - acquittement de l'exception et reprise du code. Structures spécialisées : try {...} catch {...} Olivier Curé - UMLV [page 87 ] Exploitation des exceptions Il est nécessaire de séparer le bloc d'instructions pouvant engendrer des erreurs. Ce bloc est insérer au niveau d'un try. Le(s) bloc(s) catch permet(tent) de récupérer la main pour traiter l'exception. On peut aussi utiliser ces blocs pour spécialiser les traitements. Olivier Curé - UMLV [page 88 ] Exemple de gestion d'une exception try { x = System.in.read(); } catch (IOException e) { System.out.println("Erreur : " + e.getMessage()); } Olivier Curé - UMLV [page 89 ] 5. Collections dans Java Olivier Curé - UMLV [page 90 ] Présentation générale Une collection est un objet qui contient d'autres objets. Ces objets proposent une solution au stockage de données et permettent une manipulation de celles-ci Les classes et interfaces se trouvent dans le paquetage : java.util. Olivier Curé - UMLV [page 91 ] Collections et versions de Java Premières versions de Java : Tableaux Vector : tableaux dynamiques (listes) Hashtable : tables associatives A partir de Java2, existence d'une infrastructure pour la gestion de collections ( dans le package java.util). Olivier Curé - UMLV [page 92 ] Infrastructure Offre une architecture unifiée pour représenter et manipuler les collections. Composée de 3 parties : Une hiérarchie d'interfaces permettant de représenter les collections sous forme de types abstraits. Des implémentations de ces interfaces. Implémentation de méthodes liées aux collections (recherche, tri, etc.). Olivier Curé - UMLV [page 93 ] Avantages Les collections permettent de : Améliorer la qualité et la performance des applications Réduire l'effort lors de l'implémentation Faciliter l'apprentissage de nouvelles API Réduire le coût de conception de nouvelles API Encourager le réutilisation de logiciels. Olivier Curé - UMLV [page 94 ] Interfaces 2 hiérarchies principales : Map : collections indexées par des clés (Cf. Entrées d'un dictionnaire) Collection Olivier Curé - UMLV [page 95 ] Classes Abstraites : AbstractCollection, AbstractMap, AbstractList, ... Concrètes : ArrayList, HashSet, TreeSet, HashMap, ... Elles héritent des classes abstraites Olivier Curé - UMLV [page 96 ] Interface Collection Un objet qui est un groupe d'objets Principales méthodes : boolean add(Object obj) boolean contains(Object obj) boolean containsAll(Collection collection) Iterator iterator() int size() Object[] toArray() Object[] toArray(Object[] tableau) Olivier Curé - UMLV [page 97 ] Interface Set Un groupe d'objets n'acceptant pas 2 objets égaux (au sens de equals). Implémentations : HashSet garantit un temps constant pour les opérations de base (set, size, add, remove). TreeSet garantit que les éléments sont rangés dans leur ordre naturel (interface Comparable) ou l'ordre d'un Comparator. Olivier Curé - UMLV [page 98 ] Interface List Un groupe d'objets repérés par des numéros (en débutant à l'indice 0). Classes implémentées : ArrayList (tableau à taille variable), LinkedList (listechaînée) En règle générale, on utilise ArrayList maisLinkedList est utile si il y a beaucoup d'opérations d'insertions/suppressions (evite les décalages). Olivier Curé - UMLV [page 99 ] Classe ArrayList Une sorte de tableau contenant un nombre quelconque d'instances de la classe Object (utiliser Integer pour ranger des entiers). Les emplacements sont repérés par des valeurs entières (à débutant à 0, comme un tableau). Les méthodes ne sont pas synchronisées (Vector). Olivier Curé - UMLV [page 100 ] Méthodes de ArrayList boolean add(Object obj) void add(int indice, Object obj) boolean contains(Object obj) Object get(int indice) => casting l'élément. int indexOf(Object obj) Iterator iterator() void remove(int indice) void set(int indice, Object obj) int size() Olivier Curé - UMLV [page 101 ] Exemple d'ArrayList ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto"); liste.add(p1); // création d'autres instances de Personne for (int cpt=0; cpt<liste.size();cpt++) System.out.println(((Personne)liste.get(cpt)).getNom( )); } Olivier Curé - UMLV [page 102 ] Interface Iterator Une interface permettant d'énumérer les éléments contenus dans une collection. Toutes les collections proposent une méthode itérator renvoyant un itérateur. Olivier Curé - UMLV [page 103 ] Méthodes d'Iterator boolean hasNext() object next() Lance une exception NoSuchElementException lorsqu'il n'y a plus rien à renvoyer. Olivier Curé - UMLV [page 104 ] Exemple d'Iterator ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto"); liste.add(p1); // création d'autres instances de Personne Iterator it = liste.iterator(); while(it.hasNext()) { System.out.println(((Personne)it.next()).getNom()); } Olivier Curé - UMLV [page 105 ] Exemple d'Iterator (2) ArrayList liste = new ArrayList(); Personne p1 = new Personne("Toto", "Marie"); liste.add(p1); // création d'autres instances de Personne Iterator it = liste.iterator(); while(it.hasNext()) { Personne tmp = (Personne)it.next(); System.out.println(tmp.getNom()+" "+tmp.getPrenom()); } Olivier Curé - UMLV [page 106 ] Interface Map Des couples clé-valeur. Une clé repère une unique valeur. Implémentations : HashMap : table de hachage avec garantie d'un accès en temps constant. TreeMap : arbre ordonnée* suivant les valeurs des clés (accès en log(n)). * ordre naturel ou une instance de Comparator. Olivier Curé - UMLV [page 107 ] Méthodes de Map boolean containsKey(Object clé) boolean containsValue(Object valeur) Set entrySet() Object get(Object clé) // null si objet n'existe pas. boolean isEmpty() Set keySet() int size() Collection values() Olivier Curé - UMLV [page 108 ] Table de hachage Une table de hachage range des éléments en les regroupant dans des sous-ensembles pour les retrouver plus rapidement. Le regroupement dépend de la valeur d'un calcul effectué sur les éléments. On retrouve l'élément en fournissant la valeur. Recherche efficace si répartition uniforme des éléments sur les sous-ensembles. Olivier Curé - UMLV [page 109 ] Classe HashMap Utilise la structure d'une table de hachage pour ranger les clés. La méthode hashCode() est exploitée pour répartir les clés dans la table de hachage. Olivier Curé - UMLV [page 110 ] Exemple de HashMap Map hm = new HashMap(); Personne p1 = new Personne("Toto"); p1.setMatricule("p99"); hm.put(p1.getMatricule(), p1); . . // création d'autres instances de Personne Personne p2 = (Employe)hm.get("p101"); Collection elements = hm.values(); Iterator it = elements.iterator(); while (it.hasNext()) { System.out.println( ((Personne)it.next()).getNom()); } Olivier Curé - UMLV [page 111 ] Trier une liste import java.util.*; public class Coll1 { public static void main(String args[]) { List liste = new ArrayList(); liste.add( new Integer(9)); liste.add(new Integer(12)); liste.add(new Integer(5)); Collections.sort(liste); Iterator it = liste.iterator(); while (it.hasNext()) { System.out.println( ((Integer)it.next()).toString()); } } } Olivier Curé - UMLV [page 112 ] Recherche dans une liste import java.util.*; public class ListePersonneTest { public static void main(String[] args) { List liste = new ArrayList(); Personne p1 = new Personne("Xyel","Pierre"); Personne p2 = new Personne("Durand","jean"); Personne p3 = new Personne("Smith","Joe"); liste.add(p1); liste.add(p2); liste.add(p3); Collections.sort(liste, new ComparatorPersonne()); System.out.println("Recherche ="+ Collections.binarySearch(liste,p1,new ComparatorPersonne())); } } // Exécution : Rercherche = 2. Olivier Curé - UMLV [page 113 ] Interface Comparator Elle propose une méthode : int compare(Object o1, Object o2) Elle doit renvoyer : Un entier positif si o1 est "plus grand" que o2. 0 si la valeur de o1 est identique à celle de o2. Une entier négatif si o1 est "plus petit" que o2. Olivier Curé - UMLV [page 114 ] Exemple d'un Comparator import java.util.Comparator; public class ComparatorPersonne implements Comparator { public int compare(Object o1, Object o2) { String nom1 = ((Personne) o1).getNom(); String nom2 = ((Personne) o2).getNom(); return nom1.compareTo(nom2); } } Olivier Curé - UMLV [page 115 ] Utilisation d'un Comparator import java.util.* public class ListePersonneTest { public static void main(String[] args) { List liste = new ArrayList(); Personne p1 = new Personne("Xyel","Pierre"); Personne p2 = new Personne("Durand","jean"); Personne p3 = new Personne("Smith","Joe"); liste.add(p1); liste.add(p2); liste.add(p3); Collections.sort(liste, new ComparatorPersonne()) } } Olivier Curé - UMLV [page 116 ] 6. Interactions HommeMachine Olivier Curé - UMLV [page 117 ] Introduction Les programmes informatiques nécessitent des interactions avec les utilisateurs : questionner, saisir et afficher. Cette interaction (homme-machine IHM) peut s'effectuer en mode console ou graphique. Cette partie du cours porte sur les GUI (Graphical User Interface) en Java. Olivier Curé - UMLV [page 118 ] IHM Utilisabilité : Accessibilité : proposer efficacement et garantir la facilité d'apprentissage pour l'utilisateur de manipuler ses entrées et interpréter les sorties. naturellement l'accès à différentes fonctionnalités. Approprié : Versatilité : garantir une réponse appropriée et pertinente aux différentes situations rencontrées. garantir une utilisation optimale dans différents contextes et situations. Olivier Curé - UMLV [page 119 ] IHM et programmation Eléments graphiques Fenêtre, bouton, zones de texte et saisie, menu, liste, etc.. Programmation événementielle Écouteurs - listeners Écoutés handleEvent Olivier Curé - UMLV [page 120 ] Modèle Vue Contrôleur (MVC) Le modèle représente les données de l'application. La vue représente visuellement les données. Le contrôleur gère l'interaction utilisateur avec le modèle. Olivier Curé - UMLV [page 121 ] MVC (suite) Le modèle contient les données et gère la miseà-jour et le renseignement des données. La vue affiche les composants et les données. Elle gère la mise-à-jour (graphique, textuelle), la notification des modifications au contrôleur et le renseignement. Le contrôleur écoute les actions produites dans la vue et récupère des informations de la vue, met à jour le modèle, récupère les nouvelles données de la vue pour les transmettre à la vue. Olivier Curé - UMLV [page 122 ] MVC (fin) Avantages : Séparation entre les données et la présentation. Données stockées à un endroit connu. Modifications plus faciles Olivier Curé - UMLV [page 123 ] GUI et Java Trois toolkits pour les GUI en Java : AWT (Abstract Windowing Toolkit) Swing SWT (Standard Widget Toolkit) Les programmes de GUI sont dirigés par événements. Olivier Curé - UMLV [page 124 ] Toolkits GUI Java AWT, développé par SUN et présent depuis le JDK 1.0. Swing, développé par SUN et présent depuis le JDK 1.2. SWT, développé par IBM et présent depuis JDK 1.2. Le cours porte essentiellement sur Swing et un peu sur AWT. Olivier Curé - UMLV [page 125 ] AWT Chaque composant Java présente un « peer » C++ correspondant au composant de la plateforme. Problème : aspect/focntionnement différents sur les différentes plateformes. Olivier Curé - UMLV [page 126 ] Swing Swing est construit au-dessus de AWT : la gestion des événements est identique et les classes Swing héritent de AWT. Les composants Swing ont un nom qui débute par un "J". Swing offre une palette bien plus large, plus élaborée fonctionnellement et esthétiquement mais est plus lent et plus lourd que AWT. Olivier Curé - UMLV [page 127 ] SWT Développé par IBM pour l'IDE Eclipse. Même principe que AWT mais avec un « peer » Java et non C++. Pas intégré au JDK Le cours ne porte pas sur SWT, seulement sur AWT et surtout SWING qui est le plusutilisé actuellement. Olivier Curé - UMLV [page 128 ] Composant et Container AWT, SWT et Swing utilisent des classes différentes pour représenter chaque composant graphique. Exemple pour les composants : Pour AWT : Component Pour Swing : Jcomponent SWT : Widget Container : un composant contenant des composants. Olivier Curé - UMLV [page 129 ] Composant et Container Attention : Tout JComponent est un Container ! Olivier Curé - UMLV [page 130 ] Composants Swing 3 types de composants : Les composants lourds qui correspondent à des fenêtres de la plateforme : JFrame, JDialog, JWindow, Japplet. Ils sont gérés par AWT. Les composants légers sont du code "pur Java" qui les dessinent : JButton , JTextfield, JLabel, etc.. La plupart correspondent à des sous-classes de la classe JComponent. les conteneurs intermédiaires : JPanel, JScrollPane, JTabbedPane, etc.. Olivier Curé - UMLV [page 131 ] Composants Window : une fenêtre sans bordure Frame : fenêtre principale d'application Panel : conteneur de composants que l'on place dans une fenêtre. Applet : permet l'ouverture d'un emplcament dans un navigateur internet ScrollPane : conteneur supportant une barre de défilement. Olivier Curé - UMLV [page 132 ] Look and Feel Avec Swing, il est possible de modifier l'aspect graphique (look and feel) d'un ensemble de composants. Des exemples : Windows (com.sun.java.swing.plaf.windows.WindowsLookAndFeel). Motif (com.sun.java.swing.plaf.motif.MotifLookAndFeel). Metal (javax.swing.plaf.metal.MetalLookAndFeel). GTK (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). Olivier Curé - UMLV [page 133 ] Exemple 1 JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; class FrameTd1 extends JFrame { public FrameTd1() { setTitle("Ma JFrame"); setSize(200,200); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } } public class FrameTd1Test { public static void main(String args[]) { JFrame frame1 = new FrameTd1(); frame1.setVisible(true); } } Olivier Curé - UMLV [page 134 ] Exemple 1 (suite) import javax.swing.*; import java.awt.*; import java.awt.event.*; class FrameTd1 extends JFrame { public FrameTd1() { setTitle("Ma JFrame"); setSize(200,200); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } } Fixe le nom de la fenêtre et sa taille Fermeture du process en même temps que fermeture de la fenêtre. On peut aussi utiliser la méthode setDefaultCloseOperation(JF rame.EXIT_ON_CLOSE). Olivier Curé - UMLV [page 135 ] Exemple 1 (fin) public class FrameTd1Test { public static void main(String args[]) { JFrame frame1 = new FrameTd1(); frame1.setVisible(true); } } Création d'une instance de la classe Frame1 Affichage à l'écran de cette instance de Frame1. Olivier Curé - UMLV [page 136 ] Ajouter des éléments dans une JFrame La méthode getContentPane() de la classe JFrame retourne le conteneur (Container) de cette JFrame. A partir de ce conteneur, on peut ajoter des éléments à la fenêtre. Il est également possible de changer le conteneur à l'aide de setContentPane(). Olivier Curé - UMLV [page 137 ] Ajouter des éléments dans une Jframe (2) Pour ajouter un élément à ce conteneur, on utilise un méthode add(component). le paramètre de add est un objet du type Component, par exemple un JButton, JLabel ou bien un élément intermédiaire JPanel. Olivier Curé - UMLV [page 138 ] Exemple 2 JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; public class FrameTd2Test { public static void main(String args[]) { JFrame frame2 = new FrameTd1(); Container contentPane2 = frame2.getContentPane(); JButton jb1 = new JButton("Bouton #1"); jb1.setBackground(Color.red); contentPane2.add(jb1); frame2.setVisible(true); JFrame frame21 = new FrameTd1(); Container contentPane21 = frame21.getContentPane(); JLabel jl1 = new JLabel("Un label dans le second cadre"); contentPane21.add(jl1); frame21.setVisible(true); } } Olivier Curé - UMLV [page 139 ] La classe JComponent Taille d'un composant : taille actuelle avec get/setSize() taille préférée avec get/setPreferredSize() Taille minimale avec get/setMinimumSize() Taille maximale avec get/setMaximalSize() Etat : activation avec is/setEnabled() visibilté avec is/setVisible() Olivier Curé - UMLV [page 140 ] Quelques JComponent : boutons Plusieurs classes pour les boutons qui héritent toutes de AbstractButton : JButton JCheckBox correspondant à une case à cocher. JRadioButton correspondant à un bouton radio. Pour avoir un seul bouton sélectionné à la fois, il faut intégrer les boutons dans un ButtonGroup Olivier Curé - UMLV [page 141 ] Quelques JComponent :JPanel Sert à regrouper des composants dans une zone écran. Ne possède pas d'aspect visuel déterminé; son aspect visuel est conditionné par ses composants. Olivier Curé - UMLV [page 142 ] Exemple 3 import java.awt.Container; import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JRadioButton; public class ButtonPanel extends JFrame { public JPanel createGroup(JPanel panel) { ButtonGroup buttonGroup = new ButtonGroup(); for(int cpt=0; cpt<5;cpt++) { JRadioButton radioButton = new JRadioButton("#"+cpt); panel.add(radioButton); buttonGroup.add(radioButton); } return panel; } public ButtonPanel() { JPanel panel = new JPanel(); Container contentPane = this.getContentPane(); contentPane.add(createGroup(panel)); } public static void main(String[] args) { ButtonPanel buttonPanel = new ButtonPanel(); buttonPanel.setVisible(true); } } Olivier Curé - UMLV [page 143 ] Quelques Jcomponent: JLabel, JTextField,JTextArea Ils prennent un texte lors de la construction. JLabel permet d'afficher du texte mais on ne peut interagir avec. JTextArea et JtextField offrent des zones où l'on peut saisir du texte. Olivier Curé - UMLV [page 144 ] Quelques JComponent: liste et liste déroulante JComboBox et JList peuvent prendre un tableau à la construction. Exemple : Object[] tableau = new Object[5]; Jlist list = new Jlist(tableau); list.setVisibleRowCount(3); ... JcomboBox comboBox = new JComboBox(tableau); Olivier Curé - UMLV [page 145 ] Layout manager Le placement des composants est réalisé à l'aide de layout manager et non au pixel près. Utilisabilité pour l'agrandissement/réduction de composants lourds. Un layout manager est associé au container. Olivier Curé - UMLV [page 146 ] Layout (2) Un layout manager utilise les tailles d'un composants pour les placer dans son container, les méthodes sont : getPreferredSize() getMaximalSize() getMinimalSize() La méthode pack() de JFrame redimensionne sa taille en fonction de la taille préférée de chacun des container. Olivier Curé - UMLV [page 147 ] Layout (3) On peut redimmensionner un composant : setSize(largeur, hauteur) setPreferredSize(dimension) Olivier Curé - UMLV [page 148 ] Layout (4) 2 types de layout : sans contrainte : FlowLayout, GridLayout et BoxLayout. avec contraintes : BorderLayout et GridBagLayout. Olivier Curé - UMLV [page 149 ] FlowLayout Affiche les composants de la gauche vers la droite en passant à la ligne s'il n'y a plus de place. La disposition est recalculée après chaque redimensionnement. Olivier Curé - UMLV [page 150 ] GridLayout Affiche les composants sur une grille, ligne par ligne et les cellules ont toutes la même taille. GridLayout (int li, int co, int hgap, int vgap); Respectivement le nombre de lignes, colonnes et distances horizontale et verticale (nulles par défaut). Si li=0, le nombre de lignes est ignoré. Si li > 0, co est ignoré. Olivier Curé - UMLV [page 151 ] GridLayout Affiche les composants sur une grille, ligne par ligne et les cellules ont toutes la même taille. GridLayout (int li, int co, int hgap, int vgap); Olivier Curé - UMLV [page 152 ] GridLayout Respectivement le nombre de lignes, colonnes et distances horizontale et verticale (nulles par défaut). Si li=0, le nombre de lignes est ignoré. Si li > 0, co est ignoré. Olivier Curé - UMLV [page 153 ] BorderLayout Affiche les composants dans 5 zones (nord, sud, est, ouest et centre) où 'nord' et 'sud' occupent toute la largeur; 'est' et 'ouest' occupent la hauteur restante. Olivier Curé - UMLV [page 154 ] BoxLayout Exemple, BoxLayout (horizontal) correspond à des cellules de même hauteur mais de largeur variable. On peut définir l'axe à l'aide des constantes X_AXIS(horiz.) et Y_AXIS (vert.). Olivier Curé - UMLV [page 155 ] Composant Box Le composant Box est un conteneur trasparent dont le gestionnaire est BoxLayout. On peut y ajouter un élément glue pour faire du remplissage. En fait, il absorbe les espaces vides. Olivier Curé - UMLV [page 156 ] Box: exemple Box box = new Box(BoxLayout.X_AXIS); box.add(Box.createHorizontalGlue()); box.add(new Jbutton(''texte''); box.add(Box.createHorizontalGlue()); ... Olivier Curé - UMLV [page 157 ] GridBagLayout Affiche les composants dans une grille selon un ensemble de contraintes (exprimé par la classe GridBagConstraints) : La zone réservée de la grille. La place occupée dans cette zone. Olivier Curé - UMLV [page 158 ] Layout (5) JPanel utilise par défaut un FlowLayout. JFrame utilise par défaut un BorderLayout. Olivier Curé - UMLV [page 159 ] Exemple 4 JFrame import javax.swing.*; import java.awt.*; import java.awt.event.*; public class FrameTd3Test { public static void main(String args[]) { JFrame frame3 = new FrameTd1(); Container contentPane3 = frame3.getContentPane(); contentPane3.setLayout (new java.awt.GridLayout (2, 2)); /* GridLayout avec 2 lignes et 2 colonnes */ JButton jb1 = new JButton("Bouton #1"); jb1.setBackground(Color.red); JButton jb2 = new JButton("Bouton #2"); jb2.setBackground(Color.green); JLabel jl1 = new JLabel("Un label en bas"); contentPane3.add(jb1); contentPane3.add(jb2); contentPane3.add(jl1); frame3.setLocation(300,300); frame3.show(); } } Olivier Curé - UMLV [page 160 ] Evénements L'utilisateur utilise le clavier et la souris pour interagir sur le déroulement du programme. Le programme doit lier des traitements aux actions de l'utilisateur. On distingue les événements de "bas niveau", actions élémentaires de l'utilisateur, et les événements de "haut niveau", qui correspondent à une action logique de l'utilisateur. Un exemple, la frappe d'un "A": en bas niveau ; 4 evts : appui sur shift, appui sur a, relachement de a et relachement de shift. en haut niveau ; 1 evt : frappe de "A". Olivier Curé - UMLV [page 161 ] La classe ActionEvent Cette classe décrit des événements de haut niveau très utilisés qui correspondent à un type d'action de l'utilisateur qui va déclencher un traitement. C'est le cas, pour : le clic d'un bouton, la frappe de la touche return dans une zone de texte, un choix dans un menu, un double clic dans une liste. Olivier Curé - UMLV [page 162 ] Comment utiliser les listeners Pour enregistrer un listener, il faut instancier une classe implémentant une certaine interface. On peut créer un tel objet de plusieurs manières. La méthode addActionListener sur un bouton enregistre les objets déclenchés par un clic. Respectivement, removeActionListener désenregistre les objets. ActionListener est une interface définissant la méthode actionPerformed(ActionEvent evt). Olivier Curé - UMLV [page 163 ] import javax.swing.*; import java.awt.*; import java.awt.event.*; class FrameTd4 extends JFrame implements ActionListener { JButton jb1; JLabel jl1; public FrameTd4() { setTitle("Ma JFrame avec des evenements"); setSize(200,200); Container contentPane = this.getContentPane(); contentPane.setLayout (new java.awt.GridLayout (2, 2)); jb1 = new JButton("Mon bouton avec evt"); jb1.addActionListener(this); jb1.setBackground(Color.yellow); jl1 = new JLabel("Pas de message"); contentPane.add(jb1); contentPane.add(jl1); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); }}); } public void actionPerformed(ActionEvent evt) { jl1.setText("Un clic sur bouton #1"); } } public class FrameTd4Test { public static void main(String args[]) { JFrame frame1 = new FrameTd4(); frame1.show(); } } Ex. 5 JFrame Olivier Curé - UMLV [page 164 ] Comment utiliser les listeners (2) On peut enregistrer un même listener pour plusieurs composants. La méthode getSource() permet alors d'obtenir le composant ayant créé l'événement. public void actionPerformed(ActionEvent) { Object o = event.getSource(); if(o==jb1) ... else if(o==jb1) ... Olivier Curé - UMLV [page 165 ] Ex. 6 import java.awt.Color; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class TestListener extends JFrame { private JPanel panel; public TestListener() {this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle("TestListener"); JPanel panel = new JPanel(); JButton boutonRouge = new JButton("Rouge"); boutonRouge.addActionListener(new MyActionListener(panel, Color.RED)); JButton boutonBleu = new JButton("Bleu"); boutonBleu.addActionListener(new MyActionListener(panel, Color.BLUE)); panel.add(boutonRouge); panel.add(boutonBleu); this.getContentPane().add(panel); } public static void main(String[] args) { TestListener test = new TestListener(); test.setVisible(true); } } Olivier Curé - UMLV [page 166 ] Ex. 6 fin import import import import java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JPanel; public class MyActionListener implements ActionListener { private JPanel panel; private Color color; public MyActionListener(JPanel panel, Color color) { this.panel = panel; this.color= color; } public void actionPerformed(ActionEvent evt) { panel.setBackground(color); } } Olivier Curé - UMLV [page 167 ] Classe anonyme Les classes anonymes sont déclarées immédiatement après l'expression d'instanciation d'une classe, permettant directement d'étendre ou d'implémenter respectivement la classe ou l'interface instanciée. La déclaration d'une classe anonyme doit être toujours suivie d'un point virgule immédiatement après son accolade fermante, sans quoi une erreur de compilation serait générée. Olivier Curé - UMLV [page 168 ] Classe anonyme (2) Les classes anonymes obéissent aux mêmes restrictions que les classes locales et de plus, ne peuvent ni être abstraites (abstract) ni être statiques (static). Par contre, elles portent toujours implicitement le modificateur final. En fait, aucun modificateur n'est permis dans une déclaration de classe anonyme. Olivier Curé - UMLV [page 169 ] Classe anonyme (3) Une classe anonyme ne peut déclarer explicitement un constructeur, le compilateur Java fournissant automatiquement un constructeur anonyme pour ce genre de classe. Une classe anonyme ne possède pas d'identificateur et est immédiatement utilisée lors de l'instanciation de la classe ou l'interface concernée. Les classes anonymes ont été créées pour écrire les listeners Olivier Curé - UMLV [page 170 ] Classe anonyme: exemple JButton bouton = new JButton(); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent evt) { System.out.println(evt); } }); bouton.addActionListener(al); Olivier Curé - UMLV [page 171 ] Classe anonyme (4) On peut accéder aux champs de la classe et aux variables locales. Olivier Curé - UMLV [page 172 ] Ex. 7 import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class TestListenerAnonyme extends JFrame { public TestListenerAnonyme() { this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle("TestListener"); setSize(200,200); JPanel panel = new JPanel(); panel.add(addButton(panel, Color.RED,"rouge")); panel.add(addButton(panel, Color.BLUE,"bleu")); this.getContentPane().add(panel); } public JButton addButton(final JPanel panel, final Color color, String texte) { JButton bouton = new JButton(texte); bouton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { panel.setBackground(color); }}); return bouton; } public static void main(String[] args) { TestListenerAnonyme test = new TestListenerAnonyme(); test.setVisible(true); } } Olivier Curé - UMLV [page 173 ] Plug-in VE Olivier Curé - UMLV [page 174 ] 8. Java et les bases de données Olivier Curé - UMLV [page 175 ] ODBC Open DataBase Connectivity. Une API standard pour l'accès aux bases de données. En utilisant des instructions ODBC dans un programme, on peut accéder à de nombreux SGBD. Permet au programme l'exploitation de SQL. ODBC gère une requête SQL et transforme celleci dans un format compréhensible par le SGBD. Olivier Curé - UMLV [page 176 ] JDBC Java DataBase Connectivity. Une API Java pour connecter des programmes java à des SGBD. Un ensemble de classes et interfaces java. JDBC va permettre D'établir une connexion à la BD. D'envoyer des requêtes SQL. De récupérer les résultats des requêtes. Olivier Curé - UMLV [page 177 ] JDBC (2) Il faut charger un driver pour le SGBD. Il est possible d'utiliser l'interface JDBC pour accéder aux BD accessibles via ODBC => "pont" JDBC-ODBC. Olivier Curé - UMLV [page 178 ] JDBC (3) Etapes : Importer le package (import java.sql.*;). Faire connaître le pilote JDBC du SGBD Ouvrir une connexion à la BD. Créer un objet 'Statement'. Exécuter une requête et obtenir un objet ResultSet. Fermer les objets ResultSet et Statement. Fermer la connexion à la BD. Olivier Curé - UMLV [page 179 ] Pilote JDBC Le pilote JDBC est un composant logiciel qui satisfait aux spécifications JDBC établies par Sun. Ce pilote est spécifique à un fabriquant de base de donnée. On trouvera par exemple un pilote pour les bases de données Oracle, un pilote pour la base MySQL. On traite dans ce cours du SGBDR MySQL. Ce pilote est une classe Java qui implémente linterface java.sql.Driver. Pour le driver MySQL, cette classe est : com.mysql.jdbc.Driver. Nous devons donc charger cette classe. Pour cela, la méthode Class.forName() est généralement utilisée (cf. Page suivante). Olivier Curé - UMLV [page 180 ] Chargement du pilote Il convient d'importer le package java.sql import java.sql.*; public class QueryExample { ... try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.err.println("Driver loading error : " + e); } ... } Olivier Curé - UMLV [page 181 ] URL de connection Afin de localiser la base de donnée sur le serveur de base de donnée, il est indispensable de spécifier une adresse de connexion sous la forme d'une URL. Ces URL commenceront toutes par "jdbc:". Généralement, il faudra se référer à la documentation du fournisseur du driver afin de connaître le format de l'URL à utiliser. Pour MySQL, l'URL est la suivante : jdbc:mysql://host:port/database. Host : correspond à l'adresse IP du serveur. port : port MySQL ou port par défaut. Database : le nom de la base de donnée à laquelle on doit se connecter. Olivier Curé - UMLV [page 182 ] Etablir une connexion Etablir une connexion en utilisant la classe java.sql.DriverManager. Son rôle est de créer des connexions en utilisant le driver préalablement chargé. Cette classe dispose d'une méthode statique getConnection() prenant en paramètre l'URL de connexion, le nom d'utilisateur et le mot de passe. String url = "jdbc:mysql://localhost/tp"; try { Connection connection = DriverManager.getConnection(url, "root", "secret"); } catch (SQLException e) { System.err.println("Error opening SQL connection: " + e.getMessage()); } Olivier Curé - UMLV [page 183 ] Les requêtes Afin d'exécuter des requêtes, il convient d'utiliser un object Statement. Une instance de cet objet est retourné par un appel à la méthode Connection.createStatement() : try { Statement statement = connection.createStatement(); } catch (SQLException e) { System.err.println("Error creating SQL statement: " + e.getMessage()); } Olivier Curé - UMLV [page 184 ] Les requêtes (2) Il existe deux types de requêtes : des requêtes de sélection (SELECT), accessibles par la méthode Statement.executeQuery(). Cette méthode retourne un résultat de type java.sql.ResultSet contenant les lignes sélectionnées. des requêtes de modification (UPDATE), d'insertion (INSERT) ou de suppression (DELETE), accessibles par la méthode Statement.executeUpdate(). Cette méthode retourne un résultat de type int correspondant au nombre de lignes affectées par la requête. Olivier Curé - UMLV [page 185 ] Les requêtes (3) String query = "SELECT name,email FROM users;"; try { ResultSet resultSet = statement.executeQuery(query); } catch (SQLException e) { System.err.println("Error executing query: " + e.getMessage()); } String query = "UPDATE users SET email='[email protected]' WHERE name='JOHN SMITH';"; try { int result = statement.executeUpdate(query); } catch (SQLException e) { System.err.println("Error executing query: " + e.getMessage()); } Olivier Curé - UMLV [page 186 ] Traitement des résultats L'objet ResultSet permet d'avoir un accès aux données résultantes de notre requête en mode ligne par ligne. La méthode ResultSet.next() permet de passer d'une ligne à la suivante. Cette méthode renvoie false dans le cas où il n'y a pas de ligne suivante. Il est nécessaire d'appeler au moins une fois cette méthode, le curseur est placé au départ avant la première ligne (si elle existe). Olivier Curé - UMLV [page 187 ] Traitement des résultats (2) La classe ResultSet dispose aussi d'un certain nombres d'accesseurs (ResultSet.getXXX()) qui permettent de récupérer le résultat contenu dans une colonne sélectionnée. On peut utiliser soit le numéro de la colonne désirée, soit son nom avec l'accesseur. La numérotation des colonnes commence à 1. XXX correspond au type de la colonne. Le tableau suivant précise les relations entre type SQL, type JDBC et méthode à appeler sur l'objet ResultSet. Olivier Curé - UMLV [page 188 ] Les types Type SQL Type JDBC Méthode d'accès char String getString() varchar String getString() integer Integer getInt() double, Double getDouble() float Float getDouble() Date Date getDate() Blob Blob getBlob() Olivier Curé - UMLV [page 189 ] Exemple try { while (rs.next()) { System.out.println(rs.getString("NAME") + " – " + rs.getString("EMAIL")); } } catch (SQLException e) { System.err.println("Error browsing query results: " + e.getMessage()); } Olivier Curé - UMLV [page 190 ] Fermeture de la connexion Objectif : Libérer les ressources try { resultSet.close(); connection.close(); } catch (SQLException e) { System.err.println("Error closing connection: " + e.getMessage()); } Olivier Curé - UMLV [page 191 ] Exemple 'SELECT' import java.sql.*; public class Query1 { public Query1() { String url = "jdbc:mysql://localhost:3306/film"; // film est le nom de la base de donne'es Connection con; String query = "SELECT director,nat from director;"; Statement stmt; try { Driver mySQLDriver = new org.gjt.mm.mysql.Driver(); con = DriverManager.getConnection(url,"o" ,"ol" ); System.out.println("Con = " + con); stmt = con.createStatement(); Olivier Curé - UMLV [page 192 ] Exemple 'SELECT' (2) ResultSet rs = stmt.executeQuery(query); while (rs.next()) { System.out.println(rs.getString(1)+" ("+rs.getString(2)+")"); } stmt.close(); con.close(); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()); } } public static void main(String args[]) { Query1 query1 = new Query1(); } } Olivier Curé - UMLV [page 193 ] Instruction SQL paramétrée La plupart des SGBD (dont Oracle) ne peuvent analyser qu'une seule fois une requête exécutée un grand nombre de fois JDBC permet de profiter de ce type de fonctionnalité par l'utilisation de requêtes paramétrées ou de procédures stockées. Les requêtes paramétrées sont associées aux instances de l'interface PreparedStatement qui hérite de l'interface Statement Olivier Curé - UMLV [page 194 ] Création d'une requête paramétrée PreparedStatement pstmt = conn.preparedStatement("UPDATE emp SET sal=? WHERE nom=?;"); Les '?' indiquent les emplacements des paramètres. Les valeurs des paramètres sont données par les méthodes setXXX(n,valeur). On choisit la méthode setXXX suivant le type SQL de la valeur que l'on veut mettre dans la requête. C'est au développeur de passer une valeur Java cohérente avec le type. Olivier Curé - UMLV [page 195 ] Requête paramétrée Exemple PreparedStatement pstmt = conn.preparedStatement("UPDATE emp SET sal=? WHERE nom=?;"); for(int i=1; i<=10,i++) { pstmt.setDouble(1, salaire[i]); pstmt.setString(2,nom[i]); pstmt.executeUpdate(); } On peut passer la valeur NULL avec setNull (n,type) (type de la classe Types). Olivier Curé - UMLV [page 196 ] Avantages des requêtes paramétrées Traitement plus rapide si elles sont utilisées plusieurs fois avec plusieurs paramètres. Amélioration de la portabilité (indépendance des setXXX avec les SGBD). Olivier Curé - UMLV [page 197 ]