Cours programmationorientée objet en Java Chapitre I Introduction A) Généralités 3 Pourquoi JAVA ? • Problème du logiciel: • Taille • Coût : développement et maintenance • Fiabilité • Solutions : • Modularité • Réutiliser le logiciel • Certification • Comment? Historique de Java (1) • Java a été développé à partir de décembre 1990 par une équipe de Sun Microsystems dirigée par James Gosling • Au départ, il s’agissait de développer un langage de programmation pour permettre le dialogue entre de futurs ustensiles domestiques • Or, les langages existants tels que C++ ne sont pas à la hauteur : recompilation dès qu'une nouvelle puce arrive, complexité de programmation pour l'écriture de logiciels fiables... 4 Historique de Java (2) • 1990 : Ecriture d'un nouveau langage plus adapté à la réalisation de logiciels embarqués, appelé OAK • Petit, fiable et indépendant de l'architecture • Destiné à la télévision interactive • Non rentable sous sa forme initiale • 1993 : le WEB « décolle », Sun redirige ce langage vers Internet : les qualités de portabilité et de compacité du langage OAK en ont fait un candidat parfait à une utilisation sur le réseau. Cette réadaptation prit près de 2 ans. • 1995 : Sun rebaptisa OAK en Java (nom de la machine à café autour de laquelle se réunissait James Gosling et ses collaborateurs) 5 Historique de Java (3) • Les développeurs Java ont réalisé un langage indépendant de toute architecture de telle sorte que Java devienne idéal pour programmer des applications utilisables dans des réseaux hétérogènes, notamment Internet. • Le développement de Java devint alors un enjeu stratégique pour Sun et l'équipe écrivit un navigateur appelé HotJava capable d’exécuter des programmes Java. • La version 2.0 du navigateur de Netscape a été développée pour supporter Java, suivi de près par Microsoft (Internet Explorer 3) • L'intérêt pour la technologie Java s’est accru rapidement: IBM, Oracle et d'autres ont pris des 6 licences Java. Les différentes versions de Java • De nombreuses versions de Java depuis 1995 • • • • • • • • • • Java Java Java Java Java Java Java Java Java Java 1.0 en 1995 1.1 en 1996 1.2 en 1999 (Java 2, version 1.2) 1.3 en 2001 (Java 2, version 1.3) 1.4 en 2002 (Java 2, version 1.4) 5 en 2004 6 en 2006 7 en 2011 8 en 2014 celle que nous utiliserons dans nos TP 9 pour 2017 ? • Évolution très rapide et succès du langage • Une certaine maturité atteinte avec Java 2 • Mais des problèmes de compatibilité existaient • entre les versions 1.1 et 1.2/1.3/1.4 • avec certains navigateurs 7 Histoire récente • En mai 2007, Sun publie l’ensemble des outils Java dans un « package » OpenJDK sous licence libre. • La société Oracle a acquis en 2009 l'entreprise Sun Microsystems. On peut désormais voir apparaître le logo Oracle dans les documentations de l'api Java. • Le 12 avril 2010, James Gosling, le créateur du langage de programmation Java démissionne d’Oracle pour des motifs qu’il ne souhaite pas divulguer. Il était devenu le directeur technologique de la division logicielle client pour Oracle. • Août 2012: faille de sécurité importante dans Java 7 • Mars 2014 : Java 8 met en avant plan JavaFX 8 B) Principes de base de la POO • Objet et classe: • Classe = définitions pour des données (variables) + fonctions (méthodes) agissant sur ces données • Objet = élément d’une classe (instance) avec un état • (une méthode ou une variable peut être • de classe = commune à la classe ou • d’instance = dépendant de l’instance ) 9 Principes de bases (suite) • Encapsulation et séparation de la spécification et de l’implémentation • Séparer l’implémentation de la spécification. • Ne doit être visible de l’extérieur que ce qui est nécessaire, les détails d’implémentation sont « cachés » • Héritage: • Une classe peut hériter des propriétés d’une autre classe: un classe peut être une extension d’une autre classe. 10 Principes de bases de la POO • Mais surtout notion de polymorphisme: • Si une classe A est une extension d’une classe B: • A doit pouvoir redéfinir certaines méthodes (disons f()) • Un objet a de classe A doit pouvoir être considéré comme un objet de classe B • On doit donc accepter : • B b; • b=a; (a a toutes les propriétés d’un B) • b.f() • Doit appeler la méthode redéfinie dans A! • C’est le transtypage • (exemple: méthode paint des interfaces graphiques) 11 Principes de bases • Polymorphisme: • Ici l’association entre le nom ‘f()’ et le code (code de A ou code de B) a lieu dynamiquement (=à l’exécution) Liaison dynamique • On peut aussi vouloir « paramétrer » une classe (ou une méthode) par une autre classe. Exemple: Pile d’entiers Dans ce cas aussi un nom peut correspondre à plusieurs codes, mais ici l’association peut avoir lieu de façon statique (au moment de la compilation) 12 C) Comment assurer la réutilisation du logiciel? • Type abstrait de données • définir le type par ses propriétés (spécification) • Interface, spécification et implémentation • Une interface et une spécification (=les propriétés à assurer) pour définir un type • Une (ou plusieurs) implémentation du type abstrait de données • Ces implémentations doivent vérifier la spécification 13 Comment assurer la réutilisation du logiciel? • Pour l’utilisateur du type abstrait de données • Accès uniquement à l’interface (pas d’accès à l’implémentation) • Utilisation des propriétés du type abstrait telles que définies dans la spécification. • (L’utilisateur est lui-même un type abstrait avec une interface et une spécification) 14 Comment assurer la réutilisation du logiciel? • Mais en utilisant un type abstrait l’utilisateur n'en connaît pas l’implémentation • il sait uniquement que la spécification du type abstrait est supposée être vérifiée par l'implémentation. • Pour la réalisation concrète, une implémentation particulière est choisie • Il y a naturellement polymorphisme 15 java: quelques rappels… • Un source avec le suffixe .java • Une classe par fichier source (en principe) même nom pour la classe et le fichier source (sans le suffixe .java) • Méthode public static void main(String argv[]); • main est le point d’entrée • Compilation génère un .class • Exécution en lançant la machine java 16 Généralités… • Un peu plus qu’un langage de programmation: • “gratuit”! • Indépendant de la plateforme • Langage interprété et byte code • Portable • Syntaxe à la C • Orienté objet (classes héritage) • Nombreuses bibliothèques • Pas de pointeurs! (ou que des pointeurs!) • Ramasse-miettes • Multi-thread • Distribué (WEB) applet, servlet, portlet, etc… 17 Plateforme Java 18 • La compilation génère un .class en bytecode (langage intermédiaire indépendant de la plateforme). • Le bytecode est interprété par un interpréteur Java JVM Compilation javac interprétation java Langage intermédiaire et Interpréteur… • Avantage: indépendance de la plateforme • Échange de byte-code (applet) • Inconvénient: efficacité 19 Plateforme Java • La plateforme java: software au-dessus d’une plateforme exécutable sur un hardware (exemple MacOs, linux …) • Java VM • Java application Programming Interface (Java API): 20 Tout un environnement… • Java 8 sdk: JRE (java runtime environment + outils de développements compilateur, debogueurs etc…) 21 Trois exemples de base • Une application • Une applet • Une application avec interface graphique 22 Application: • Fichier Appli.java: /** * Une application basique... */ class Appli { public static void main(String[] args) { System.out.println("Bienvenue en L3..."); //affichage } } 23 Compiler, exécuter… • Créer un fichier Appli.java • Compilation: • javac Appli.java • Création de Appli.class (bytecode) • Interpréter le byte code: • java Appli • Attention aux suffixes!!! • (il faut que javac et java soient dans $PATH) Exception in thread "main" java.lang.NoClassDefFoundError: • Il ne trouve pas le main -> vérifier le nom! • Variable CLASSPATH ou option -classpath 24 Remarques • Commentaires /* … */ et // • Définition de classe • une classe contient des méthodes (=fonctions) et des variables • Pas de fonctions ou de variables globales (uniquement dans des classes ou des instances) • Méthode main: • public static void main(String[] arg) • • • • public static Void String • Point d’entrée 25 Remarques • Classe System • out est une variable de la classe System • println méthode de System.out • out est une variable de classe qui fait référence à une instance de la classe PrintStream qui implémente un flot de sortie. • Cette instance a une méthode println 26 Remarques… • Classe: définit des méthodes et des variables (déclaration) • Instance d’une classe (objet) • Méthode de classe: fonction associée à (toute la) classe. • Méthode d’instance: fonction associée à une instance particulière. • Variable de classe: associée à une classe (globale et partagée par toutes les instances) • Variable d’instance: associée à un objet (instancié) • Patience… 27 Applet: • Applet et WEB • Client (navigateur) et serveur WEB • Le client fait des requêtes html, le serveur répond par des pages html • Applet: • Le serveur répond par une page contenant des applets • Applet: byte code • Code exécuté par le client • Permet de faire des animations avec interfaces graphiques sur le client. • Une des causes du succès de java. 28 Exemple applet • Fichier MonApplet.java: /** * Une applet basique... */ import java.applet.Applet; import java.awt.Graphics; public class MonApplet extends Applet { public void paint(Graphics g){ g.drawString("Bienvenue en en L3...", 50,25); } } 29 Remarques: • import et package: • Un package est un regroupement de classes. • Toute classe est dans un package • Package par défaut (sans nom) • classpath • import java.applet.*; • Importe le package java.applet • Applet est une classe de ce package, • Sans importation il faudrait java.applet.Applet 30 Remarques: • La classe Applet contient ce qu’il faut pour écrire une applet • … extends Applet: • La classe définie est une extension de la classe Applet: • Elle contient tout ce que contient la classe Applet • (et peut redéfinir certaines méthodes (paint)) • Patience!! 31 Remarques… 32 • Une Applet contient les méthodes paint start et init. En redéfinissant paint, l’applet une fois lancée exécutera ce code redéfini. • Graphics g argument de paint est un objet qui représente le contexte graphique de l’applet. • drawString est une méthode (d’instance) qui affiche une chaîne, • 50, 25: affichage à partir de la position (x,y) à partir du point (0,0) coin en haut à gauche de l’applet. Pour exécuter l’applet • L’applet doit être exécutée dans un navigateur capable d’interpréter du bytecode correspondant à des applet. • Il faut créer un fichier HTML pour le navigateur. 33 Html pour l’applet 34 • Fichier Bienvenu.html: <HTML> <HEAD> <TITLE> Une petite applet </TITLE> <BODY> <APPLET CODE='MonApplet.class' WIDTH=200 Height=50> </APPLET> </BODY> </HTML> Html 35 • Structure avec balises: • Exemples: • <HTML> </HTML> • url: • <a target="_blank" href="http://wwww.tondeurh.fr">page de TH</a> • Ici: <APPLET CODE='MonApplet.class' WIDTH=200 Height=50> </APPLET> Exemple interface graphique Fichier MonSwing.java: /** * Une application basique... avec interface graphique */ import javax.swing.*; public class MonSwing { private static void creerFrame() { //Une formule magique... JFrame.setDefaultLookAndFeelDecorated(true); //Creation d'une Frame JFrame frame = new JFrame("MonSwing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Afficher un message JLabel label = new JLabel("Bienvenue en L3..."); frame.getContentPane().add(label); //Afficher la fenêtre frame.pack(); frame.setVisible(true); } public static void main(String[] args) { creerFrame(); } } 36 Remarques • Importation de packages • Définition d’un conteneur top-level JFrame, implémenté comme instance de la classe JFrame • Affichage de ce conteneur • Définition d’un composant JLabel, implémenté comme instance de JLabel • Ajout du composant JLabel dans la JFrame • Définition du comportement de la Jframe sur un click du bouton de fermeture • Une méthode main qui crée la JFrame 37 Chapitre II Syntaxe du langage Java Les commentaires • /* commentaire sur une ou plusieurs lignes */ • Identiques à ceux existant dans le langage C • // commentaire de fin de ligne • Identiques à ceux existant en C++ • /** commentaire d'explication */ • Les commentaires d'explication se placent généralement juste avant une déclaration (d'attribut ou de méthode) • Ils sont récupérés par l'utilitaire javadoc et inclus dans la documentation ainsi générée. 39 Instructions, blocs et blancs • Les instructions Java se terminent par un ; • Les blocs sont délimités par : { pour le début de bloc } pour la fin du bloc Un bloc permet de définir un regroupement d’instructions. La définition d’une classe ou d’une méthode se fait dans un bloc. • Les espaces, tabulations, sauts de ligne sont autorisés. Cela permet de présenter un code 40 plus lisible. Point d’entrée d’un programme Java • Pour pouvoir faire un programme exécutable il faut toujours une classe qui contienne une méthode particulière, la méthode « main » • c’est le point d’entrée dans le programme : le microprocesseur sait qu’il va commencer à exécuter les instructions à partir de cet endroit public static void main(String arg[ ]) { …/… } 41 Exemple (1) Fichier Bonjour.java public class Bonjour { //Accolade débutant la classe Bonjour La classe est l’unité de base de nos programmes. Le mot clé en Java pour définir une classe est class public static void main(String args[]) { //Accolade débutant la méthode main /* Pour l’instant juste une instruction */ System.out.println(“bonjour”); } //Accolade fermant la méthode main } //Accolade fermant la classe Bonjour 42 Exemple (2) Fichier Bonjour.java public class Bonjour Accolades délimitant le début et la fin de la définition de la class Bonjour { public static void main(String args[]) { System.out.println(“bonjour”); Accolades délimitant le début et la fin de la méthode main } } Les instructions se terminent par des ; 43 Exemple (3) Fichier Bonjour.java public class Bonjour { Une méthode peut recevoir des paramètres. Ici la méthode main reçoit le paramètre args qui est un tableau de chaîne de caractères. public static void main(String args[]) { System.out.println(“bonjour”); } } 44 Compilation et exécution (1) Le nom du fichier est nécessairement celui de la classe avec l’extension .java en plus. Java est sensible à la casse des lettres. Fichier Bonjour.java Compilation en bytecode java dans une console DOS: javac Bonjour.java Génère un fichier Bonjour.class Exécution du programme (toujours depuis la console DOS) sur la JVM : java Bonjour Affichage de « bonjour » dans la console public class Bonjour { public static void main(String[] args) { System.out.println(“bonjour”); } } 45 Compilation et exécution (3) • Pour résumer, dans une console DOS, si j’ai un fichier Bonjour.java pour la classe Bonjour : • javac Bonjour.java • Compilation en bytecode java • Indication des erreurs de syntaxe éventuelles • Génération d’un fichier Bonjour.class si pas d’erreurs • java Bonjour • Java est la machine virtuelle • Exécution du bytecode • Nécessité de la méthode main, qui est le point d’entrée dans le programme 46 Identificateurs (1) • On a besoin de nommer les classes, les variables, les constantes, etc. ; on parle d’identificateur. • Les identificateurs commencent par une lettre, _ ou $ Attention : Java distingue les majuscules des minuscules • Conventions sur les identificateurs : • Si plusieurs mots sont accolés, mettre une majuscule à chacun des mots sauf le premier. • exemple : uneVariableEntiere • La première lettre est majuscule pour les classes et 47 les interfaces • exemples : MaClasse, UneJolieFenetre Identificateurs (2) • Conventions sur les identificateurs : • La première lettre est minuscule pour les méthodes, les attributs et les variables • exemples : setLongueur, i, uneFenetre • Les constantes sont entièrement en majuscules • exemple : LONGUEUR_MAX 48 Les mots réservés de Java abstract default goto null synchronized boolean do if package this break double implements private throw byte else import protected throws case extends instanceof public transient catch false int return true char final interface short try class finally long static void continue float native super volatile const for new switch while 49 Les types de bases (1) • En Java, tout est objet sauf les types de base. • Il y a huit types de base : • un type booléen pour représenter les variables ne pouvant prendre que 2 valeurs (vrai et faux, 0 ou 1, etc.) : boolean avec les valeurs associées true et false • un type pour représenter les caractères : char • quatre types pour représenter les entiers de divers taille : byte, short, int et long • deux types pour représenter les réelles : float et double • La taille nécessaire au stockage de ces types est indépendante de la machine. • Avantage : portabilité • Inconvénient : "conversions" coûteuses 50 Les types de bases (2) : les entiers • Les entiers (avec signe) • byte : codé sur 8 bits, peuvent représenter des entiers allant de -27 à 27 –1 (-128 à +127) • short : codé sur 16 bits, peuvent représenter des entiers allant de -215 à 215 –1 • int : codé sur 32 bits, peuvent représenter des entiers allant de -231 à 231 –1 • long : codé sur 64 bits, peuvent représenter 51 des entiers allant de -263 à 263 –1 Les types de bases (3) : les entiers • Notation • • • • 2 entier normal en base décimal 2L entier au format long en base décimal 010 entier en valeur octale (base 8) 0xF entier en valeur hexadécimale (base 16) • Opérations sur les entiers • opérateurs arithmétiques +, -, * • / :division entière si les 2 arguments sont des entiers • % : reste de la division entière • exemples : • 15 / 4 donne 3 • 15 % 2 donne 1 52 Les types de bases (4) : les entiers • Opérations sur les entiers (suite) • les opérateurs d’incrémentation ++ et de décrémentation et -• ajoute ou retranche 1 à une variable int n = 12; n ++; //Maintenant n vaut 13 • n++; « équivalent à » n = n+1; n--; « équivalent à » n = n-1; • 8++; est une instruction illégale • peut s’utiliser de manière suffixée : ++n. La différence avec la version préfixée se voit quand on les utilisent dans les expressions. En version suffixée la (dé/inc)rémentation s’effectue en premier int m=7; int n=7; int a=2 * ++m; //a vaut5316, m vaut 8 int b=2 * n++; //b vaut 14, n vaut 8 Les types de bases (5) : les réels • Les réels • float : codé sur 32 bits, peuvent représenter des nombres allant de -1035 à + 1035 • double : codé sur 64 bits, peuvent représenter des nombres allant de -10400 à +10400 • Notation • 4.55 ou 4.55D réel double précision 54 • 4.55f réel simple précision Les types de bases (6) : les réels • Les opérateurs • opérateurs classiques +, -, *, / • attention pour la division : • 15 / 4 donne 3 division entière • 15 % 2 donne 1 • 11.0 / 4 donne 2.75 (si l’un des termes de la division est un réel, la division retournera un réel). • puissance : utilisation de la méthode pow de la classe Math. 55 à • double y = Math.pow(x, a) équivalent x^a, x et a étant de type double Les types de bases (7) : les booléens • Les booléens • boolean contient soit vrai (true) soit faux (false) • Les opérateurs logiques de comparaisons • Egalité : opérateur == • Différence : opérateur != • supérieur et inférieur strictement à : opérateurs > et < • supérieur et inférieur ou égal : 56 opérateurs >= et <= Les types de bases (8) : les booléens • Notation boolean x; x= true; x= false; x= (5==5); // l ’expression (5==5) est évaluée et la valeur est affectée à x qui vaut alors vrai x= (5!=4); // x vaut vrai, ici on obtient vrai si 5 est différent de 4 x= (5>5); // x vaut faux, 5 n'est pas supérieur strictement à 5 x= (5<=5); // x vaut vrai, 5 est bien inférieur ou égal à 5 57 Les types de bases (9) : les booléens • Les autres opérateurs logiques • • • • et logique : && ou logique : || non logique : ! Exemples : si a et b sont 2 variables booléennes boolean a,b, c; a= true; b= false; c= (a && b); // c vaut false c= (a || b); // c vaut true 58 c= !(a && b); // c vaut true c=!a; // c vaut false Les types de bases (10) : les caractères • Les caractères • char : contient une seule lettre • le type char désigne des caractères en représentation Unicode • Codage sur 2 octets contrairement à ASCII/ANSI codé sur 1 octet. Le codage ASCII/ANSI est un sous-ensemble d’Unicode • Notation hexadécimale des caractères Unicode de ‘ \u0000 ’ à ‘ \uFFFF ’. • Plus d’information sur Unicode à : www.unicode.org 59 Les types de bases (11) : les caractères • Notation char a,b,c; // a,b et c sont des variables du type char a='a'; // a contient la lettre 'a' b= '\u0022' //b contient le caractère guillemet : " c=97; // x contient le caractère de rang 97 : 'a' 60 Les types de bases (12) exemple et remarque int x = 0, y = 0; float z = 3.1415F; double w = 3.1415; long t = 99L; boolean test = true; char c = 'a'; • Remarque importante : • Java exige que toutes les variables soient définies et initialisées. Le compilateur sait déterminer si une variable est susceptible d'être utilisée avant initialisation et produit une erreur de compilation. 61 Les structures de contrôles (1) • Les structures de contrôle classiques existent en Java : • if, else • switch, case, default, break • for • while • do, while 62 Les structures de contrôles (2) : if / else • Instructions conditionnelles • Effectuer une ou plusieurs instructions seulement si une certaine condition est vraie if (condition) instruction; et plus généralement : if (condition) { bloc d’instructions} condition doit être un booléen ou renvoyer une valeur booléenne • Effectuer une ou plusieurs instructions si une certaine condition est vérifiée sinon effectuer d’autres instructions if (condition) instruction1; else instruction2; 63 et plus généralement if (condition) { 1er bloc d’instructions} else {2ème bloc d’instruction} Les structures de contrôles (3) : if / else Max.java import java.io.*; public class Max { public static void main(String args[]) { Console console = System.console(); int nb1 = Integer.parseInt(console.readLine("Entrer un entier:")); int nb2 = Integer.parseInt(console.readLine("Entrer un autre entier:")); if (nb1 > nb2) System.out.println("l'entier le plus grand est "+ nb1); else System.out.println("l'entier le plus grand est "+ nb2); } 64 } Les structures de contrôles (4) : while • Boucles indéterminées • On veut répéter une ou plusieurs instructions un nombre indéterminés de fois : on répète l’instruction ou le bloc d’instruction tant que une certaine condition reste vraie • nous avons en Java une première boucle while (tant que) • while (condition) {bloc d’instructions} • les instructions dans le bloc sont répétées tant que la condition reste vraie. • On ne rentre jamais dans la boucle si la 65 condition est fausse dès le départ Les structures de contrôles (5) : while • Boucles indéterminées • un autre type de boucle avec le while: • do {bloc d’instructions} while (condition) • les instructions dans le bloc sont répétées tant que la condition reste vraie. • On rentre toujours au moins une fois dans la boucle : la condition est testée en fin de boucle. 66 Les structures de contrôles (6) : while Facto1.java import java.io.*; public class Facto1 { public static void main(String args[]) { int n, result,i; n = Integer.parseInt(System.console().readLine("Entrer une valeur pour n:")); result = 1; i = n; while (i > 1) { result = result * i; i--; } 67 System.out.println("la factorielle de "+n+" vaut "+result); } } Les structures de contrôles (7) : for • Boucles déterminées • On veut répéter une ou plusieurs instructions un nombre déterminés de fois : on répète l’instruction ou le bloc d’instructions pour un certain nombre de pas. • La boucle for for (int i = 1; i <= 10; i++) System.out.println(i); //affichage des nombres de 1 à 10 • une boucle for est en fait équivalente à une boucle while for (instruction1; expression1; expression2) {bloc} … est équivalent à … instruction 1; while (expression1) {bloc; expression2}} 68 Les structures de contrôles (8) : for Facto2.java import java.io.*; public class Facto2 { public static void main(String args[]) { int n, result,i; n = Integer.parseInt(System.console().readLine("Entrer une valeur pour n:")); result = 1; for(i =n; i > 1; i--) { result = result * i; } System.out.println("la factorielle de "+n+" vaut "+result); 69 } } Les structures de contrôles (9) : switch • Sélection multiples • l’utilisation de if / else peut s’avérer lourde quand on doit traiter plusieurs sélections et de multiples alternatives • pour cela existe en Java le switch / case assez identique à celui de C/C++ • La valeur sur laquelle on teste doit être un char ou un entier (à l’exclusion d’un long). • L’exécution des instructions correspondant à une alternative commence au niveau du case correspondant et se termine à la rencontre d’une instruction break ou arrivée à la fin du switch 70 Les structures de contrôles (10) : switch Alternative.java import java.io.*; Variable contenant la valeur que l’on veut tester. public class Alternative Première alternative : { on affiche Un et on sort public static void main(String args[]) du bloc du switch au break; { int nb = Integer.parseInt(System.console().readLine("Entrer une valeur pour n:")); switch(nb) { Deuxième alternative : case 1: on affiche Deux et on sort System.out.println("Un"); break; du bloc du switch au break; case 2: System.out.println("Deux"); break; default: Alternative par défaut: System.out.println("Autre nombre"); break; on réalise une action } 71 par défaut. } } Les tableaux (1) • Les tableaux permettent de stocker plusieurs valeurs de même type dans une variable. • Les valeurs contenues dans la variable sont repérées par un indice • En langage java, les tableaux sont des objets • Déclaration • int tab [ ]; String chaines[ ]; • Création d'un tableau • tab = new int [20]; // tableau de 20 int • chaines = new String [100]; // tableau de 100 chaine 72 Les tableaux (2) • Le nombre d'éléments du tableau est mémorisé. Java peut ainsi détecter à l'exécution le dépassement d'indice et générer une exception. Mot clé length • Il est récupérable par nomTableau.length int taille = tab.length; //taille vaut 20 • Comme en C/C++, les indices d’un tableau commencent à ‘ 0 ’. Donc un tableau de taille 100 aura ses indices qui iront de 0 à 99. 73 Les tableaux (3) • Initialisation tab[0]=1; tab[1]=2; //etc. noms[0] = new String( "Boule"); noms[1] = new String( "Bill");//etc • Création et initialisation simultanées String noms [ ] = {"Boule","Bill"}; Point pts[ ] = { new Point (0, 0), new Point (10, -1)}; 74 Les tableaux (4) Tab1.java public class Tab1 { public static void main (String args[]) { int tab[ ] ; tab = new int[4]; tab[0]=5; tab[1]=3; tab[2]=7; tab[3]=tab[0]+tab[1]; } } Les indices vont toujours de 0 à (taille-1) Pour déclarer une variable tableau on indique le type des éléments du tableau et le nom de la variable tableau suivi de [ ] on utilise new <type> [taille]; pour initialiser le tableau On peut ensuite affecter des valeurs au différentes cases du tableau : <nom_tableau>[indice]75 Les tableaux (5) Tab1.java public class Tab1 { public static void main (String args[]) { int tab[ ] ; tab = new int[4]; tab[0]=5; tab[1]=3; tab[2]=7; tab[3]=tab[0]+tab[1]; } } Mémoire 0x0000 0x258 0 0 0 0 76 Les tableaux (6) Tab1.java public class Tab1 { public static void main (String args[]) { int tab[ ] ; tab = new int[4]; tab[0]=5; tab[1]=3; tab[2]=7; tab[3]=tab[0]+tab[1]; } } Mémoire 0x258 5 0 0 3 0 7 0 8 77 Les tableaux (7) Tab2.java public class Tab2 { public static void main (String args[]) { String tab[ ] ; tab = new String[4]; tab[0]=new String("Pierre"); tab[1]=new String("Paul"); tab[2]=new String("Jacques"); tab[3]=new String("Philippe"); } } Mémoire 0x0258 0x0106 0x0116 0x0126 0x0136 "Pierre" "Paul" "Jacques" "Philippe" 78 La classe String (1) • Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s contient la chaîne "aaa" mais String s=new String("aaa"); // identique à la ligne précédente • La concaténation • l’opérateur + entre 2 String les concatène : String str1 = "Bonjour ! "; String str2 = null; str2 = "Comment vas-tu ?"; String str3 = str1 + str2; / * Concaténation de chaînes : str3 contient " Bonjour ! Comment vas-tu ?" 79 Différences entre objets et types de base Mémoire int x=3,y=3; x == y est vrai 3 3 0x768 0x852 String s1="abc",s2="abc"; s1 == s2 est faux... Abc .... Quand on compare 2 variables d’un type de base on compare leur valeur. Quand on compare 2 objet avec les opérateurs on compare leur référence (leur adresse en mémoire). Introduction de la méthode equals() pour les objets : s1.equals(s2) est vrai Abc .... 80 La classe String (2) • Longueur d’un objet String : • méthode int length() : renvoie la longueur de la chaîne String str1 = "bonjour"; int n = str1.length(); // n vaut 7 • Sous-chaînes • méthode String substring(int debut, int fin) • extraction de la sous-chaine depuis la position debut jusqu’à la position fin non-comprise. String str2 = str1.substring(0,3); // str2 contient la valeur "bon" • le premier caractère d’une chaîne occupe la position 0 • le deuxième paramètre de substring indique la position du premier caractère que l ’on ne souhaite pas copier 81 La classe String (3) • Récupération d’un caractère dans une chaîne • méthode char charAt(int pos) : renvoie le caractère situé à la position pos dans la chaîne de caractère à laquelle on envoie se message String str1 = "bonjour"; char unJ = str1.charAt(3); // unJ contient le caractère 'j' • Modification des objets String • Les String sont inaltérables en Java : on ne peut modifier individuellement les caractères d’une chaîne. • Par contre il est possible de modifier le contenu de la variable contenant la chaîne (la variable ne référence plus la même chaîne). str1 = str1.substring(0,3) + " soir"; /* str1 contient maintenant la chaîne "bonsoir" */ 82 La classe String (4) • Les chaînes de caractères sont des objets : • pour tester si 2 chaînes sont égales il faut utiliser la méthode boolean equals(String str) et non == • pour tester si 2 chaînes sont égales à la casse près il faut utiliser la méthode boolean equalsIgnoreCase(String str) String str1 = "BonJour"; String str2 = "bonjour"; String str3 = "bonjour"; boolean a, b, c, d; a = str1.equals("BonJour"); //a contient la valeur true b = (str2 = = str3); //b contient la valeur false c = str1.equalsIgnoreCase(str2);//c contient la valeur true d = "bonjour".equals(str2); //d contient la valeur true 83 La classe String (5) • Quelques autres méthodes utiles • boolean startsWith(String str) : pour tester si une chaine de caractère commence par la chaine de caractère str • boolean endsWith(String str) : pour tester si une chaîne de caractère se termine par la chaine de caractère str String str1 = "bonjour "; boolean a = str1.startsWith("bon");//a vaut true boolean b = str1.endsWith("jour");//b vaut true 84 La classe String (7) Plus d’informations dans les documentations de l’API dans le package java.lang 85 Chapitre III Classes et objets Concept d’objet • Qu’est-ce qu’un objet ? • Le monde qui nous entoure est composé d'objets • Ces objets ont tous deux caractéristiques • un état • un comportement • Exemples d’objets du monde réel • chien • état : nom, couleur, race, poids.... • comportement : manger,aboyer,renifler... • Bicyclette • état : nombre de vitesses, vitesse courante, couleur • comportement : tourner, accélérer, changer de vitesse 87 L’approche objet • L’approche objet : • Programmation dirigé par les données et non par les traitements • les procédures existent toujours mais on se concentre d’abord sur les entités que l’on va manipuler avant de se concentrer sur la façon dont on va les manipuler • Notion d’encapsulation • les données et les procédures qui les manipulent (on parle de méthodes) sont regroupés dans une même entité (la classe). • Un objet informatique • maintient son état dans des variables (appelées champs) • implémente son comportement à l'aide de méthodes objet informatique = regroupement logiciel de variables et de méthodes • Cycle de vie • construction (en mémoire) • Utilisation (changements d’état par affectations, comportements par 88 exécution de méthodes) • destruction Concept de classe • En informatique, la classe est un modèle décrivant les caractéristiques communes et le comportement d’un ensemble d’objets : la classe est un moule et l’objet est ce qui est moulé à partir de cette classe • Mais l'état de chaque objet est indépendant des autres • Les objets sont des représentations dynamiques (appelées instances) du modèle défini au travers de la classe. • Une classe permet d’instancier plusieurs objets. • Chaque objet est instance d’une seule classe. 89 La classe (1) : définition • Classe : description d’une famille d’objets ayant une même structure et un même comportement. Elle est caractérisée par : • Un nom • Une composante statique : des champs (ou attributs) nommés ayant une valeur. Ils caractérisent l’état des objets pendant l’exécution du programme • Une composante dynamique : des méthodes représentant le comportement des objets de cette classe. Elles manipulent les champs des objets et caractérisent les actions pouvant être effectuées par les objets. 90 La classe (2) : représentation graphique Nom Champs Méthodes Une classe représentée avec la notation UML (Unified Modeling Language) 91 Syntaxe de définition d’une classe Exemple : Une classe définissant un point Class Point Nom de la Classe { double x; // abscisse du point Attributs double y; // ordonnée du point // translate de point de (dx,dy) void translate (double dx, double dy) { x = x+dx; y = y+dy; Méthodes } // calcule la distance du point à l’origine double distance() { return Math.sqrt(x*x+y*y); } } 92 L’instanciation (1) • Instanciation : concrétisation d’une classe en un objet « concret ». • Dans nos programmes Java nous allons définir des classes et instancier ces classes en des objets qui vont interagir. Le fonctionnement du programme résultera de l’interaction entre ces objets « instanciés ». • En Programmation Orientée Objet, on décrit des classes et l’application en elle-même va être constituée des objets instanciés, à partir de ces classes, qui vont communiquer et agir les uns sur les autres. 93 L’instanciation (2) • Instance • représentant physique d'une classe • obtenu par moulage du dictionnaire des variables et détenant les valeurs de ces variables. • Son comportement est défini par les méthodes de sa classe • Par abus de langage « instance » = « objet » • Exemple : • si nous avons une classe voiture, alors votre voiture est une instance particulière de la classe voiture. • Classe = concept, description • Objet = représentant concret d’une classe 94 Les constructeurs (1) • L'appel de new pour créer un nouvel objet déclenche, dans l'ordre : • L'allocation mémoire nécessaire au stockage de ce nouvel objet et l'initialisation par défaut de ces attributs, • L'initialisation explicite des attributs, s'il y a lieu, • L'exécution d'un constructeur. • Un constructeur est une méthode d'initialisation. public class Application { public static void main(String args[]) { Personne jean = new Personne(); jean.setNom("Jean") ; } } Le constructeur est ici celui par défaut (pas de constructeur défini dans la classe Personne) 95 Les constructeurs (2) • Lorsque l'initialisation explicite n'est pas possible (par exemple lorsque la valeur initiale d'un attribut est demandée dynamiquement à l'utilisateur), il est possible de réaliser l'initialisation au travers d'un constructeur. • Le constructeur est une méthode : • de même nom que la classe, • sans type de retour. • Toute classe possède au moins un constructeur. Si le programmeur ne l'écrit pas, il en existe un par défaut, sans paramètres, de code vide. 96 Les constructeurs (3) Personne.java public class Personne { public String nom; public String prenom; public int age; public Personne(String unNom, String unPrenom, int unAge) { nom=unNom; prenom=unPrenom; age = unAge; } } Va donner une erreur à la compilation Définition d’un Constructeur. Le constructeur par défaut (Personne() )n’existe plus. Le code précédent occasionnera une erreur public class Application { public static void main(String args[]) { Personne jean = new Personne(); jean.setNom("Jean") ; } } 97 Les constructeurs (4) • Pour une même classe, il peut y avoir plusieurs constructeurs, de signatures différentes (surcharge). • L'appel de ces constructeurs est réalisé avec le mot new auquel on fait passer les paramètres. • p1 = new Personne(« Hervé", « Tondeur", 44); • Déclenchement du "bon" constructeur • Il se fait en fonction des paramètres passés lors de l'appel (nombre et types). C'est le mécanisme de "lookup". • Attention • Si le programmeur crée un constructeur (même si c'est un constructeur avec paramètres), le constructeur par98défaut n'est plus disponible. Attention aux erreurs de compilation ! Les constructeurs (5) Personne.java public class Personne { public String nom; public String prenom; public int age; public void Personne() { nom=null; prenom=null; age = 0; } public String Personne(String unNom, String unPrenom, int unAge) { nom=unNom; prenom=unPrenom; age = unAge; } } Redéfinition d’un Constructeur sans paramètres On définit plusieurs constructeurs qui se différencient uniquement par leurs paramètres (on parle de leur signature) 99 Classe et objet en Java Du modèle à … … la classe Java et de la classe à ... ... des instances de cette classe class Personne Personne jean, pierre; { jean = new Personne (); String nom; pierre = new Personne (); int age; float salaire; } L’opérateur d’instanciation en Java est new : MaClasse monObjet = new MaClasse(); En fait, new va réserver l’espace mémoire nécessaire pour créer l’objet « monObjet » de la classe « MaClasse » Le new ressemble beaucoup au malloc du C 100 Accès aux attributs d’un objet (1) Personne.java public class Personne { public String nom; public String prenom; public int age; public void setNom(String unNom) { nom = unNom; } public String getNom() { return (nom); } } 101 Accès aux attributs d’un objet (2) Application.java public class Application { public static void main(String args[]) { Personne jean = new Personne() jean.nom = "Jean" ; jean.prenom = "Pierre" ; } } Remarque : Contrairement aux variables, les attributs d'une classe, s'ils ne sont pas initialisés, se voient affecter automatiquement une valeur par défaut. Cette valeur vaut : 0 pour les variables numériques, false pour les booléens, et null pour les références. 102 Accès aux méthodes d’un objet (1) Personne.java public class Personne { public String nom; public String prenom; public int age; public void setNom(String unNom) { nom = unNom; } public String getNom() { return (nom); } } 103 Accès aux méthodes d’un objet (2) Application.java public class Application { public static void main(String args[]) { Personne jean = new Personne() jean.setNom("Jean") ; } } 104 Notion de méthodes et de paramètres (1) La notion de méthodes dans les langages objets • Proches de la notion de procédure ou de fonction dans les langages procéduraux. • La méthode c’est avant tout le regroupement d’un ensemble d’instructions suffisamment générique pour pouvoir être réutilisées • Comme pour les procédures ou les fonctions (au sens mathématiques) on peut passer des paramètres aux méthodes et ces dernières peuvent renvoyer des valeurs (grâce au mot clé return). 105 Mode de passage des paramètres • Java n'implémente qu'un seul mode de passage des paramètres à une méthode : le passage par valeur. • Conséquences : • l'argument passé à une méthode ne peut être modifié, • si l'argument est une instance, c'est sa référence qui est passée par valeur. Ainsi, le contenu de l'objet peut être modifié, mais pas la référence elle-même. 106 Notion de méthodes et de paramètres (2) exemple : public, static type de la valeur renvoyée ou void couples d'un type et d'un identificateur séparés par des «,» <modificateur> <type-retour> <nom> (<liste-param>) {<bloc>} public double add (double number1, double number2) { return (number1 +number2); } Notre méthode retourne ici une valeur 107 Portée des variables (1) • Les variables sont connues et ne sont connues qu’à l’intérieur du bloc dans lequel elles sont déclarées public class Bidule { int i, j, k; public void truc(int z) { int j,r; r = z; } public void machin() { k = r; } } Ce sont 2 variables différentes k est connu au niveau de la méthode machin() car déclaré dans le bloc de la classe. Par contre r n’est pas défini pour machin(). On obtient une erreur à la compilation 108 Portée des variables (2) • En cas de conflit de nom entre des variables locales et des variables globales, c’est toujours la variable la plus locale qui est considérée comme étant la variable désignée par cette partie du programme • Attention par conséquent à ce type de conflit quand on manipule des variables globales. public class Bidule { int i, k, j; public void truc(int z) { int j,r; j = z; } C’est le j défini en local qui est utilisé dans la méthode truc() } 109 Destruction d’objets (1) • Java n'a pas repris à son compte la notion de destructeur telle qu’elle existe en C++ par exemple. • C'est le ramasse-miettes (ou Garbage Collector - GC en anglais) qui s'occupe de collecter les objets qui ne sont plus référencés. • Le ramasse-miettes fonctionne en permanence dans un thread de faible priorité (en « tâche de fond »). Il est basé sur le principe du compteur de références. 110 Destruction d’objets (2) • Ainsi, le programmeur n’a plus à gérer directement la destruction des objets, ce qui était une importante source d'erreurs (on parlait de fuite de mémoire ou « memory leak » en anglais). • Le ramasse-miettes peut être "désactivé" en lançant l'interpréteur java avec l'option -noasyncgc. • Inversement, le ramasse-miettes peut être lancé par une application avec l'appel System.gc(); 111 Destruction d’objets (3) • Il est possible au programmeur d'indiquer ce qu'il faut faire juste avant de détruire un objet. • C'est le but de la méthode finalize() de l'objet. • Cette méthode est utile, par exemple, pour : • • • • fermer une base de données, fermer un fichier, couper une connexion réseau, etc. 112 L’encapsulation (1) • Notion d'encapsulation : • les données et les procédures qui les manipulent sont regroupées dans une même entité, l'objet. • Les détails d'implémentation sont cachés, le monde extérieur n'ayant accès aux données que par l'intermédiaire d'un ensemble d'opérations constituant l'interface de l'objet. • Le programmeur n'a pas à se soucier de la représentation physique des entités utilisées et peut raisonner en termes d'abstractions. 113 L’encapsulation (2) • Programmation dirigée par les données : • pour traiter une application, le programmeur commence par définir les classes d'objets appropriées, avec leurs opérations spécifiques. • chaque entité manipulée dans le programme est un représentant (ou instance) d'une de ces classes. • L'univers de l'application est par conséquent composé d'un ensemble d'objets qui détiennent, chacun pour sa part, les clés de leur comportement. 114 Contrôle d’accès (1) • Chaque attribut et chaque méthode d'une classe peut être : • visible depuis les instances de toutes les classes d'une application. En d'autres termes, son nom peut être utilisé dans l'écriture d'une méthode de ces classes. Il est alors public. • visible uniquement depuis les instances de sa classe. En d'autres termes, son nom peut être utilisé uniquement dans l'écriture d'une méthode de sa classe. Il est alors privé. • Les mots réservés sont : • public • private 115 Contrôle d’accès (2) • En toute rigueur, il faudrait toujours que : • les attributs ne soient pas visibles, • Les attributs ne devraient pouvoir être lus ou modifiés que par l'intermédiaire de méthodes prenant en charge les vérifications et effets de bord éventuels. • les méthodes "utilitaires" ne soient pas visibles, • seules les fonctionnalités de l'objet, destinées à être utilisées par d'autres objets soient visibles. • C’est la notion d’encapsulation • Nous verrons dans la suite que l’on peut encore affiner le contrôle d’accès 116 Contrôle d’accès (3) public class Parallelogramme { private int longueur = 0; // déclaration + initialisation explicite private int largeur = 0; // déclaration + initialisation explicite public int profondeur = 0; // déclaration + initialisation explicite public void affiche ( ) {System.out.println("Longueur= " + longueur + " Largeur = " + largeur + " Profondeur = " + profondeur); }} public class ProgPpal { public static void main(String args[]) { Parallelogramme p1 = new Parallelogramme(); p1.longueur = 5; // Invalide car l'attribut est privé p1.profondeur = 4; // OK p1.affiche( ); // OK }} 117 Variables de classe (1) • Il peut s'avérer nécessaire de définir un attribut dont la valeur soit partagée par toutes les instances d'une classe. On parle de variable de classe. • Ces variables sont, de plus, stockées une seule fois, pour toutes les instances d'une classe. • Mot réservé : static • Accès : • depuis une méthode de la classe comme pour tout autre attribut, • via une instance de la classe, • à l'aide du nom de la classe. 118 Variables de classe (2) Variable de classe public class UneClasse { public static int compteur = 0; public UneClasse () { compteur++; } } public class AutreClasse { public void uneMethode() { int i = UneClasse.compteur; } } Utilisation de la variable de classe compteur dans le constructeur de la classe Utilisation de la variable de classe compteur dans une autre classe 119 Méthodes de classe (1) • Il peut être nécessaire de disposer d'une méthode qui puisse être appelée sans instance de la classe. C'est une méthode de classe. • On utilise là aussi le mot réservé static • Puisqu'une méthode de classe peut être appelée sans même qu'il n'existe d'instance, une méthode de classe ne peut pas accéder à des attributs non statiques. Elle ne peut accéder qu'à ses propres variables et à des variables de classe. 120 Méthodes de classe (2) public class UneClasse { public int unAttribut; public static void main(String args[]) { unAttribut = 5; // Erreur de compilation } } La méthode main est une méthode de classe donc elle ne peut accéder à un attribut non lui-même attribut de classe Autres exemples de méthodes de classe courantes Math.sin(x); String String.valueOf (i); 121 Modificateur de classe 122 • Précède la déclaration de la classe • • • • • Annotations (plus tard…) public (par défaut package) abstract(incomplète, pas d’instance) final(pas d’extension) Strictfp (technique…) classes et objets III) Champs 123 • Modificateurs • annotations • Contrôle d’accès • • • • • • • • private protected public package static (variables de classe) final (constantes) transient Volatile • Initialisations • Création par opérateur new classes et objets V) Méthodes 124 • Modificateurs: • • • • • • • • Annotations Contrôle d’accès (comme pour les variables) abstract static n’a pas accès aux variables d’instances final ne peut pas être remplacée synchronized native (utilisation de fonctions « native ») strictfp classes et objets Composition d’objets (1) • Un objet peut être composé à partir d’autres objets Exemple : Une voiture composée de • 5 roues (roue de secours) chacune composée • d’un pneu • d’un moteur composé • de plusieurs cylindres • de portières • etc… Chaque composant est un attribut de l’objet composé 125 Composition d’objets (2) Syntaxe de composition d’objets class Pneu { private float pression ; void gonfler(); void degonfler();} class Roue { private float diametre; Pneu pneu ;} class Voiture { Roue roueAVG,roueAVD, roueARG, roueARD , roueSecours ; Portiere portiereG, portiereD; Moteur moteur;} 126 Composition d’objets (3) • Généralement, le constructeur d’un objet composé doit appeler le constructeur de ses composants public Roue () { pneu = new Pneu();} public Voiture () { roueAVG = new Roue(); roueAVD = new Roue(); roueARG = new Roue(); roueARD = new Roue(); portiereG = new Portiere(); portiereD = new Portiere(); moteur = new Moteur();} 127 Composition d’objets (4) • L’instanciation d’un objet composé instancie ainsi tous les objets qui le composent 128 Chapitre IV Héritage L’héritage (1) : Concept • La modélisation du monde réel nécessite une classification des objets qui le composent • Classification = distribution systématique en catégories selon des critères précis • Classification = hiérarchie de classes • Exemples : • classification des éléments chimiques • classification des êtres vivants 130 L’héritage (2) : exemple 131 L’héritage (3) : définition • Héritage : mécanisme permettant le partage et la réutilisation de propriétés entre les objets. La relation d’héritage est une relation de généralisation / spécialisation. • La classe parente est la superclasse. • La classe qui hérite est la sous-classe. 132 L’héritage (3) : représentation graphique Superclasse Lien d’héritage Sous-classe Représentation avec UML d’un héritage (simple) 133 L’héritage avec Java (1) • Java implémente le mécanisme d'héritage simple qui permet de "factoriser" de l'information grâce à une relation de généralisation / spécialisation entre deux classes. • Pour le programmeur, il s'agit d'indiquer, dans la sousclasse, le nom de la superclasse dont elle hérite. • Par défaut toutes classes Java hérite de la classe Object • L'héritage multiple n'existe pas en Java. • Mot réservé : extends 134 L’héritage avec Java (2) class Personne { private String nom; private Date date_naissance; // ... } class Employe extends Personne { private float salaire; // ... } class Etudiant extends Personne { private int numero_carte_etudiant; // ... } 135 L’héritage en Java (3) • Constructeurs et héritage • par défaut le constructeur d’une sous-classe appelle le constructeur "par défaut" (celui qui ne reçoit pas de paramètres) de la superclasse. Attention donc dans ce cas que le constructeur sans paramètre existe toujours dans la superclasse... • Pour forcer l'appel d'un constructeur précis, on utilisera le mot réservé super. Cet appel devra être la première instruction du constructeur. 136 L’héritage en Java (4) public class Employe extends Personne { public Employe () {} public Employe (String nom, String prenom, int anNaissance) { super(nom, prenom, anNaissance); } } Appel explicite à ce constructeur avec le mot clé super public class Personne { public String nom, prenom; public int anNaissance; public Personne() { nom=""; prenom=""; } public Personne(String nom, String prenom, int anNaissance) { this.nom=nom; this.prenom=prenom; this.anNaissance=anNaissance; } } 137 L’héritage en Java (5) public class Personne { public String nom, prenom; public int anNaissance; public Personne() { nom=""; prenom=""; } public Personne(String nom, String prenom, int anNaissance) { this.nom=nom; this.prenom=prenom; this.anNaissance=anNaissance; } } public class Object { public Object() { … / ... } } Appel par défaut dans le constructeur de Personne au constructeur par défaut de la superclasse de Personne, qui est Object 138 Redéfinition de méthodes • Une sous-classe peut redéfinir des méthodes existant dans une de ses superclasses (directe ou indirectes), à des fins de spécialisation. • Le terme anglophone est "overriding". On parle aussi de masquage. • La méthode redéfinie doit avoir la même signature. class Employe extends Personne class Cadre extends Employe { { redéfinition private float salaire; public calculePrime() public calculePrime( ) { { // ... // ... } } // ... } } 139 Recherche dynamique des méthodes (1) • Le polymorphisme • Capacité pour une entité de prendre plusieurs formes. • En Java, toute variable désignant un objet est potentiellement polymorphe, à cause de l'héritage. • Polymorphisme dit « d’héritage » • le mécanisme de "lookup" dynamique : • déclenchement de la méthode la plus spécifique d’un objet, c'est-à-dire celle correspondant au type réel de l'objet, déterminé à l'exécution uniquement (et non le type de la référence, seul type connu à la compilation, qui peut être plus générique). • Cette dynamicité permet d'écrire du code plus générique. 140 Recherche dynamique des méthodes (2) Employe jean = new Employe(); jean.calculePrime(); Employe salaire : Double calculePrime() Cadre Employe jean = new Cadre(); jean.calculePrime(); calculePrime() 141 Opérateur instanceof • L'opérateur instanceof confère aux instances une capacité d'introspection : il permet de savoir si une instance est instance d'une classe donnée. • Renvoie une valeur booléenne if ( ... ) Personne jean = new Etudiant(); else Personne jean = new Employe(); //... if (jean instanceof Employe) // discuter affaires else // proposer un stage 142 Forçage de type / transtypage (1) • Lorsqu'une référence du type d'une classe désigne une instance d'une sous-classe, il est nécessaire de forcer le type de la référence pour accéder aux attributs spécifiques à la sous-classe. • Si ce n'est pas fait, le compilateur ne peut déterminer le type réel de l'instance, ce qui provoque une erreur de compilation. • On utilise également le terme de transtypage • Similaire au « cast » en C 143 Forçage de type / transtypage (2) class Personne { private String nom; private Date date_naissance; // ... } class Employe extends Personne { public float salaire; // ... } Personne jean = new Employe (); float i = jean.salaire; // Erreur de compilation float j = ( (Employe) jean ).salaire; // OK A ce niveau pour le compilateur dans la variable « jean » c’est un objet de la classe Personne, donc qui n’a pas d’attribut « salaire » On « force » le type de la variable « jean » pour pouvoir accéder à l’attribut « salaire ». On peut le faire car c’est bien un objet Employe qui est dans cette variable 144 L’autoréférence : this (1) • Le mot réservé this, utilisé dans une méthode, désigne la référence de l'instance à laquelle le message a été envoyée (donc celle sur laquelle la méthode est « exécutée »). • Il est utilisé principalement : • lorsqu'une référence à l'instance courante doit être passée en paramètre à une méthode, • pour lever une ambiguïté, • dans un constructeur, pour appeler un autre constructeur de la même classe. 145 L’autoréférence : this (2) class Personne { public String nom; Personne (String nom) { this.nom=nom; } } Pour lever l’ambiguïté sur le mot « nom » et déterminer si c’est le nom du paramètre ou de l’attribut public MaClasse(int a, int b) {...} public MaClasse (int c) { this(c,0); } public MaClasse () { this(10); } Appelle le constructeur MaClasse(int a, int b) Appelle le constructeur MaClasse(int c) 146 Classes abstraites (1) • Il peut être nécessaire au programmeur de créer une classe déclarant une méthode sans la définir (c'est-àdire sans en donner le code). La définition du code est dans ce cas laissée aux sous-classes. • Une telle classe est appelée classe abstraite. • Elle doit être marquée avec le mot réservé abstract. • Toutes les méthodes de cette classe qui ne sont pas définies doivent elles aussi être marquées par le mot réservé abstract. • Une classe abstraite ne peut pas être instanciée. 147 Classes abstraites (2) • Par contre, il est possible de déclarer et d'utiliser des variables du type de la classe abstraite. • Si une sous-classe d'une classe abstraite ne définit pas toutes les méthodes abstraites de ses superclasses, elle est abstraite elle aussi. public abstract class Polygone { private int nombreCotes = 3; public abstract void dessine (); // methode non définie public int getNombreCotes() { return(nombreCotes); } } 148 Notion d’ « Interfaces » • Pour définir qu'une certaine catégorie de classes doit implémenter un ensemble de méthodes, on peut regrouper les déclarations de ces méthodes dans une interface. • Le but est de décrire le fait que de telles classes pourront ainsi être manipulées de manière identique. • Exemple : • Tous les appareils électriques peuvent être allumés ou éteint • Tous les objets comestibles peuvent être mangés • Tous les objets lumineux éclairent 149 Définition d’Interface • Une interface est donc la description d’un ensemble des procédures (méthodes) que les classes Java peuvent mettre en œuvre. • Les classes désirant appartenir à la catégorie ainsi définie • déclareront qu'elles implémentent cette interface, • fourniront le code spécifique des méthodes déclarées dans cette interface. • Cela peut être vu comme un contrat entre la classe et l’interface • la classe s’engage à implémenter les méthodes définies dans l’interface 150 Codage d’une interface en Java • Mot réservé : interface • Dans un fichier nom_interface.java, on définit la liste de toutes les méthodes de l’interface interface nomInterface { type_retour methode1(paramètres); type_retour methode2(paramètres); … } • Les méthodes d'une interface sont abstraites : elles seront écrites spécifiquement dans chaque classe implémentant l’interface • Le modificateur abstract est facultatif. 151 Implémentation d’une interface dans une classe • Mot réservé : implements • La classe doit expliciter le code de chaque méthode définie dans l’interface class MaClasse implements nomInterface { … type_retour methode1(paramètres) {code spécifique à la méthode1 pour cette classe}; … } 152 Exemple d’Interface (1) interface Electrique { void allumer(); void eteindre(); } class Radio implements Electrique { // ... void allumer() {System.out.println(« bruit »);} void eteindre() {System.out.println(« silence »);} class Ampoule implements Electrique { // ... void allumer() {System.out.println(« j’éclaire »);} void eteindre() {System.out.println(« plus de lumière»);} } 153 Exemple d’Interface (2) // … Ampoule monAmpoule = new Ampoule(); Radio maRadio = new Radio(); Electrique c; Boolean sombre; // … if(sombre == true) c = monAmpoule; else c = maRadio; c.allumer(); … c.eteindre(); // … 154 Utilisation des interfaces Une variable peut être définie selon le type d’une interface Une classe peut implémenter plusieurs interfaces différentes L’opérateur instanceof peut être utilisé sur les interfaces Exemple : interface Electrique … interface Lumineux … class Ampoule implements Electrique, Lumineux … Electrique e; Object o = new Ampoule(); 155 if (o instanceof Electrique) {e=(Electrique)o;e.allumer();} Conclusion sur les interfaces • Un moyen d’écrire du code générique • Une solution au problème de l’héritage multiple • Un outil pour concevoir des applications réutilisables 156 Chapitre V – La généricité 157 Principes généraux de la généricité Généricité Principes 158 • Paramétrer une classe ou une méthode par un type: • une pile de X • En java toute classe étant dérivée de Object, cela permet d'obtenir une forme de généricité sans contrôle des types • une pile d'Object • La généricité en Java est un mécanisme "statique" assez complexe • la généricité existe dans d'autres langages (exemple C++ et Ada) (mais de façon différente) Généricité Exemple: Classe non générique 159 class TestGenerique{ int valeur; TestGenerique(){ valeur=0; } TestGenerique(int v){ valeur=v; } public void setValeur(int v){ valeur=v; } public String getValeur(){ return valeur; } } TestGenerique tg=new TestGenerique(10); tg.setValeur(20); System.out.println(tg.getValeur()); OK fonctionne TestGenerique tg=new TestGenerique("Bonjour"); tg.setValeur("Le monde"); System.out.println(tg.getValeur()); Ne fonctionne pas Généricité L’opérateur diamant <> 160 Pour rendre notre classe générique, on vas utiliser l’opérateur « Diamant » noté <>, cet opérateur permet mis devant une classe de passer à cette même classe un type génrérique à la classe. L’opérateur diamant <UNNOM> prend entre les chevrons un nom qui sera le nom générique du type. Exemple : class maClasse<UnTypeGenerique>{ …. } Généricité Rendre générique une classe 161 class TestGenerique{ int valeur; TestGenerique(){ valeur=0; } TestGenerique(int v){ valeur=v; } Il faut pour cela rendre générique les types que l’on rencontre dans notre classe. Ici int dans notre exemple. public void setValeur(int v){ valeur=v; } public int getValeur(){ return valeur; } } Généricité Utilisation de l’opérateur <> 162 class TestGenerique<T>{ T valeur; TestGenerique(){ valeur=0; } TestGenerique(T v){ valeur=v; } On va placer notre opérateur <T> après le nom de la classe On remplace l’ensemble des types par notre type générique T public void setValeur(T v){ valeur=v; } public T getValeur(){ return valeur; } } Généricité Utilisation de l’opérateur <> class TestGenerique<T>{ 163 T valeur; TestGenerique(){ valeur=0; } TestGenerique(T v){ valeur=v; } public void setValeur(T v){ valeur=v; } public T getValeur(){ return valeur; } } TestGenerique<int> tg=new TestGenerique(10); tg.setValeur(20); System.out.println(tg.getValeur()); On indique lors de la création de l’instance de l’objet, le type générique de la classe TestGenerique<String> tg=new TestGenerique("Bonjour"); tg.setValeur("Le monde"); System.out.println(tg.getValeur()); Maintenant notre classe est devenu générique, elle fonctionne quelquesoit le type simple utilisé ou avec un nom de classe comme type. Remarques 164 • Une déclaration de type générique peut avoir plusieurs paramètres: • Map<K,V> Généricité Chapitre VI Exceptions VI) Exceptions 1. 2. 3. 4. 5. Principes généraux Déclarations de throws try, catch et finally Transfert d'information: chainage, pile Assertions 166 Exceptions et assertions • principe: • traitement des "erreurs" • quand une exception est lancée: • rupture de l'exécution séquentielle • "dépiler" les méthodes et les blocs • jusqu'à un traite exception adapté • erreur: • rupture du contrat: • précondition violée 167 Exceptions • checked ou unchecked • checked: cas exceptionnel, mais dont l'occurrence est prévue et peut être traitée (exemple: valeur en dehors des conditions de la précondition, …) • Une méthode qui peut lancer une checked exception doit le déclarer • unchecked: il n'y a rien à faire, (exemple une erreur interne de la JVM) ou une erreur à l'exécution (dépassement de tableau) • Une méthode qui peut lancer une unchecked exception ne doit pas le déclarer 168 Exceptions • Une exception est un objet d'une classe dérivée de Throwable. • Le mécanisme est le même que pour tout objets: • • • • on peut définir des sous-classes des constructeurs redéfinir des méthodes ajouter des méthodes 169 Exceptions et traite-exceptions • Un traite exception déclare dans son entête un paramètre • Le type du paramètre détermine si le traiteexception correspond à l'exception • même mécanisme que pour les méthodes et l'héritage 170 Throw • Certaines exceptions et errors sont lancées par la JVM • L'utilisateur peut définir ses propres exceptions et les lancer lui-même: throw expression; l'expression doit s'évaluer comme une valeur ou une variable qui peut être affectée à Throwable 171 Environnement • Par définition une exception va transférer le contrôle vers un autre contexte • le contexte dans lequel l'exception est traitée est différent du contexte dans lequel elle est lancée • l'exception elle-même peut permettre de passer de l'information par son instanciation • l'état de la pile au moment de l'exception est aussi transmis public StackTraceElement[] getStackTrace() et public void printStackTrace() 172 Hiérarchie: • java.lang.Throwable (implements java.io.Serializable) • java.lang.Error • • • • java.lang.AssertionError java.lang.LinkageError java.lang.ThreadDeath java.lang.VirtualMachineError • exemple:java.lang.StackOverflowError • java.lang.Exception • • • • • • • • java.lang.ClassNotFoundException java.lang.CloneNotSupportedException java.lang.IllegalAccessException java.lang.InstantiationException java.lang.InterruptedException java.lang.NoSuchFieldException java.lang.NoSuchMethodException java.lang.RuntimeException • exemple: java.lang.IndexOutOfBoundsException 173 Hiérarchie • Throwable: • la super classe des erreurs et des exceptions • Error : unchecked • Exception :checked sauf RuntimeException 174 Exemple public class MonException extends Exception{ public final String nom; public MonException(String st) { super("le nombre "+st+" ne figure pas"); nom=st; } } 175 Exemple (suite) class Essai{ static String[] tab={"zéro","un","deux","trois","quatre"}; static int chercher(String st ) throws MonException{ for(int i=0;i<tab.length;i++) if (tab[i].equals(st))return i; throw new MonException(st); } public static void main(String st[]){ try{ chercher("zwei"); }catch(Exception e){ System.out.println(e); } } } 176 Résultat • Donnera: exceptions.MonException: le nombre zwei ne figure pas • e.printStackTrace(); dans le try bloc donnera: exceptions.MonException: le nombre zwei ne figure pas at exceptions.Essai.chercher(MonException.java:29) at exceptions.Essai.main(MonException.java:34) 177 Throws • principe: • toute méthode qui peut générer directement ou indirectement une (checked) exception doit le déclarer par une clause "throws" dans l'entête de la méthode. • (les initialiseurs statiques ne peuvent donc pas générer d'exceptions) • La vérification a lieu à la compilation 178 Clause throws • Une méthode qui appelle une méthode qui peut lancer une exception peut • attraper (catch) cette exception dans un try bloc englobant la méthode qui peut lancer cette exception • attraper cette exception et la transformer en une exception déclarée dans la clause throws de la méthode • déclarer cette exception dans la clause throws de sa déclaration 179 Clause throws et héritage • Si une classe dérivée redéfinit (ou implémente) une méthode la clause throws de la méthode redéfinie doit être compatible avec celle d'origine • compatible = les exceptions de la clause throws sont dérivées de celles de la méthode d'origine • pourquoi? 180 try, catch, finally • On attrape les exceptions dans des try-bloc: try{ instructions }catch(exception-type1 id1){ instructions } catch(exception-type2 id2){ ... }finally{ instructions } 181 Principe: • le corps du try est exécuté jusqu'à ce qu'il termine ou qu'une exception est lancée • Si une exception est lancée les clauses "catch" sont examinées dans l'ordre • la première dont le type peut correspondre à l'exception est choisie et son code exécuté • si aucun catch ne peut correspondre l'exception est propagée • si une clause finally figure son code est ensuite exécuté (toujours avec ou sans exception) 182 Exemple class A extends Exception{ } class B extends A{ } class essai{ public static void main(String[] st){ try{ throw new B(); }catch (A a){ System.out.println(a); // }catch (B b){ // System.out.println(b); }finally{ System.out.println("finally.."); } } } 183 finally public boolean rechercher(String fichier, String mot) throws StreamException{ Stream input=null; try{ input=new Stream(fichier); while(!input.eof()) if(input.next().equals(mot)) return true; return false; }finally{ if (input != null) input.close(); } } 184 Chaînage d'exceptions • Une exception peut être causée par une autre. • il peut être utile dans ce cas de transmettre la cause de l'exception • méthode: public Throwable initCause(Throwable cause) 185 Transmission d'information • en définissant une extension de la classe et en définissant des constructeurs • par défaut on a les constructeurs public Throwable() public Throwable(String message) public Throwable(String message, Throwable cause) 186 Transmission d'information • On peut récupérer ces informations: public String getMessage() public Throwable getCause() • On peut obtenir l'état de la pile: public void printStackTrace() public StackTraceElement[] getStackTrace() 187 Exemple class X extends Exception{ public X(){} public X(String details){ super(details); } public X(Throwable e){ super(e); } public X(String details, Throwable e){ super(details,e); } } 188 Suite try{ throw new A(); }catch (A a){ try { throw new X(a); } catch (X ex) { ex.printStackTrace(); } } } ----- X: A at essai.main(Finally.java:61) Caused by: A at essai.main(Finally.java:58) 189 Remarque • à la place de: throw new X(a); • on pourrait mettre throw (X) new X().initCause(a); (pourquoi le cast (X) est nécessaire?) 190 Java Swing Principes de base • Des composants graphiques (exemple: JFrame, JButton …) • Hiérarchie de classes • Des événements et les actions à effectuer (exemple presser un bouton) • (Et d'autres choses…) Principes • Définir les composants (instance de classes) • Les placer à la main (layout Manager) dans un JPanel ou un content pane ou en utilisant des outils comme eclipse ou netbeans • Définir les actions associées aux événements (Listener) et les associer aux composants graphiques Principes • Dans une interface graphique, le programme réagit aux interactions avec l'utilisateur • Les interactions génèrent des événements • Le programme est dirigé par les événements (event-driven) Afficher… • Pour pouvoir être affiché, il faut que le composant soit dans un top-level conteneur: (JFrame, JDialog et JApplet) • Hiérarchie des composants: arbre racine toplevel Exemple • Correspond à la hiérarchie Le code import java.awt.*; import javax.swing.*; public class TopLevel { /*** Affiche une fenêtre JFrame top level * avec une barre de menu JMenuBar verte * et un JLabel jaune */ private static void afficherMaFenetre() { //créer la Jframe //créer la JMenuBar //créer le Jlabel // mettre le JMenuBar et le Jlable dans la Jframe //afficher la Jframe } } Le code //Creer la JFrame JFrame frame = new JFrame("TopLevelDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Créer la JMenuBar JMenuBar greenMenuBar = new JMenuBar(); greenMenuBar.setOpaque(true); greenMenuBar.setBackground(new Color(0, 200, 0)); greenMenuBar.setPreferredSize(new Dimension(200, 20)); //Créer le JLabel JLabel yellowLabel = new JLabel(); yellowLabel.setOpaque(true); yellowLabel.setBackground(new Color(250, 250, 0)); yellowLabel.setPreferredSize(new Dimension(200, 180)); //mettre la JmenuBar et position le JLabel frame.setJMenuBar(greenMenuBar); frame.getContentPane().add(yellowLabel, BorderLayout.CENTER); //afficher... frame.pack(); frame.setVisible(true); Et le main public class TopLevel {//afficherMaFenetre() public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { afficherMaFenetre(); } }); } } Evénements: principes • Dans un système d'interface graphique: • Quand l'utilisateur presse un bouton, un "événement" est posté et va dans une boucle d'événements • Les événements dans la boucle d'événements sont transmis aux applications qui se sont enregistrées pour écouter. Evénements • Chaque composant génère des événements: • Presser un Jutton génère un ActionEvent (système d'interface graphique) • Cet ActionEvent contient des infos (quel bouton, position de la souris, modificateurs…) • Un event listener (implémente ActionListener) • définit une méthode actionPerformed • S'enregistre auprès du bouton addActionListener • Quand le bouton est "clické",l'actionPerformed sera exécuté (avec l'ActionEvent comme paramètre) Exemples Buttons Un exemple • Un bouton qui réagit Le code: • Un JButton • Un JLabel • Implementer ActionListener • actionPerfomed définit ce qui se passe quand le bouton est cliqué • Placer le bouton et le label Code: import java.awt.*; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JButton; import javax.swing.Jcomponent; import java.awt.Toolkit; import java.awt.BorderLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JLabel; public class UnBouton extends Jpanel implements ActionListener { JButton bouton; String contenu="Rien Reçu"; JLabel label=new JLabel(contenu); int cmp=0; public UnBouton() { //…} public void actionPerformed(ActionEvent e) {//…} private static void maFenetre(){//…} public static void main(String[] args) {//…} } Code public UnBouton() { super(new BorderLayout()); bouton = new JButton("Click"); bouton.setPreferredSize(new Dimension(200, 80)); add(bouton, BorderLayout.NORTH); label = new JLabel(contenu); label.setPreferredSize(new Dimension(200, 80)); add(label,BorderLayout.SOUTH); bouton.addActionListener(this); } public void actionPerformed(ActionEvent e) { Toolkit.getDefaultToolkit().beep(); label.setText("clické "+ (++cmp)+ " fois"); } Code private static void maFenetre() { JFrame frame = new JFrame("UnBouton"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent newContentPane = new UnBouton(); newContentPane.setOpaque(true); frame.setContentPane(newContentPane); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Formule magique javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { maFenetre(); } }); } Variante public class UnBoutonBis extends JPanel { //… bouton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Toolkit.getDefaultToolkit().beep(); label.setText("clické " + (++cmp) + " fois"); } }); } //… } Hiérarchie des classes… 209 Un exemple • Un traceur de fonctions • Une interface graphique swing Organisation • GrapheSwing contient unGraphePanel extension de Jpanel • GraphePanel méthode paintComponent qui affiche le graphe de la fonction • Graphe est la classe contenant le gaphe et définissant une méthode draw pour l'affichage • Cette méthode appelle tracer de la classe abstraite Traceur • FonctionTraceur étend Traceur 212 Le main public static void main(String[] args) { new GrapheSwing(unGraphe());} public static Graphe unGraphe() { PlotSettings p = new PlotSettings(-2, 2, -1, 1); p.setPlotColor(Color.RED); p.setGridSpacingX(0.5); p.setGridSpacingY(0.5); p.setTitle("Une parabole et une sinusoide"); Graphe graphe = new Graphe(p); graphe.functions.add(new Parabole()); graphe.functions.add(new FonctionTraceur() { public double getY(double x) { return Math.sin(x); } public String getName() { return "Sin(x)"; } }); 213 Composants • Modèle Vue Contrôleur Préliminaires… • Lightweight et heavyweight composants • Dépendent ou non du système d’interface graphique • Lightweight écrit en Java et dessinés dans un heavyweight composant- indépendant de la plateforme • Les heavyweight composants s’adressent directement à l’interface graphique du système • (certaines caractéristiques dépendent du look and feel). Look and feel • Look and feel: Possibilité de choisir l’apparence de l’interface graphique. UIManager gère l’apparence de l’interface public static void main(String[] args) { try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { } new SwingApplication(); //Create and show the GUI. } Multithreading • Attention au « modèle, contrôleur, vue » en cas de multithreading: • Tous les événements de dessin de l’interface graphiques sont dans une unique file d’eventdispatching dans une seule thread. • La mise à jour du modèle doit se faire tout de suite après l’événement de visualisation dans cette thread. Plus précisément • Swing prend en charge la gestion des composants qui sont dessinés en code Java (lightweight) • Les composants AWT sont eux liés aux composants natifs (heavyweight) • Swing dessine le composants dans un canevas AWT et utilise le traitement des événements de AWT Suite Les threads • Main application thread • Toolkit thread • Event dispatcher thread • Toutes Les opérations d'affichage ont lieu dans une seule thread l'EDT Principes • Une tâche longue ne doit pas être exécutée dans l'EDT • Un composant Swing doit s'exécuter dans l'EDT Exemple public void actionPerformed(ActionEvent e){ try { Thread.sleep(4000); } catch (InterruptedException e) { } } Provoque une interruption de l'affichage pendant 4 secondes Une solution public void actionPerformed(ActionEvent e){ try{ SwingUtilities.invokeLater(newRunnable( { public void run() { //opération longue } }); } catch (InterruptedException ie) {} catch (InvocationTargetException ite) {} } } Le main • Normalement la création d'une fenêtre ne devrait avoir lieu que dans l'EDT: public static void main(String[] args) { //Formule magique javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() {maFenetre(); } }); } invokeLater crée une nouvelle thread qui poste la thread crée dans l'EDT Attendre le résultat: try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { show(); } }); } catch (InterruptedException ie) { } catch (InvocationTargetException ite) { } Chapitre VIII Strings, en savoir plus Plan • • • • 226 A) String B) Expressions régulières C) Chaînes et tableaux (char et byte) D) Chaînes modifiables Strings String 227 • Une String est une chaîne de caractères non modifiable • (attention les caractères en java sont en Unicode) • StringBuilder et StringBuffer sont des classes de chaînes qui peuvent être modifiées. • String StringBuilder et StringBuffer implémentent l'interface CharSequence Strings CharSequence 228 • Interface: • char charAt(int index) Retourne le char the char en position index. • int length() Retourne la longueur de la séquence. • CharSequence subSequence(int start, int end) Retourne une sous CharSequence • String toString() Retourne la string correspondant à la séquence Strings String 229 • De nombreuses méthodes pour manipuler les chaines (attention un objet String n'est pas modifiable) • constructeurs • indexOf, lastIndexOf retourne la première (dernière) position • conversion valueOf( valeur d'un type primitif) • replace, trim, split • toLowerCase, toupperCase() • … Strings Comparaison 230 • '==' ne compare les contenus, MAIS deux littéraux ayant le même contenu sont identiques: String st1="bonjour"; String st2="bonjour" if(st1==st2)System.out.println("égal"); else System.out.println("différent"); donnera égal La méthode intern permet de retourner un String de même référence Strings Manipulations sur les chaînes • • • • • • • • • • • 231 char charAt(int index) int compareTo(String anotherString) comparaison lexicographique boolean contains(CharSequence s) boolean equals(Object anObject) int length() boolean matches(String regex) boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) String replace(CharSequence target, CharSequence replacement) String[] split(String regex) String trim() Strings Exemples 232 String string = "Madam, I am Adam"; boolean // true b = string.startsWith("Mad"); b = string.endsWith("dam"); // true b = string.indexOf("I am") > 0; // true b = string.matches("(?i)mad.*"); b = string.matches("(?i).*adam"); b = string.matches("(?i).*i am.*"); Strings Exemple: remplacement 233 static String replace(String str, String pattern, String replace) { int s = 0; int e = 0; StringBuffer result = new StringBuffer(); while ((e = str.indexOf(pattern, s)) >= 0) { result.append(str.substring(s, e)); result.append(replace); s = e+pattern.length(); } result.append(str.substring(s)); return result.toString(); } Strings Exemple 234 Strinf st1="bonjour"; String st3=new String("bonjour"); if(st1==st3)System.out.println("égal"); else System.out.println("différent"); String st4=st3.intern(); if(st1==st4)System.out.println("égal"); else System.out.println("différent"); (la comparaison des références est bien sûr moins coûteuse que la comparaison des contenus) (de plus dans tous les cas des chaînes de même contenus ont le même hashcode) Strings Expressions régulières 235 • Les expressions régulières permettent de définir un motif (pattern) objet de la classe Pattern. • Un motif est créé par la méthode compile • Pattern pat = Pattern.compile("[a-z]*") Strings Expressions régulières 236 • la syntaxe des expressions régulières (rationnelles) est assez large: • caractères • exemples \t , a ,\xhh , • classes de caractères • exemples [a-z], [^a-z], [a-z&&0-9] • classes de caractères prédéfinis • exemples . , \d, \D, \w, \W, \s, \S • classes prédéfinies ASCII, Character • exemples \p{Blank}, \p{javaLowerCase} • bords • exemples ^, $,\b (bord d'un mot) • itérations • exemples [a-z]?, [1-9][0-9]+, \W*, • capture et restitution • (X) définit la capture de X • \n correspond à la n-ième capture Strings Recherche de motif 237 • Principe: Pattern pat=Pattern.compile(regex); Matcher matcher=pat.match(entrée); boolean trouve = matcher.find(); la classe Matcher contient les méthodes pour chercher (find()), retourner la sous-séquence trouvée (group()) Strings Exemple: rechercher 238 String patternStr = "b"; Pattern pattern = Pattern.compile(patternStr); CharSequence inputStr = "a b c b"; Matcher matcher = pattern.matcher(inputStr); boolean matchFound = matcher.find(); // true String match = matcher.group(); // b int start = matcher.start(); // 2 int end = matcher.end(); // 3 matchFound = matcher.find(); // true Strings Remplacer CharSequence inputStr = "ab12 cd efg34"; String patternStr = "([a-zA-Z]+[0-9]+)"; Pattern pattern = Pattern.compile(patternStr); Matcher matcher = pattern.matcher(inputStr); // Remplacer toutes les occurrences StringBuffer buf = new StringBuffer(); boolean found = false; while ((found = matcher.find())) { String replaceStr = matcher.group(); replaceStr = replaceStr.toUpperCase(); matcher.appendReplacement(buf, replaceStr); } matcher.appendTail(buf); Strings String result = buf.toString(); // AB12 cd EFG34 239 Chaines et tableaux de char 240 • Une string n'est pas un tableau de char mais on peut passer de l'un à l'autre • constructeurs String(char[] value) String(char[] value, int offset, int count) • méthode: void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) Strings Chaînes et tableaux de byte 241 • les chaines contiennent des caractères codés en UTF-16. • On peut convertir ces caractères en byte suivant un codage • De même on peut coder des bytes en caractères unicode. • (par exemple un byte Latin-1 se code en Unicode en ajoutant un octet de 0) Strings Charset 242 • la classe Charset permet de faire correspondre des séquences d'unicode et des bytes. En standard: • • • • • • US-ASCII ISO-8859-1 UTF-8 UTF-16BE UTF-16LE UTF-16 Strings tableau de byte 243 • constructeurs: • String(byte[] bytes) (conversion suivant le jeu de caractère par défaut) • String(byte[] bytes, int offset, int length) • String(byte[] bytes, String charsetName) (suivant le charset) • String(byte[] bytes, int offset, int length, String charsetName) (suivant le charset) • méthodes • • byte[]getBytes() byte[]getBytes(String charsetName) Strings Exemple: 244 try { // Conversion Unicode en x-MacRoman String string = "abcéçùà\u563b"; System.out.println(string); byte[] mac = string.getBytes("x-MacRoman"); System.out.println(new String(mac)); // Conversion x-MacRoman vers Unicode string = new String(utf8, "x-MacRoman"); System.out.println(string); } catch (UnsupportedEncodingException e) { } • abcéçùà? • abcŽ??ˆ? • abcéçùà? Strings Exemples: 245 for(String nom: Charset.availableCharsets().keySet()) System.out.println(nom); affichera la liste des jeux de caractères: • EUC-JP • EUC-KR • GB18030 • GB2312 • GBK • IBM-Thai • IBM00858 • IBM01140 • IBM01141 • IBM01142 • IBM01143 • IBM01144 • IBM01145 • IBM01146 • IBM01147 • IBM01148 • … Strings Exemple 246 Charset charset = Charset.forName("ISO-8859-1"); CharsetDecoder decoder = charset.newDecoder(); CharsetEncoder encoder = charset.newEncoder(); try { // Convertit une string vers ISO-LATIN-1 ByteBuffer bbuf = encoder.encode(CharBuffer.wrap("une chaîne")); // Convertit ISO-LATIN-1 bytes en string. CharBuffer cbuf = decoder.decode(bbuf); String s = cbuf.toString(); } catch (CharacterCodingException e) { } Strings Exemple: 247 try { // Conversion vers ISO-LATIN-1 de bytes ByteBuffer bbuf = encoder.encode(CharBuffer.wrap("une chaîne")); // Conversion de ISO-LATIN-1 vers bytes CharBuffer cbuf = decoder.decode(bbuf); String s = cbuf.toString(); System.out.println(s); } catch (CharacterCodingException e) { } Strings StringBuilder 248 • La classe StringBuilder peut contenir des chaînes qui peuvent être modifiées. • Il s'agit d'une structure de données dynamique: la taille de la chaîne est augmentée automatiquement • La taille initiale peut être précisée dans le constructeur (16 par défaut). • (Il existe aussi une classe StringBuffer qui est "thread-safe") • méthodes insert, append, delete Strings Chapitre IX Entrées-sorties Principes généraux 250 • entrées sorties • streams dans java.io • channels dans java.nio ("n" pour non-blocking) • streams: séquences de données ordonnées avec une source (stream d'entrée) ou une destination (stream de sortie) • channels et buffer. Buffer contient les données et le channel correspond à des connections I/O package Streams 251 • Deux grandes sortes de Stream • character Streams contiennent des caractères UTF16 • byte Streams contiennent des octets • Character versus byte • InputStream ou OutputStream pour les byte • Reader, Writer pour les character • deux hiérarchies qui se correspondent I/O package Hiérarchie 252 • java.io.InputStream (implements java.io.Closeable) • java.io.ByteArrayInputStream • java.io.FileInputStream • java.io.FilterInputStream • • • • java.io.BufferedInputStream java.io.DataInputStream (implements java.io.DataInput) java.io.LineNumberInputStream java.io.PushbackInputStream • java.io.ObjectInputStream (implements java.io.ObjectInput, java.io.ObjectStreamConstants) • java.io.PipedInputStream • java.io.SequenceInputStream • java.io.StringBufferInputStream I/O package Hiérarchie 253 • java.io.OutputStream (implements java.io.Closeable, java.io.Flushable) • java.io.ByteArrayOutputStream • java.io.FileOutputStream • java.io.FilterOutputStream • java.io.BufferedOutputStream • java.io.DataOutputStream (implements java.io.DataOutput) • java.io.PrintStream (implements java.lang.Appendable, java.io.Closeable) • java.io.ObjectOutputStream (implements java.io.ObjectOutput, java.io.ObjectStreamConstants) • java.io.PipedOutputStream I/O package Hiérarchie 254 • java.io.Reader (implements java.io.Closeable, java.lang.Readable) • java.io.BufferedReader • java.io.LineNumberReader • java.io.CharArrayReader • java.io.FilterReader • java.io.PushbackReader • java.io.InputStreamReader • java.io.FileReader • java.io.PipedReader • java.io.StringReader I/O package Hiérarchie 255 • java.io.Writer (implements java.lang.Appendable, java.io.Closeable, java.io.Flushable) • • • • java.io.BufferedWriter java.io.CharArrayWriter java.io.FilterWriter java.io.OutputStreamWriter • java.io.FileWriter • java.io.PipedWriter • java.io.PrintWriter • java.io.StringWriter I/O package Streams d'octets 256 • Class InputStream (toutes ces méthodes peuvent lancer IOEXception) • abstract int read() lit un octet • int read (byte[] b) lit et écrit dans b, (le nombre d'octets lus dépend de b et est retourné • int read(byte[] b, int off, int len) • long skip(long n) • int available() n d'octets pouvant être lus • void mark(int readlimit) et void reset() pose d'une marque et retour à la marque • voidclose() I/O package Stream d'octets 257 • OutputStream (toutes ces méthodes peuvent lancer IOEXception) • • • • • abstract void write(int b) écrit un octet void write(byte[] b) void write(byte[] b, int off, int len) voidclose() voidflush() I/O package Exemples 258 public static int compteIS(String st){ try{ InputStream in; int n=0; in= new FileInputStream(st); while (in.avalaible()!=0){ System.out.println(in.read()); } } catch(IOException ioe) {ioe.printStackTrace();} return n; } I/O package Exemples 259 public static void trOS(String fichier){ int b; OutputStream out=null; try{ if(f==null) out=System.out; else out=new FileOutputStream(fichier); while((b= System.in.read())!=-1) out.write(b); out.flush(); out.close(); }catch(IOException ex){ ex.printStackTrace(); } } I/O package Reader-Writer 260 • Reader et Writer sont les deux classes abstraites pour les streams de caractères: • le read de InputStream retourne un byte comme octet de poids faible d'un int alors que le read de Reader retourne un char à partir de 2 octets de poids faible d'un int I/O package Reader 261 • essentiellement les mêmes méthodes que pour InputStream: • • • • • • • • • int read() int read(char[] cbuf) abstract int read(char[] cbuf, int off, int len) int read(CharBuffer target) boolean ready() si prêt à lire voidreset() voidmark(int readAheadLimit) booleanmarkSupported() longskip(long n) I/O package Writer 262 • similaire à OutputStream mais avec des caractères au lieu d'octets. • • • • • • • • • • • void write(char[] cbuf) abstract void write(char[] cbuf, int off, int len) void write(int c) void write(int c) void write(String str) void write(String str, int off, int len) Writer append(char c) Writer append(CharSequence csq) Writer append(CharSequence csq, int start, int end) abstract void close() abstract void flush() I/O package Exemples 263 public static int compteR(String st){ try{ Reader in; int n=0; if (st==null) in=new InputStreamReader(System.in); else in= new FileReader(st); for(; in.read() != -1;n++); Catch(IOException ioe){ioe.printStackTrace();} return n; } I/O package Exemples 264 public static void trWr(String fichier){ int b; Writer out=null; try { if(f==null) out= new OutputStreamWriter(System.out); else out=new FileWriter(fichier); while((b= System.in.read())!=-1) out.write(b); out.flush(); out.close(); }catch(IOException e){System.out.println(e);} } I/O package Remarques 265 • les streams standard System.in et System.out sont des streams d'octets • InputStreamReader permet de passer de InputStream à Reader • System.in et System.out sont des PrintStream (obsolète à remplacer par la version caractère PrintWriter) I/O package InputStreamReader et OutputStreamWriter 266 • conversion entre caractères et octets, la conversion est donnée par un charset • Constructeurs: • • • • • • • InputStreamReader(InputStream in) InputStreamReader(InputStream in, Charset cs) InputStreamReader(InputStream in, String charsetName) OutputStreamWriter(OutputStream out) OutputStreamWriter(OutputStream out, Charset cs) OutputStreamWriter(OutputStream out, CharsetEncoder enc) OutputStreamWriter(OutputStream out, String charsetName) I/O package Autres classes 267 • FileInputStream • FileOutputStream • FileReader • FileWriter • Ces classes permettent d'associer une stream à un fichier donné par son nom (String) par un objet File ou un objet FileDescriptor (un mode append peut être défini pour les ecritures) I/O package Quelques autres classes 268 • Les filtres • • • • FilterInputStream FilterOutputStream FilterReader FilterWriter • Buffered • • • • BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter • Tubes • PipedInputStream • PipedOutputStream • PipedReader • PipedWriter I/O package Exemple d'un filtre 269 class conversionMaj extends FilterReader{ public conversionMaj(Reader in){ super(in); } public int read() throws IOException{ int c=super.read(); return(c==-1?c:Character.toUpperCase((char)c)); } public int read(char[] buf, int offset, int count)throws IOException{ int nread=super.read(buf,offset,count); int last=offset+nread; for(int i=offset; i<last;i++) buf[i] = Character.toUpperCase(buf[i]); return nread; } } I/O package Exemple suite: 270 StringReader source=new StringReader("ma chaîne"); FilterReader filtre=new conversionMaj(source); int c; try{ while((c=filtre.read())!= -1) System.out.print((char)c); }catch(IOException e){ e.printStackTrace(System.err); } I/O package Pipe (tube) 271 • Un tube associe une entrée et un sortie: on lit à une extrémité et on écrit à l'autre. I/O package Exemple pipe class PipeExemple extends Thread{ private Writer out; private Reader in; public PipeExemple(Writer out,Reader in){ this.out=out; this.in=in; } public void run(){ int c; try{ try{ while ((c=in.read())!=-1){ out.write(Character.toUpperCase((char)c)); } }finally{out.close();} }catch(IOException e){e.printStackTrace(System.err);} I/O package } } 272 Suite PipedWriter out1=new PipedWriter(); PipedReader in1=new PipedReader(out1); PipedWriter out2=new PipedWriter(); PipedReader in2=new PipedReader(out2); PipeExemple pipe=new PipeExemple(out1, in2); pipe.start(); try{ for(char c='a';c<='z';c++) { out2.write(c); System.out.print((char)(in1.read())); } }finally { out2.close(); I/O package } 273 ByteArray, String… 274 • java.io.InputStream (implements java.io.Closeable) • java.io.ByteArrayInputStream • java.io.StringBufferInputStream • java.io.OutputStream (implements java.io.Closeable, java.io.Flushable) • java.io.ByteArrayOutputStream • java.io.Reader (implements java.io.Closeable, java.lang.Readable) • java.io.CharArrayReader • java.io.StringReader • java.io.Writer (implements java.lang.Appendable, java.io.Closeable, java.io.Flushable) • java.io.CharArrayWriter • java.io.StringWriter I/O package Print Streams 275 • java.io.PrintStream (implements java.lang.Appendable, java.io.Closeable) • java.io.PrintWriter • méthode println() I/O package Streams pour les données 276 • DataInput: interface pour lire des bytes d'une stream binaire et les transformer en données java de type primitif • DataOutput: interface pour convertir des valeurs de type primitif en stream binaire. I/O package Sérialisation 277 • sauvegarder des objets java en flot d'octets: • objet vers byte: sérialisation • byte vers objet: désérialisation • java.io.ObjectInputStream (implements java.io.ObjectInput, java.io.ObjectStreamConstants) • java.io.ObjectInputStream (implements java.io.ObjectInput, java.io.ObjectStreamConstants) I/O package Sauver des objets 278 • la serialisation-désérialisation doit permettre de sauvegarder et restituer des objets. • sauver et restituer des objets n'est pas si simple. Pourquoi? • interface serializable • (alternative XML) I/O package Manipuler des fichiers… 279 La classe File Les fichiers et les répertoires sont encapsulés dans la classe File du package java.io. Il n'existe pas de classe pour traiter les répertoires car ils sont considérés comme des fichiers. Une instance de la classe File est une représentation logique d'un fichier ou d'un répertoire qui peut ne pas exister physiquement sur le disque. Depuis la version 1.2 du J.D.K., de nombreuses fonctionnalités ont été ajoutées à cette classe : •la création de fichiers temporaires (createNewFile, createTempFile, deleteOnExit) •la gestion des attributs "caché" et "lecture seule" (isHidden, isReadOnly) •des méthodes qui renvoient des objets de type File au lieu de type String (getParentFile, getAbsoluteFile, getCanonicalFile, listFiles) •une méthode qui renvoie le fichier sous forme d'URL (toURL) I/O package Manipuler des fichiers… 280 - boolean canRead() indique si le fichier peut être lu - boolean canWrite() indique si le fichier peut être modifié - boolean createNewFile() création d'un nouveau fichier vide - File createTempFile(String, String) création d'un nouveau fichier dans le répertoire par défaut des fichiers temporaires. Les deux arguments sont le préfixe et le suffixe du fichier. - File createTempFile(String, String, File) création d'un nouveau fichier temporaire. Les trois arguments sont le préfixe et le suffixe du fichier et le répertoire. - boolean delete() détruire le fichier ou le répertoire. Le booléen indique le succès de l'opération - deleteOnExit() demande la suppression du fichier à l'arrêt de la JVM - boolean exists() indique si le fichier existe physiquement - String getAbsolutePath() renvoie le chemin absolu du fichier Manipuler des fichiers… 281 - boolean isAbsolute() indique si le chemin est absolu - boolean isDirectory() indique si le fichier est un répertoire - boolean isFile() indique si l'objet représente un fichier - long length() renvoie la longueur du fichier - String[] list() renvoie la liste des fichiers et répertoire contenu dans le répertoire - boolean mkdir() création du répertoire - boolean mkdirs() création du répertoire avec création des répertoires manquants dans l'arborescence du chemin - boolean renameTo() renommer le fichier Chapitre X Threads, le multitâche Threads 283 • threads: plusieurs activités qui coexistent et partagent des données • exemples: • pendant un chargement long faire autre chose • coopérer • processus versus threads • problème de l'accès aux ressources partagées • verrous • moniteur • synchronisation thread Cycle de vie d’une Thread 284 Principes de base 285 • extension de la classe Thread • méthode run est le code qui sera exécuté. • la création d'un objet dont la superclasse est Thread crée la thread (mais ne la démarre pas) • la méthode start démarre la thread (et retourne immédiatement) • la méthode join permet d'attendre la fin de la thread • les exécutions des threads sont asynchrones et concurrentes thread Exemple 286 class ThreadAffiche extends Thread{ private String mot; private int delay; ThreadAffiche(String w,int duree){ mot=w; delay=duree; } public void run(){ try{ while(true){ System.out.println(mot); Thread.sleep(delay); } }catch(InterruptedException e){ } } } thread Suite 287 public static void main(String[] args) { new ThreadAffiche("PING", 10).start(); new ThreadAffiche("PONG", 30).start(); new ThreadAffiche("Splash!",60).start(); } thread Alternative: Runnable 288 • Une autre solution: • créer une classe qui implémente l'interface Runnable (cette interface contient la méthode run) • créer une Thread à partir du constructeur Thread avec un Runnable comme argument. thread Exemple 289 class RunnableAffiche implements Runnable{ private String mot; private int delay; public RunnableAffiche(String w,int duree){ mot=w; delay=duree; } public void run(){ try{ for(;;){ System.out.println(mot); Thread.sleep(delay); } }catch(InterruptedException e){ } } } thread Suite 290 public static void main(String[] args) { Runnable ping=new RunnableAffiche("PING", 10); Runnable pong=new RunnableAffiche("PONG", 50); new Thread(ping).start(); new Thread(pong).start(); } thread Synchronisation 291 • les threads s'exécutent concurremment et peuvent accéder concurremment à des objets: • il faut contrôler l'accès: • thread un lit une variable (R1) puis modifie cette variable (W1) • thread deux lit la même variable (R2) puis la modifie (W2) • R1-R2-W2-W1 • R1-W1-R2-W2 résultat différent! thread Exemple 292 class X{ int val; } class Concur extends Thread{ X x; int i; String nom; public Concur(String st, X x){ nom=st; this.x=x; } public void run(){ i=x.val; System.out.println("thread:"+nom+" valeur x="+i); try{ Thread.sleep(10); }catch(Exception e){} x.val=i+1; System.out.println("thread:"+nom+" valeur x="+x.val); } } thread Suite 293 public static void main(String[] args) { X x=new X(); Thread un=new Concur("un",x); Thread deux=new Concur("deux",x); un.start(); deux.start(); try{ un.join(); deux.join(); }catch (InterruptedException e){} System.out.println("X="+x.val); } donnera (par exemple) • thread:un valeur x=0 • thread:deux valeur x=0 • thread:un valeur x=1 • thread:deux valeur x=1 • X=1 thread Deuxième exemple 294 class Y{ int val=0; public int increment(){ int tmp=val; tmp++; try{ Thread.currentThread().sleep(100); }catch(Exception e){} val=tmp; return(tmp); } int getVal(){return val;} } class Concur1 extends Thread{ Y y; String nom; public Concur1(String st, Y y){ nom=st; this.y=y; } public void run(){ System.out.println("thread:"+nom+" valeur="+y.increment()); } } thread Suite 295 public static void main(String[] args) { Y y=new Y(); Thread un=new Concur1("un",y); Thread deux=new Concur1("deux",y); un.start(); deux.start(); try{ un.join(); deux.join(); }catch (InterruptedException e){} System.out.println("Y="+y.getVal()); } ----------- • thread:un valeur=1 • thread:deux valeur=1 • Y=1 thread Verrous 296 • à chaque objet est associé un verrou • synchronized(expr) {instructions} • expr doit s'évaluer comme une référence à un objet • verrou sur cet objet pour la durée de l'exécution de instructions • déclarer les méthodes comme synchronized: la thread obtient le verrou et le relâche quand la méthode se termine thread synchronised(x) 297 class Concur extends Thread{ X x; int i; String nom; public Concur(String st, X x){ nom=st; this.x=x; } public void run(){ synchronized(x){ i=x.val; System.out.println("thread:"+nom+" valeur x="+i); try{ Thread.sleep(10); }catch(Exception e){} x.val=i+1; System.out.println("thread:"+nom+" valeur x="+x.val); } } } thread Méthode synchronisée 298 class Y{ int val=0; public synchronized int increment(){ int tmp=val; tmp++; try{ Thread.currentThread().sleep(100); }catch(Exception e){} val=tmp; return(tmp); } int getVal(){return val;} } ------------ • thread:un valeur=1 • thread:deux valeur=2 • Y=2 thread Mais… 299 • la synchronisation par des verrous peut entraîner un blocage: • la thread un (XA) pose un verrou sur l'objet A et (YB) demande un verrou sur l'objet B • la thread deux (XB) pose un verrou sur l'objet B et (YA) demande un verrou sur l'objet A • si XA –XB : ni YA ni YB ne peuvent êter satisfaites -> blocage • (pour une méthode synchronisée, le verrou concerne l'objet globalement et pas seulement la méthode) thread Exemple 300 class Dead{ Dead partenaire; String nom; public Dead(String st){ nom=st; } public synchronized void f(){ try{ Thread.currentThread().sleep(100); }catch(Exception e){} System.out.println(Thread.currentThread().getName()+ " de "+ nom+".f() invoque "+ partenaire.nom+".g()"); partenaire.g(); } public synchronized void g(){ System.out.println(Thread.currentThread().getName()+ " de "+ nom+".g()"); } public void setPartenaire(Dead d){ partenaire=d; } } thread Exemple (suite) 301 final Dead un=new Dead("un"); final Dead deux= new Dead("deux"); un.setPartenaire(deux); deux.setPartenaire(un); new Thread(new Runnable(){public void run(){un.f();} },"T1").start(); new Thread(new Runnable(){public void run(){deux.f();} },"T2").start(); ------------ • T1 de un.f() invoque deux.g() • T2 de deux.f() invoque un.g() thread Synchronisation… 302 • wait, notifyAll notify • attendre une condition / notifier le changement de condition: synchronized void fairesurcondition(){ while(!condition) wait(); faire ce qu'il faut qaund la condition est vraie } ----------------synchronized void changercondition(){ … changer quelque chose concernant la condition notifyAll(); // ou notify() } thread Exemple (file: rappel Cellule) 303 public class Cellule<E>{ private Cellule<E> suivant; private E element; public Cellule(E val) { this.element=val; } public Cellule(E val, Cellule suivant){ this.element=val; this.suivant=suivant; } public E getElement(){ return element; } public void setElement(E v){ element=v; } public Cellule<E> getSuivant(){ return suivant; } public void setSuivant(Cellule<E> s){ this.suivant=s; } thread File synchronisées 304 class File<E>{ protected Cellule<E> tete, queue; private int taille=0; public synchronized void enfiler(E item){ Cellule<E> c=new Cellule<E>(item); if (queue==null) tete=c; else{ queue.setSuivant(c); } c.setSuivant(null); queue = c; notifyAll(); } thread File (suite) 305 public synchronized E defiler() throws InterruptedException{ while (tete == null) wait(); Cellule<E> tmp=tete; tete=tete.getSuivant(); if (tete == null) queue=null; return tmp.getElement(); } thread 306 CHAPITRE XI Les Applets Qu’est ce qu’une applet ? 307 Une Applet, est une application Java qui s ’éxécute dans une page Web, elle exploite le plugin Java pour IE/Firefox/Chrome etc. Une Applet permet de réaliser très facilement des applications graphiques, en dessinant directement sur le Canvas de l’applet, ou d’utiliser des objets comme les boutons, boite d’éditions, etc… Comment créer une Applet ? Object | +----- Component { paint(); resize(); …} | +----- Container | +----- Panel | +--- Applet | +--- JApplet • Une applet est un objet graphique. • Mais c'est aussi un objet actif créé et contrôlé par le navigateur Web 308 Une Applet est une application qui hérite de la classe Japplet Pour définir une applet, il faut ajouter la close « import javax.swing.JApplet; ». Public class MonApplet extends JApplet implements MouseListener { Public void init(){…} } Cycle de vie d’une applet 309 Dans une applet, il existe ce que l’on appel le « le cycle de vie d’une applet », ce cycle correspond à un certains nombres de méthodes que l'on peut surcharger.Ce cycle de vis correspond à un certains nombres d'états de notre applet. • Les applets sont sous le contrôle du navigateur WWW (Firefox, IE, Hot Java, etc.) • L'interface décide quand charger les applets d'une page HTML (=> état inactif) • L'interface (re)démarre une applet quand sa fenêtre est visible sur l'écran (=> état actif) • L'interface arrête l'applet quand elle disparaît de l'écran (=> état inactif) • L'interface efface l'applet quand elle n'en a plus besoin. Cycle de vie d’une applet 310 Les méthodes de la classe Applet • les méthodes d'interface graphique (héritées): public void paint(Graphics g); 311 • les méthodes de contrôle d'exécution (héritées) : public void init(); public void start(); public void stop(); public void destroy(); Ces méthodes correspondent aux différents états de notre applet, et sont appelées lorsque nécessaire par notre JVM. Au premier lancement de l’applet => public void init (){…..} Au démarrage de l’applet => public void start(){….} A l’arrêt de l’applet => public void stop(){….} A la destruction de l’applet => public void destroy(){….} A l’affichage de l’applet => public void paint(Graphics g){….} La méthode repaint() permet de redessiner explicitement le « canvas » de l’applet, on appel pas directement la méthode paint(). Dessiner sur une applet 312 On remarquera que la méthode « paint » à pour paramètre un objet de la classe « Graphics », la classe « Graphics » apporte un ensemble de méthodes permettant de dessiner directement sur le « canvas de l'applet ». En général, on utilise des méthodes de la classe Graphics en les appelant dans la méthode paint de l'applet. • Dessiner et remplir : texte, lignes, rectangles, cercles, ellipses, polygones, arcs, images. • Modifier : couleur, fonte, zone de dessin (« clipping area ») • Mode de dessin : XOR avec une couleur donnée Consultez l’aide sur les classes Graphics Exemples de méthodes : et Graphics2D des API Java • g.setColor(bg); • g.draw3DRect(0, 0, d.width - 1, d.height - 1, true); • g.drawRoundRect(x, y, rectWidth, rectHeight, 10, 10); Gestion de la souris, l’Interface MouseListener… Gestion de la souris dans une applet => Implements MouseListener Dans la méthode init pour une applet ou le constructeur sinon : addMouseListener(this) ; Re-déclarer les 5 méthodes abstraites (obligatoire) : Public void mousePressed(MouseEvent e){….} Public void mouseClicked(MouseEvent e){….} Public void mouseReleased(MouseEvent e){….} Public void mouseExited(MouseEvent e){….} Public void mouseEntered(MouseEvent e){….} 313 Appeler une Applet dans une page Web 314 Le tag APPLET But: inclure dans un document HTML un espace pour l'exécution d'une petite application. <APPLET [CODEBASE = localisation_programme] CODE=nom_fichier_programme WIDTH=largeur_fenêtre HEIGHT=hauteur_fenêtre autres> <PARAM NAME=nom1 VALUE=valeur1> <PARAM NAME=nom2 VALUE=valeur2> ... </APPLET> Le tag PARAM permet d'envoyer des paramètres (strings) à l'applet. Passage de paramètres a une Applet 315 Transmettre un argument à une applet : On transmet un argument à une applet par l’intermédiaire du code HTML : < PARAM NAME = * VALUE = * > < PARAM NAME = font VALUE = * > Les * symbolisent les valeurs que vous devez spécifier, la première le nom du paramètre et la seconde sa valeur.. Récupérer un argument à partir d’une applet : Pour récupérer à partir d’une applet les arguments transmis par le HTML, on utilise la méthode getParameter(). TypeDeDonnée NomDeLaVariable = getParameter (" nomDuParamètre " ) ; String theFont = getParameter(" font ") ; Chapitre XII Structures collectives en Java Définition d ’une collection 317 Une collection regroupe plusieurs données de même nature Exemples : promotion d’étudiants, sac de billes, ... Une structure collective implante une collection plusieurs implantations possibles ordonnées ou non, avec ou sans doublons, ... accès, recherche, tris (algorithmes) plus ou moins efficaces Objectifs adapter la structure collective aux besoins de la collection ne pas re-programmer les traitements répétitifs classiques (affichage, saisie, recherche d’éléments, …) Structures collectives classiques 318 Tableau type[] et Array accès par index recherche efficace si le tableau est trié (dichotomie) insertions et suppressions peu efficaces défaut majeur : nombre d’éléments borné Liste interface List accès séquentiel : premier, suivant insertions et suppressions efficaces recherche lente, non efficace Tableau dynamique = tableau + liste class ArrayList Paquetage java.util de Java 319 • Interface Collection • Interfaces Set et List • Méthodes • boolean add(Object o) • boolean remove(Object o) • … • Plusieurs implantations • tableau : ArrayList • liste chaînée : LinkedList Collection Set List ArrayList LinkedList • Algorithmes génériques : tri, maximum, copie ... méthodes statiques de Collection Collection : méthodes communes boolean add(Object) : ajouter un élément boolean addAll(Collection) : ajouter plusieurs éléments void clear() : tout supprimer boolean contains(Object) : test d'appartenance boolean containsAll(Collection) : appartenance collective boolean isEmpty() : test de l'absence d'éléments Iterator iterator() : pour le parcours (cf Iterator) boolean remove(Object) : retrait d'un élément boolean removeAll(Collection) : retrait de plusieurs éléments boolean retainAll(Collection) : intersection int size() : nombre d'éléments Object[] toArray() : transformation en tableau Object[] toArray(Object[] a) : tableau de même type que a 320 Exemple : ajout d’éléments import java.util.*; public class MaCollection { static final int N = 25000; List listEntier = new ArrayList(); public static void main(String args[]) { MaCollection c = new MaCollection(); int i; for (i = 0; i < N; i++) { c.listEntier.add(new Integer(i)); } } } 321 Caractéristiques des collections • Ordonnées ou non 322 interface Set • Ordre sur les éléments ? voir tri • Doublons autorisés ou non interface SortedSet • liste (List) : avec doubles • ensemble (Set) : sans doubles • Besoins d’accès • indexé • séquentiel, via Iterator interface Collection public Iterator iterator() interface List ... get(int index) ... set(int index,Object o) Fonctionnalités des Listes 323 Implantent l'interface List ArrayList Liste implantée dans un tableau accès immédiat à chaque élément ajout et suppression lourdes LinkedList accès aux éléments lourd ajout et suppression très efficaces permettent d'implanter les structures FIFO (file) et LIFO (pile) méthodes supplémentaires : addFirst(), addLast(), getFirst(), getLast(), removeFisrt(), removeLast() Fonctionnalités des ensembles Implantent l'interface Set Eléments non dupliqués HashSet table de hashage utiliser la méthode hashCode() accès très performant aux éléments TreeSet arbre binaire de recherche maintient l'ensemble trié en permanence méthodes supplémentaires first() (mini), last() (maxi), subSet(deb,fin), headSet(fin), tailSet(deb) 324 Recherche d’un élément 325 Méthode public boolean contains(Object o) interface Collection, redéfinie selon les sous-classes Utilise l’égalité entre objets égalité définie par boolean equals(Object o) par défaut (classe Object) : égalité de références à redéfinir dans chaque classe d’éléments Cas spéciaux doublons : recherche du premier ou de toutes les occurrences ? structures ordonnées : plus efficace, si les éléments sont comparables (voir tri) Tri d’une structure collective 326 Algorithmes génériques Collections.sort(List l) Arrays.sort(Object[] a,…) Condition : collection d’éléments dont la classe définit des règles de comparaison en implémentant l’interface java.lang.Comparable implements Comparable en définissant la méthode de comparaison public int compareTo(Object o) a.compareTo(b) == 0 si a.equals(b) a.compareTo(b) < 0 pour a strictement inférieur à b a.compareTo(b) > 0 pour a strictement supérieur à b Généricité des algorithmes • N'utiliser que les méthodes communes • Déclaration • Collection col = new ArrayList(); • Parcours des éléments de la collection : Iterator • • • • accès indexé pas toujours disponible (méthode get()) utiliser la méthode Iterator iterator() se déplacer avec les méthodes next() et hasNext() exemple Collection col = new TreeSet(); Iterator i = col.iterator(); while (i.hasNext()) traiter ((transtypage)i.next()); 327 Vue d'ensemble des collections • Hiérarchie simplifiée 328 329