Cours JAVA : Concepts de la POO


Télécharger Cours JAVA : Concepts de la POO
3.53.5 étoiles sur 5 a partir de 2 votes.
Votez ce document:

Télécharger aussi :


Cours programmationorientée objet en Java

Licence d’informatique

Hugues Fauconnier

   
   

Plan du cours

 

oo oo oo oo 

oo oo 

oo oo oo 

oo oo oo 

Introduction:  nnprogrammation objet pourquoi? Comment? Un exemple en Java Classes et objets (révision) nnMéthodes et variables, constructeurs, contrôle d’accès, constructeurs Héritage: liaison dynamique et typage

nnExtension de classe, méthode et héritage, variables et héritage, constructeurs et héritage Héritage: compléments

nnclasses abstraites et interfaces, classes internes et emboîtées, classe Object, clonage,  Introduction à Swing Exceptions

nnExceptions, assertions

Divers: Noms, conversions, héritage et tableaux

Généricité

nnGénéralités, types génériques imbriqués, types paramètres bornés, méthodes génériques Types de données

nnString et expressions régulières, Collections, Conteneurs, itérations

Entrées-sorties

Threads

Compléments

nnReflections, annotations, documentation…

 

Le site du cours: Didel POO

POO-L3 H. Fauconnier

2

Bibliographie

ooDe nombreux livres sur java (attention java >= 1.5)

ooEn ligne: nn nnThinking in Java, 4th edition Bruce Eckel

              nn

ooLivre conseillé: nnThe Java Programming language fourth edition AW Ken Arnold, James Gosling,

David Holmes 

 

A) Généralités

 

ooProblème du logiciel:

nnTaille nnCoût : développement et maintenance nnFiabilité

ooSolutions : nnModularité

nnRéutiliser le logiciel nnCertification 

nnComment?


Typage…

 

ooHistoire:

nnFonctions et procédures (60 Fortran) nnTypage des données (70) Pascal Algol nnModules: données + fonctions regroupées

(80) ada nnProgrammation objet: classes, objets et héritage

B) Principes de base de la POO

ooObjet et classe: nnClasse = définitions pour des données (variables) + fonctions (méthodes) agissant sur ces données

nnObjet = élément d’une classe (instance) avec un état

nn(une méthode ou une variable peut être oode classe = commune à la classe ou 

ood’instance = dépendant de l’instance

 )

Principes de bases (suite)

 

ooEncapsulation et séparation de la spécification et de l’implémentation nnSéparer l’implémentation de la spécification.

ooNe doit être visible de l’extérieur que ce qui est nécessaire, les détails d’implémentation sont « cachés » ooHéritage:

nnUne classe peut hériter des propriétés d’une autre classe: un classe peut être une extension d’une autre classe.

Principes de bases de la POO

ooMais surtout notion de polymorphisme:

nnSi une classe A est une extension d’une classe B:

oo 

A doit pouvoir redéfinir certaines méthodes (disons f())

oo 

Un objet a de classe A doit pouvoir être considéré comme un objet de classe B

oo 

On doit donc accepter : nnB b;

nnb=a; (a a toutes les propriétés d’un B) nnb.f()  ooDoit appeler la méthode redéfinie dans A!

nnC’est le transtypage

oo 

(exemple: méthode paint des interfaces graphiques)

Principes de bases

 

ooPolymorphisme:

nnIci l’association entre le nom ‘f()’ et le code (code de A ou code de B) a lieu dynamiquement (=à l’exécution)

Liaison dynamique

nnOn 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)


C) Comment assurer la réutilisation du logiciel?

 

ooType abstrait de données

nndéfinir le type par ses propriétés (spécification)

ooInterface, spécification et implémentation

nnUne interface et une spécification (=les propriétés à assurer) pour définir un type nnUne (ou plusieurs) implémentation du type abstrait de données

                            ooCes implémentations doivent vérifier la spécification

Comment assurer la réutilisation du logiciel?

 

ooPour l’utilisateur du type abstrait de données

nnAccès uniquement à l’interface (pas d’accès à l’implémentation)

nnUtilisation des propriétés du type abstrait telles que définies dans la spécification.

nn(L’utilisateur est lui-même un type abstrait avec une interface et une spécification)

Comment assurer la réutilisation du logiciel?

 

ooMais en utilisant un type abstrait l’utilisateur n'en connaît pas l’implémentation 

nnil sait uniquement que la spécification du type abstrait est supposée être vérifiée par l'implémentation.

ooPour la réalisation concrète, une implémentation particulière est choisie ooIl y a naturellement polymorphisme


Notion de contrat (Eiffel)

 

ooUn client et un vendeur

ooUn contrat lie le vendeur et le client (spécification) ooLe client ne peut utiliser l’objet que par son interface

ooLa réalisation de l’objet est cachée au client  ooLe contrat est conditionné par l’utilisation correcte de l’objet (pré-condition)

ooSous réserve de la pré-condition le vendeur s’engage à ce que l’objet vérifie sa spécification (post-

condition)

ooLe vendeur peut déléguer: l’objet délégué doit vérifier au moins le contrat (héritage)

D) Un exemple…

 

ooPile abstraite et diverses

implémentations

Type abstrait de données

 

NOM

    pile[X] 

FONCTIONS

    vide : pile[X] -> Boolean     nouvelle : -> pile[X]     empiler : X x pile[X] -> pile[X]

    dépiler : pile[X] -> X x pile[X]

PRECONDITIONS

    dépiler(s: pile[X]) <=> (not vide(s))

AXIOMES

    forall x in X, s in pile[X]             vide(nouvelle())             not vide(empiler(x,s))             dépiler(empiler(x,s))=(x,s)

Remarques

 

ooLe type est paramétré par un autre type

ooLes axiomes correspondent aux pré- conditions

ooIl n’y pas de représentation ooIl faudrait vérifier que cette définition caractérise bien un pile au sens usuel du terme (c’est possible)

Pile abstraite en java

 

package pile;

abstract class Pile <T>{     abstract public T empiler(T v);     abstract public T dépiler();     abstract public Boolean estVide(); }

Divers

 

oopackage: regroupement de diverses classes

ooabstract: signifie qu’il n’y a pas d’implémentation

oopublic: accessible de l’extérieur ooLa classe est paramétrée par un type (java 1.5)

Implémentations

 

ooOn va implémenter la pile: nnavec un objet de classe Vector (classe définie dans .package) en fait il s’agit d’un ArrayList

nnAvec un objet de classe LinkedList nnAvec Integer pour obtenir une pile de

Integer

Une implémentation

 

package pile;

import .EmptyStackException; import .Vector;

public class MaPile<T> extends Pile<T>{

    private Vector<T> items;

    // Vector devrait être remplacé par ArrayList

    public MaPile() {         items =new Vector<T>(10);

    }

    public Boolean estVide(){         return ()==0;

    }

    public T empiler(T item){         items.addElement(item);

        return item;

    }

    //…

Suite

 

//…

public synchronized T dépiler(){         int len = ();

        T item = null;         if (len == 0)

            throw new EmptyStackException();         item = items.elementAt(len - 1);         items.removeElementAt(len - 1);

        return item;

    }    

}

Autre implémentation avec listes

package pile;

import .LinkedList;  public class SaPile<T> extends Pile<T> {     private LinkedList<T> items;     public SaPile(){

        items = new LinkedList<T>();

    }

    public Boolean estVide(){         return items.isEmpty();

    }

    public T empiler(T item){         items.addFirst(item);

        return item;

    }

    public T dépiler(){

        return items.removeFirst();

    }

}

Une pile de Integer

 

public class PileInteger extends Pile<Integer>{     private Integer[] items;     private int top=0;     private int max=100;     public PileInteger(){         items = new Integer[max];

    }

    public Integer empiler(Integer item){         if (this.estPleine())             throw new EmptyStackException();

        items[top++] = item;         return item;

    }

    //…

Suite…

 

public synchronized Integer dépiler(){

        Integer item = null;         if (this.estVide())

            throw new EmptyStackException();         item = items[--top];         return item;

    }

    public Boolean estVide(){         return (top == 0);

    }

    public boolean estPleine(){         return (top == max -1);

    }

    protected void finalize() throws Throwable {         items = null; super.finalize();

    }

}

Comment utiliser ces classes?

ooLe but est de pouvoir écrire du code utilisant la classe Pile abstraite 

ooAu moment de l’exécution, bien sûr, ce code s’appliquera à un objet concret

(qui a une implémentation) ooMais ce code doit s’appliquer à toute implémentation de Pile

Un main

 

package pile; public class Main {

    public static void vider(Pile p){         while(!p.estVide()){

            .println(p.dépiler());

        }     }

public static void main(String[] args) {

        MaPile<Integer> p1= new MaPile<Integer>();         for(int i=0;i<10;i++)             p1.empiler(i);         vider(p1);

        SaPile<String> p2= new SaPile<String>();

        p2.empiler("un");         p2.empiler("deux");         p2.empiler("trois");         vider(p2);

    }

}

E) java:  quelques rappels…

 

ooUn source avec le suffixe .java ooUne classe par fichier source (en principe) même nom pour la classe et le fichier source

(sans le suffixe .java) ooMéthode 

public static void main(String[]);

nnmain est le point d’entrée

ooCompilation génère un .class ooExécution en lançant la machine java

Généralités…

 

ooUn peu plus qu’un langage de programmation:

nn 

“gratuit”! (licence GPL) 

nn 

Indépendant de la plateforme

nn 

Langage interprété et byte code

nn 

Syntaxe à la C

nn 

Orienté objet (classes héritage) ooNombreuses bibliothèques

nn 

Pas de pointeurs! (ou que des pointeurs!) ooRamasse-miettes

nn 

Multi-thread

nn 

Distribué (WEB) applet, servlet, …

nn 

Dernière version Java SE 7 (GPL)

nn 

Site:

Plateforme Java

 

ooLa compilation génère un .class en bytecode (langage intermédiaire indépendant de la plateforme).

ooLe bytecode est interprété par un interpréteur Java JVM

Compilation javac interprétation java

 

Langage intermédiaire  et Interpréteur…

 

ooAvantage: indépendance de la plateforme nnÉchange de byte-code (applet) ooInconvénient: efficacité 

 

Plateforme Java

 

ooLa plateforme java: software au-dessus d’une plateforme exécutable sur un hardware (exemple

MacOs, linux …) ooJava VM ooJava application Programming Interface (Java API): 

 

Tout un environnement…

 

ooJava 2 sdk: JRE (java runtime environment + outils de développements compilateur, debogueurs etc…)

Tout un environnement…


 

Trois exemples de base

 

ooUne application ooUne applet

ooUne application avec interface

graphique

Application:

 

ooFichier :

/** 

 * Une application  basique

 */ class Appli {

    public static void main(String[] args) {      .println("Bienvenue en L3 ");

               //affichage

    }

}

Compiler, exécuter…

 

oo 

Créer un fichier

oo 

Compilation: nnjavac

oo 

Création de Appli.class (bytecode)

oo 

Interpréter le byte code: nnjava Appli

oo 

Attention aux suffixes!!!

nn(il faut que javac et java soient dans $PATH) Exception in thread "main" .NoClassDefFoundError: 

nnIl ne trouve pas le main -> vérifier le nom! nnVariable CLASSPATH ou option -classpath

Remarques

 

oo 

Commentaires /* … */ et //

oo 

Définition de classe nnune classe contient des méthodes (=fonctions) et des variables

nnPas de fonctions ou de variables globales (uniquement dans des classes ou des instances)

oo 

Méthode main:

nnpublic static void main(String[] arg) oopublic oostatic ooVoid ooString nnPoint d’entrée

Remarques

 

ooClasse System

nnout est une variable de la classe System

nnprintln méthode de

nnout est une variable de classe qui fait référence à une instance de la classe PrintStream qui implémente un flot de sortie. ooCette instance a une méthode println

Remarques…

 

ooClasse: définit des méthodes et des variables

(déclaration) ooInstance d’une classe (objet)

nnMéthode de classe: fonction associée à (toute la) classe. nnMéthode d’instance: fonction associée à une instance particulière. nnVariable de classe: associée à une classe (globale et partagée par toutes les instances)

nnVariable d’instance: associée à un objet

(instancié)

ooPatience…

Applet:

 

ooApplet et WEB

nnClient (navigateur) et serveur WEB nnLe client fait des requêtes html, le serveur répond par des pages html

nnApplet:

ooLe serveur répond par une page contenant des applets ooApplet: byte code ooCode exécuté par le client

ooPermet de faire des animations avec interfaces graphiques sur  le client. 

                            ooUne des causes du succès de java.

Exemple applet

 

ooFichier :

/** 

 * Une applet  basique

 */

import java.applet.Applet; import .Graphics;

public class MonApplet extends Applet {     public void paint(Graphics g){

 g.drawString("Bienvenue en en L3 ", 50,25);

    }

}

Remarques:

 

oo 

import et package: 

nnUn package est un regroupement de classes.

nnToute classe est dans un package  nnPackage par défaut (sans nom) nnclasspath

oo 

import java.applet.*; nnImporte le package java.applet

ooApplet est une classe de ce package, ooSans importation il faudrait java.applet.Applet 

Remarques:

 

ooLa classe Applet contient ce qu’il faut pour écrire une applet

oo… extends Applet: nnLa classe définie est une extension de la classe Applet: ooElle contient tout ce que contient la classe

Applet oo(et peut redéfinir certaines méthodes (paint)) nnPatience!!

Remarques…

 

oo 

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.

oo 

Graphics g argument de paint est un objet qui représente le contexte graphique de l’applet.

nndrawString est une méthode (d’instance) qui affiche une chaîne, 

nn50, 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

 

ooL’applet doit être exécutée dans un navigateur capable d’interpréter du bytecode correspondant à des applet. ooIl faut créer un fichier HTML pour le navigateur.

Html pour l’applet

 

ooFichier :

<HTML>

<HEAD>

<TITLE> Une petite applet </TITLE>

<BODY>

<APPLET CODE='MonApplet.class' WIDTH=200 Height=50>

</APPLET>

</BODY>

</HTML>

Html

ooStructure avec balises: ooExemples: 

nn<HTML> </HTML> nnurl: 

oo<a target="_blank" href="http:// www.liafa.jussieu.f/~hf">page de hf</a> ooIci:

<APPLET CODE='MonApplet.class' WIDTH=200 Height=50>

</APPLET>

Exemple interface graphique

 

Fichier :

/** 

 * 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.setVisible(true);

    }

 public static void main(String[] args) {      creerFrame();

    }

}

Remarques

 

oo 

Importation de packages

oo 

Définition d’un conteneur top-level JFrame, implémenté comme instance de la classe JFrame

oo 

Affichage de ce conteneur

oo 

Définition d’un composant JLabel, implémenté comme instance de JLabel

oo 

Ajout du composant JLabel dans la JFrame

oo 

Définition du comportement de la Jframe sur un click du bouton de fremeture

oo 

Une méthode main qui crée la JFrame

Pour finir…

 

ooJava 1.5  et 6 annotations, types méthodes paramétrés par des types

ooTrès nombreux packages ooNombreux outils de développement

(gratuits) nneclipse, netbeans..

En plus…

 

ooEntrées-sorties

Entrée-sortie

 

 public static void main(String[] args) {

     // sortie avec printf ou      double a = 5.6d ;      double b = 2d ;

     String mul = "multiplié par" ;

     String eq="égal";

     .printf(Locale.ENGLISH,

                "%3.2f X %3.2f = %6.4f \n", a ,b , a*b);

     .printf(Locale.FRENCH,

          "%3.2f %s %3.2f %s %6.4f \n", a, mul,b, eq,a*b);

      .format(

         "Aujourd'hui %1$tA, %1$te %1$tB,"+

          " il est: %1$tH h %1$tM min %1$tS \n",

                Calendar.getInstance());

        // .flush();

Sortie

 

5.60 X 2.00 = 11.2000 

5,60 multiplié par 2,00 égal 11,2000 

Aujourd'hui mardi, 10 octobre, il est: 15 h

31 min 01 

Scanner

 

  Scanner sc = new Scanner();   for(boolean fait=false; fait==false;){       try {

         .println("Répondre o ou O:");

         String s1 (Pattern.compile("[0o]"));                 fait=true;

      } catch(InputMismatchException e) {       ();

      }   }

  if (sc.hasNextInt()){       int i= sc.nextInt();

      .println("entier lu "+i);

  }

  .println("next token :"());   sc.close();

Scanner

 

if (sc.hasNextInt()){     int i= sc.nextInt();

    .println("entier lu "+i);

}

.println("next token :"()); sc.close();

String input = "1 stop 2 stop éléphant gris stop rien";

Scanner s = new(Scanner(input).useDelimiter("\\s*stop\\s*");

        .println(s.nextInt());

        .println(s.nextInt());

        .println(s.next());         .println(s.next());

        s.close();

    }

Sortie

 

oonext token :o oo1 oo2 ooéléphant gris oorien

Les classes…

 

ooSystem

variable (static) de classe PrintStream

ooPrintStream contient print (et printf)

variable (static) de classe

InputStream ooScanner 


 

Classes et objets

 

ooI)   Introduction

ooII) Classe: membres et modificateurs ooIII) Champs: modificateurs ooIV) Vie et mort des objets,

Constructeurs ooV) Méthodes  ooVI) Exemple

I) Introduction

 

ooClasse nnRegrouper des données et des méthodes

ooVariables de classe ooMéthodes de classe

nnClasses<->type

ooObjet (ou instance) nnRésultat de la création d’un objet ooVariables d’instance ooVariables de classe

ooToute classe hérite de la classe Object

II) Classes

 

ooMembres d ’une classe sont:

nnChamps = données nnMéthodes = fonctions nnClasses imbriquées

Modificateur de classe

 

ooPrécède la déclaration de la classe nnAnnotations (plus tard…) nnpublic (par défaut package) nnabstract(incomplète, pas d’instance) nnfinal(pas d’extension) nnStrictfp (technique…)

III) Champs

 

oo 

Modificateurs

nnannotations nnContrôle d’accès

ooprivate ooprotected oopublic oopackage

nnstatic (variables de classe) nnfinal (constantes)

nn  transient nn  Volatile

oo 

Initialisations

oo 

Création par opérateur new


IV) Vie et mort des objets, constructeurs

 

ooCréation d’une instance: opérateur new ooObjet mort = plus aucune référence à cet objet -> garbage collector

nnon peut exécuter du code spécifique quand un objet est détruit : protected void finalize() throws Throwable

Références

 

ooUne variable est (en général) une référence à un objet nnType primitif: directement une valeur nnType référence : une référence à un objet

(existant ou créé par new) 

oonull : référence universelle ooconséquences: 

nndans le passage par valeur un type référence correspond à un passage par référence

nn‘a == b‘ teste si les a et b référencent le même objet nnMéthode equals qui peut être redéfinie (défaut this==obj)

Exemple

 

int i=0; int j=0; (i==j) // vrai class A{     int i=0; }

A a; A b=new A(); a=b; (a==b) // vrai b=new A(); (a==b) // faux 

 Constructeurs

 

ooAppelés par l’opérateur new pour créer un objet

nnPeuvent avoir des paramètres (avec surcharge)

nnInitialisent les objets nnConstructeur par défaut (si aucun constructeur n’est défini)

nnConstructeur de copie

Exemple:

 

public class Astre {     private long idNum;     private String nom = "<pasdenom>";     private Astre orbite = null;     private static long nextId = 0;    

    /** Creation d’une nouvelle instance of Astre */     private Astre() {         idNum = nextId ++;

    }

    public Astre(String nom, Astre enOrbite){         this();         =nom;         orbite=enOrbite;

    }

    public Astre(String nom){         this(nom,null);

    }//…

Exemples…

 

ooCopie  public Astre(Astre a){         idNum = a.idNum;         ;         orbite=a.orbite;

    }

Statique - dynamique

 

ooStatique <-> à la compilation ooDynamique <-> à l’exécution ooLe type d’une variable est déterminé à la compilation (déclaration et portée)

ooAvec la possibilité de l’héritage une variable peut être une référence sur un objet d’un autre type que le type de sa déclaration

Static

 

ooUne variable (une méthode) déclarée static est une variable (méthode) de classe: elle est associée à la classe (pas à une instance particulière). ooStatique parce qu’elle peut être créée au moment de la compilation (pas de new()). ooStatique -> les initialisations doivent avoir lieu à la compilation.

Initialisations

 

private static long nextId = 0;  

ooBloc d’initialisation   

private static long netxId = 0;

{

        idNum = nextId++;

 }

Initialisation static

 

public class Puissancedeux {     static int[] tab = new int[12];     static{         tab[0]=1;

        for(int i=0; i< tab.length-1;i++)             tab[i+1]= suivant(tab[i]);

         }

    static int suivant(int i){         return i*2;

    }    

}

V) Méthodes

 

ooModificateurs: nnAnnotations

nnContrôle d’accès (comme pour les variables) nn  abstract

nnstatic n’a pas accès aux variables d’instances nnfinal ne peut pas être remplacée nn  synchronized

nnnative (utilisation de fonctions « native ») nn  strictfp

Passage par valeur

 

public class ParamParVal {     public static void parVal(int i){         i=0;

        .println("dans parVal i="+i);

    }

} //…  int i =100;

 .println("Avant i="+i);  ParamParVal.parVal(i);

 .println("Avant i="+i);

--------------- Avant i=100 dans parVal i=0

Avant i=100

Mais…

 

ooComme les variables sont de références (sauf les types primitifs)…         public static void bidon(Astre a){         a=new Astre("bidon", null);

        .println("bidon a="+a);

    }

     public static void bidonbis(Astre a){

         a.setNom("bidon");

         a.setOrbite(null);

        .println("bidonbis a="+a);     }

Méthodes…

 

ooContrôler l’accès:

 //…

    public void setNom(String n){         nom=n;     }

    public void setOrbite(Astre a){         orbite=a;     }

    public String getNom(){         return nom;     }

    public Astre getOrbite(){         return orbite;

    }

Méthodes, remplacement…

 

     public String toString(){

        String st=idNum + "("+nom+")";         if (orbite != null)             st += "en orbite "+ orbite;         return st;       

    }

Remplace la méthode toString de la classe Object

Nombre variable d’arguments…

 

 public static void affiche(String list){          for(int i=0;i<list.length;i++)              .print(list[i]+" ");

 }

 //…

 affiche("un", "deux","trois");

Méthodes main

 

 public static void main(String[] args) {         for(int j =0; j<args.length;j++){

            .print(args[j] + " ");            

        }

Le main est le point d’accès et peut avoir des arguments:

VI) exemple: Les astres…

package exempleclasses;

/**

 *

 * @author sans

 */

public class Astre {     private long idNum;

    private String nom = "<pasdenom>";     private Astre orbite = null;     private static long nextId = 0;     /** Creates a new instance of Astre */     private Astre() {         idNum = nextId ++;

    } oo

Suite

 

   public Astre(String nom, Astre enOrbite){         this();         =nom;         orbite=enOrbite;

    }

    public Astre(String nom){         this(nom,null);

    }

    public Astre(Astre a){         idNum = a.idNum;         ;         orbite=a.orbite;

    }//…

 

    public void setNom(String n){         nom=n;     }

    public void setOrbite(Astre a){         orbite=a;     }

    public String getNom(){         return nom;     }

    public Astre getOrbite(){         return orbite;

    }

    public String toString(){         String st=idNum + "("+nom+")";         if (orbite != null)             st += "en orbite "+ orbite;         return st;       

    }

}


 

Chapitre III: Héritage

 

oo 

A) Extensions généralités nnAffectation et transtypage

oo 

B) Méthodes

nnSurcharge et signature

oo 

C) Méthodes (suite)

nnRedéfinition et liaison dynamique

oo 

D) Conséquences

nnLes variables

oo 

E) Divers nnSuper, accès, final

oo 

F) Constructeurs et héritage

A) Extension: généralités

 

ooPrincipe de la programmation objet:

ooun berger allemand est un chien

nnil a donc toutes les caractéristiques des chiens nnil peut avoir des propriétés supplémentaires nnun chien est lui-même un mammifère qui est lui-même un animal:  hiérarchie des classes nnOn en déduit:

ooHiérarchie des classes (Object à la racine) ooet si B est une extension de A alors un objet de B est un objet de A avec des propriétés supplémentaires

Extension: généralités

 

Quand B est une extension de la classe A:

nnTout objet de B a toutes les propriétés d’un objet de A (+ d’autres). nnDonc un objet B peut être considéré comme un objet A. nnDonc les variables définies pour un objet de A sont aussi présentes pour un objet de B (+ d’autres). (Mais elles peuvent être occultées)

nnIdem pour les méthodes : Les méthodes de A sont présentes pour B et un objet B peut définir de nouvelles méthodes.

nnMais B peut redéfinir des méthodes de A.

Extension de classe

 

Si B est une extension de A oopour les variables:

nnB peut ajouter des variables (et si le nom est identique cela  occultera la variable de même nom dans A)

 (occulter = continuer à exister mais "caché") nnLes variables de A sont toutes présentes pour un objet B, mais certaines peuvent être cachées

oopour les méthodes nnB peut ajouter de nouvelles méthodes nnB peut redéfinir des méthodes (même signature)

Remarques:

 

oopour les variables

ooc'est le nom de la variable qui est pris en compte (pas le type). oodans un contexte donné, à chaque nom de variable ne correspond qu'une seule déclaration.

oo(l'association entre le nom de la variable et sa déclaration est faite à la compilation)

oopour les méthodes nnc'est la signature (nom + type des paramètres) qui est prise en compte: ooon peut avoir des méthodes de même nom et de signatures différentes (surcharge)

oodans un contexte donné, à un nom de méthode et à une signature correspond une seule définition 

oo(l'association entre le nom de la méthode et sa déclaration est faite à la compilation, mais l'association entre le nom de la méthode et sa définition sera faite à l'exécution)

Extension (plus précisément)

 

ooSi B est une extension de A (class B extends A)

nnLes variables et méthodes de A sont des méthodes de B (mais elles peuvent ne pas être accessibles: private)

nnB peut ajouter de nouvelles variables (si le nom est identique il y a occultation)

nnB peut ajouter des nouvelles méthodes si la signature est différente

nnB redéfinit des méthodes de A si la signature est identique 

Remarques:

ooJava est un langage typé

nnen particulier chaque variable a un type: celui de sa déclaration

nnà la compilation, la vérification du typage ne peut se faire que d'après les déclarations (implicites ou explicites)

nnle compilateur doit vérifier la légalité des appels des méthodes et des accès aux variables:

ooa.f() est légal si pour le type de la variable a il existe une méthode f() qui peut s'appliquer à un objet de ce type

ooa.m est légal si pour le type de la variable a il existe une variable m qui peut s'appliquer à un objet de ce type

En conséquence:

 

ooUne variable déclarée comme étant de classe A peut référencer un objet de classe B ou plus généralement un objet d’une classe dérivée de A: nnun tel objet contient tout ce qu’il faut pour être un objet de classe A

ooPar contre une variable déclarée de classe B ne peut référencer un objet de classe A: il manque quelque chose!

Affectation downcast/upcast

class A{     public int i;

    // }

class B extends A{     public int j;

    // }

public class Affecter{     static void essai(){         A a = new A();

        B b = new B();

        //b=a; impossible que signifierait b.j??         a=b; // a référence un objet B

        // b=a;         b=(B)a; // comme a est un objet B ok!!

    }

}

Upcasting

 

oo 

Si  B est une extension de A, alors un objet de B peut être considéré comme un objet de A:

nnA a=new B();

oo 

On pourrait aussi écrire: nnA a=(A) new B();

oo 

l'upcasting permet de considérer un objet d'une classe dérivée comme un objet d'une classe de base

oo 

Upcasting: de spécifique vers moins spécifique (vers le haut dans la hiérarchie des classes)

oo 

l'upcasting peut être implicite (il est sans risque!)

oo 

attention

nnil ne s'agit pas réellement d'une conversion: l'objet n'est pas modifié

Downcasting

 

oo 

Si  B est une extension de A, il est possible qu'un objet de A soit en fait un objet de B. Dans ce cas on peut vouloir le considérer un objet de B nnA a=new B(); nnB b=(B)a;

oo 

Il faut dans ce cas un cast (transtypage) explicite (la "conversion" n'est pas toujours possible –l'objet référencé peut ne pas être d'un type dérivé de B)

oo 

A l'exécution, on vérifiera que le cast est possible et que l'objet considéré est bien d'un type dérivé de B

oo 

downcasting: affirme que l'objet considéré est d'un type plus spécifique que le type correspondant à sa décalration (vers le bas dans la hiérarchie des classes)

oo 

le downcasting ne peut pas être implicite (il n'est pas toujours possible!)

oo 

attention

              nnil ne s'agit pas réellement d'une conversion: l'objet n'est pas modifié

Casting

 

ooOn peut tester la classe avant de faire du "downcasting":

Base sref; Derive dref; if(sref instanceof Derive)     dref=(Derive) sref

B) Méthodes: Surcharge

 

ooMéthodes et signature:

nnSignature: le nom et les arguments avec leur type (mais pas le type de la valeur retournée)

              nnSeule la signature compte:

ooint f(int i) oochar f(int i)

                             ooLes deux méthodes ont la  même signature: c'est interdit

              nnSurcharge possible:

                             ooDes  signatures différentes pour un même nom

int f(int i) int f(double f)

ooLe compilateur détermine par le type des arguments quelle fonction est utilisée (on verra les règles…)

Surcharge

 

ooUn même nom de fonction pour plusieurs fonctions qui sont distinguées par leur signature

(Java, C++, Ada permettent la surcharge)

En C ’/’ est surchargé

 3/2 division entière -> 1

 3.0/2 division réelle -> 1,5

Surcharge

 

 public int f(int i){         return i;

    }

//    public double f(int i){ //        return ( i);

//    }

    public int f(double i){         return (int) ( i);

    }

    public int f(char c){         return c;

    }

Remarques

 

ooLa résolution de la surcharge a lieu à la compilation

ooLa signature doit permettre cette résolution oo(quelques complications du fait du transtypage:

nnExemple: un char est converti en int nnExemple: upcasting

)

C) Méthodes: Redéfinition

 

ooUn classe hérite des méthodes des classes ancêtres

ooElle peut ajouter de nouvelles méthodes ooElle peut surcharger des méthodes ooElle peut aussi redéfinir des méthodes des ancêtres.

Exemple

 

class Mere{     void f(int i){

        .println("f("+i+") de Mere");

    }

    void f(String st){

        .println("f("+st+") de Mere");

    }

}

Exemple (suite)

 

class Fille extends Mere{     void f(){ //surcharge

        .println("f() de Fille");

    }

//  char f(int i){

// même signature mais type de retour différent

//   }

    void g(){ //nouvelle méthode

        .println("g() de Fille");         f();         f(3);         f("bonjour");

    }

    void f(int i){ // redéfinition

        .println("f("+i+") de Fille");      

    }

}

Exemple

 

 public static void main(String[] args) {

        Mere m=new Mere();

        Fille f=new Fille();

        m.f(3);

        f.f(4);         m=f;

        m.f(5);         //m.g();         ((Fille)m).g();

        f.g();

    }

Résultat

 

f(3) de Mere f(4) de Fille f(5) de Fille g() de Fille f() de Fille f(3) de Fille f(bonjour) de Mere g() de Fille f() de Fille f(3) de Fille f(bonjour) de Mere

D) Conséquences

 

ooEt les variables? 

nnUn principe: ooUne méthode (re)définie dans une classe A ne peut être évaluée que dans le contexte des variables définies dans la classe A. nnPourquoi?

Exemple

 

class A{     public int i=4;     public void f(){

        .println("f() de A, i="+i);

    }     public void g(){

        .println("g() de A, i="+i);

    } }

class B extends A{     public int i=3;     public void f(){

        .println("f() de B, i="+i);         g();

    }

}

Exemple suite:

 

A a=new B();

a.f();

.println("a.i="+a.i);

.println("((B) a).i="+((B)a).i);

Donnera:

nnf() de B, i=3 nng() de A, i=4 nna.i=4

              nn((B) a).i=3

Remarques:

 

ooLa variable i de A est occultée par la variable i de B

ooLa variable i de A est toujours présente dans tout objet de B

ooLe méthode g de A a accès à toutes les variables définies dans A (et uniquement à celles-là)

ooLa méthode f de B redéfinit f. f() redéfinie a accès à toutes les variables définies dans B

E) Divers

 

oosuper nnLe mot clé super permet d’accéder aux méthodes de la super classe ooEn particulier super permet d’appeler dans une méthode redéfinie la méthode d’origine

 (exemple: super.finalize() appelé dans une méthode qui redéfinit le finalize permet d'appeler le finalize de la classe de base)

Exemple

 

class Base{     protected String nom(){         return "Base";

    } }

class Derive extends Base{     protected String nom(){         return "Derive";

    }

    protected void print(){         Base maref = (Base) this;

        .println("():"());

        .println("():"());

        .println("():"());

    } ------------- ():Derive ():Derive ():Base

Contrôle d’accès

 

ooprotected: accès dans les classes dérivées ooLe contrôle d’accès ne concerne pas la signature 

ooUne méthode redéfinie peut changer le contrôle d’accès mais uniquement pour élargir l’accès (de protected à public)

ooLe contrôle d’accès est vérifié à la compilation

Interdire la redéfinition

 

ooLe modificateur final interdit la redéfinition pour une méthode

oo(Bien sûr une méthode de classe ne peut pas être redéfinie! Mais, elle peut être surchargée)

ooUne variable avec modificateur final peut être occultée

E) Constructeurs et héritage

ooLe constructeurs ne sont pas des méthodes comme les autres: nnle redéfinition n’a pas de sens. ooAppeler un constructeur dans un constructeur:

nnsuper() appelle le constructeur de la super classe nnthis() appelle le constructeur de la classe ellemême

nnCes appels doivent se faire au début du code du constructeur

Constructeurs 

 

ooPrincipes: nnQuand une méthode d’instance est appelée l’objet est déjà créé. nnCréation de l’objet (récursivement)

1.      Invocation du constructeur de la super classe

2.     Initialisations des champs par les initialisateurs et les blocs d’initialisation

3.     Une fois toutes ces initialisations faites, appel du corps du constructeur (super() et this() ne font pas partie du corps)

Exemple

 

class X{

    protected int xMask=0x00ff;     protected int fullMask;     public X(){         fullMask = xMask;

    }

    public int mask(int orig){     return (orig & fullMask);

    } } class Y extends X{     protected int yMask = 0xff00;     public Y(){         fullMask |= yMask;

    }

}

Résultat

 

La classe Object

 

ooToutes les classes héritent de la classe Object oométhodes:

nnpublic final Class<? extends Object> getClass()  nnpublic int hashCode()  nnpublic boolean equals(Object obj) nnprotected Objectclone() throws

CloneNotSupportedException nnpublic StringtoString()

nnprotected void finalize() throws Throwable  nn(wait, notify,notfyall)

Exemple

 

class A{     int i;     int j;     A(int i,int j){         this.i=i;this.j=j;}

} class D <T>{     T i;     D(T i){         this.i=i;

    }

}

Suite

 

public static void main(String[] args) {

    A a=new A(1,2);

    A b=new A(1,2);     A c=a;     if (a==b)

        .println("a==b");     else

        .println("a!=b");     if (a.equals(b))

        .println("a equals b");     else

         .println("a not equals b");

    .println("Objet a: "+a.toString()+" classe "+a.getClass());

    .println("a.hashCode()"+a.hashCode());

    .println("b.hashCode()"+b.hashCode());

    .println("c.hashCode()"+c.hashCode());

    D <Integer> x=new D<Integer>(10);

    .println("Objet x: "+x.toString()+" classe "+x.getClass()); }

Résultat:

 

ooa!=b ooa not equals b

ooObjet a: [email protected] classe class A ooa.hashCode()26022015 oob.hashCode()3541984 ooc.hashCode()26022015 ooObjet x: [email protected] classe class D

En redéfinissant equals

 

class B{     int i;     int j;     B(int i,int j){         this.i=i;this.j=j;

    }

    public boolean equals(Object o){         if (o instanceof B)

            return i==((B)o).i && j==((B)o).j;

        else return false;

    }

}

Suite

 

        B d=new B(1,2);

        B e=new B(1,2);         B f=e;         if (d==e)

            .println("e==d");         else

            .println("d!=e");

        if (d.equals(e))

            .println("d equals e");         else

            .println("a not equals b");

        .println("Objet d: "+d.toString());

        .println("Objet e: "+e.toString());

        .println("d.hashCode()"+d.hashCode());         .println("e.hashCode()"+e.hashCode());     

oo

Résultat:

 

ood!=e ood equals e ooObjet d: [email protected] ooObjet e: [email protected] ood.hashCode()25358555 ooe.hashCode()26399554


 

Chapitre IV

 

1.Interfaces

2.    Classes imbriquées

3.    Objets, clonage

classes abstraites

 

abstract class Benchmark{     abstract void benchmark();     public final long repeat(int c){         long start =System.nanoTime();         for(int i=0;i<c;i++)             benchmark();

        return (System.nanoTime() -start);

    }     }

class MonBenchmark extends Benchmark{     void benchmark(){

    }

    public static long mesurer(int i){         return new MonBenchmark().repeat(i);

    }

}

suite

 

public static void main(String[] st){

 .println("temps="+

      MonBenchmark.mesurer(1000000));

    } 

Résultat:

temps=6981893

Interfaces

 

ooIl n'y a pas d'héritage multiple en Java: une classe ne peut être l'extension que d'une seule classe

ooPar contre une classe peut implémenter plusieurs interfaces (et être l'extension d'une seule classe)

ooUne interface ne contient (essentiellement) que des déclarations de méthodes 

ooUne interface est un peu comme une classe sans données membres et dont toutes les méthodes seraient abstraites

Héritage "multiple" en java

   

Exemple:

 

interface Comparable<T>{     int compareTo(T obj);

}

class Couple implements Comparable<Couple>{     int x,y;     //

    public int compareTo(Couple c){         if(x<c.x)return 1;         else if (c.x==x)             if (c.y==y)return 0;

        return -1;

    }

}

Remarques…

 

ooPourquoi, a priori, l'héritage multiple est plus difficile à implémenter que l'héritage simple? ooPourquoi, a priori, implémenter plusieurs interfaces ne pose pas (trop) de problèmes?

oo(Comment ferait-on dans un langage comme le C?)

Quelques interfaces…

 

ooCloneable: est une interface vide(!) un objet qui l'implémente peut redéfinir la méthode clone

ooComparable: est une interface qui permet de comparer les éléments (méthode compareTo)

oorunnable: permet de définir des "threads" ooSerializable: un objet qui l'implémente peut être "sérialisé" = converti en une suite d'octets pour être sauvegarder.

Déclarations

 

ooune interface peut déclarer: nndes constantes (toutes les variables déclarées sont static public et final)

nndes méthodes (elles sont implicitement abstract) nndes classes internes et des interfaces

Extension

 

les interfaces peuvent être étendues avec extends: ooExemple:

public interface SerializableRunnable extends Serializable, Runnable;

(ainsi une interface peut étendre de plusieurs façons une même interface, mais comme il n'y a pas d'implémentation de méthodes et uniquement des constantes ce n'est pas un problème)

Exemple

 

interface X{     int val=0;

}

interface Y extends X{     int val=1;     int ;

}

class Z implements Y{}

public class InterfaceHeritage {     public static void main(String[] st){

        .println("Z.val="+" Z.somme="+Z.somme);

        Z z=new Z();

         .println("z.val="+

                 " ((Y)z).val="+((Y)z).val+

                 " ((X)z).val="+((X)z).val);

    }    

}

--------------- Z.val=1 Z.somme=1

z.val=1 ((Y)z).val=1 ((X)z).val=0

Redéfinition, surcharge

 

interface A{     void f();     void g();

} interface B{     void f();     void f(int i);     void h();

}

interface C extends A,B{}

Rien n'indique que les deux méthodes void f() ont la même "sémantique". Comment remplir le double contrat?

Chapitre IV

 

1.      Interfaces

2.    Classes internes et imbriquées

3.    Object, clonage


Classes imbriquées  (nested classes)

 

ooClasses membres statiques nnmembres statiques d'une autre classe

ooClasses membres ou classes internes (inner classes) nnmembres d'une classe englobante

ooClasses locales nnclasses définies dans un bloc de code

ooClasses anonymes

nnclasses locales sans nom

Classe imbriquée statique 

 

oomembre statique d'une autre classe nnclasse ou interface nnmot clé static

nnsimilaire aux champs ou méthodes statiques: n'est pas associée à une instance et  accès uniquement aux champs statiques

Exemple

 

class PileChainee{

        public static interface Chainable{                 public Chainable getSuivant();                 public void setSuivant(Chainable noeud);

        }

        Chainable tete;         public void empiler(Chainable n){

            n.setSuivant(tete);             tete=n;         }

        public Object depiler(){             Chainable tmp;             if (!estVide()){                 tmp=tete;                 tete=tete.getSuivant();                 return tmp;

            }             else return null;

        }

        public boolean estVide(){             return tete==null;

        }

}

exemple (suite)

 

class EntierChainable implements PileChainee.Chainable{     int i;

    public EntierChainable(int i){this.i=i;}     PileChainee.Chainable next;

    public PileChainee.Chainable getSuivant(){         return next;

    }

    public void setSuivant(PileChainee.Chainable n){         next=n;     } 

    public int val(){return i;}        }

et le main

 

 public static void main(String[] args) {

        PileChainee p;         EntierChainable n;         p=new PileChainee();         for(int i=0; i<12;i++){             n=new EntierChainable(i);

            p.empiler(n);         }

        while (!p.estVide()){             .println(

                                                        ((EntierChainable)p.depiler()).val());

        }

    }

Remarques

 

ooNoter l'usage du nom hiérarchique avec

'.'

ooOn peut utiliser un import:

nn  import PileChainee.Chainable; nn  import PileChainee;

(Exercice: réécrire le programme précédent sans utiliser de classes membres statiques)

Classe membre

 

oomembre non statique d'une classe englobante oopeut accéder aux champs et méthodes de l'instance

ooune classe interne ne peut pas avoir de membres statiques

ooun objet d'une classe interne est une partie d'un objet de la classe englobante

Exemple

 

class CompteBanquaire{     private long numero;     private long balance;     private Action der;     public class Action{         private String act;         private long montant;

        Action(String act, long montant){             =act;             this.montant= montant;

        }

        public String toString(){             return numero"+":"+act+" "+montant;

        }

    }

Suite

 

 //…

    public void depot(long montant){         balance += montant;

        der=new Action("depot",montant);

    }

    public void retrait(long montant){         balance -= montant;         der=new Action("retrait",montant);

    }

}

Remarques

 

oonumero dans toString oothis: 

Action(…); .numero

Classe interne et héritage

 

class Externe{     class Interne{}

}

class ExterneEtendue extends Externe{     class InterneEtendue extends Interne{}

    Interne r=new InterneEtendue();

}

class Autre extends Externe.Interne{     Autre(Externe r){

        r.super();



    }

}

(un objet Interne (ou d'une de ses extensions) n'a de sens qu'à l'intérieur d'un objet Externe)

Quelques petits problèmes

 

class X{     int i;     class H extends Y{         void incremente(){i++;}

    }

}

Si i est une donnée membre de Y… c'est ce i qui est incrémenté

X.this.i et this.i lèvent cette ambiguïté.

Suite

 

class H{     void print(){}     void print(int i){}     class I{         void print(){};         void show(){             print();             H.this.print();

        // print(1); tous les print sont occultés

        }

    }

}

Classes locales

 

ooclasses définies à l'intérieur d'un bloc de code,

ooanalogue à des variables locales: une classe interne locale n'est pas membre de la classe et donc pas d'accès,

oousage: créer des instances qui peuvent être passées en paramètres

oousage: créer des objets d'une extension d'une classe qui n'a de sens que localement

(en particulier dans les interfaces graphiques)

Exemple

 

ooclasses Collections (ou Containers):

classes correspondant à des structures de données. 

nnexemples: List, Set, Queue,  Map. ooL'interface Iterator permet de parcourir tous les éléments composant une structure de données.

Iterator

 

public interface Iterator<E>{     boolean hasNext();

    E next() throws NoSuchElementException;

    void remove()throws               

                                                        UnsupportedOperationException,    

                                        IllegalStateException;

}

Exemple: MaCollection

 

class MaCollection implements Iterator<Object>{

    Object[] data;     MaCollection(int i){         data=new Object[i];

    }

    MaCollection(Object l){         data=new Object[l.length];         for(int i=0;i<l.length;i++)             data[i]=l[i];

    }

    private int pos=0;     public boolean hasNext(){         return (pos <data.length);

    }

    public Object next() throws NoSuchElementException{         if (pos >= data.length)             throw new NoSuchElementException();         return data[pos++];

    }

    public void remove(){

        throw new  UnsupportedOperationException();

    }

}

Et une iteration:

 

public class Main {

    public static void afficher(Iterator it){

        while(it.hasNext()){

            .println(());

        }     }

    public static void main(String[] args) {

        MaCollection m=new MaCollection(1,2,3,5,6,7);         afficher(m);

    }    

}

Classe locale

 

ooAu lieu de créer d'implémenter Iterator on pourrait aussi créer une méthode qui retourne un iterateur.

Exemple parcourir

 

 public static Iterator<Object> parcourir(final Object[] data){         class Iter implements Iterator<Object>{

            private int pos=0;             public boolean hasNext(){                 return (pos <data.length);

            }

            public Object next() throws NoSuchElementException{

                if (pos >= data.length)

                    throw new NoSuchElementException();                 return data[pos++];

            }

            public void remove(){

                throw new  UnsupportedOperationException();

            }         }

        return new Iter();

    }

et l'appel

 

Integer[] tab=new Integer[12];

//… afficher(parcourir(tab));

Remarques

 

ooparcourir() retourne un itérateur pour le tableau passé en paramètre. ool'itérateur implémente Iterator

nnmais dans une classe locale à la méthode parcourir

nnla méthode parcourir retourne un objet de cette classe.

oodata[] est déclaré final: 

nnmême si tous les objets locaux sont dans la portée de la classe locale, la classe locale ne peut accéder aux variables locales que si elles sont déclarées final.

Anonymat…

 

oomais était-il utile de donner un nom à cette classe qui ne sert qu'à créer un objet Iter?

Classe anonyme

 

 public static Iterator<Object> parcourir1( final Object[] data){             return new Iterator<Object>(){

            private int pos=0;             public boolean hasNext(){                 return (pos <data.length);

            }

            public Object next() throws NoSuchElementException{

                if (pos >= data.length)

                    throw new NoSuchElementException();                 return data[pos++];

            }

            public void remove(){

                throw new  UnsupportedOperationException();

            }

        };

    }

Exemple interface graphique:

 jButton1.addActionListener(new ActionListener(){     public void actionPerformed(ActionEvent evt){        jButton1ActionPerformed(evt);

    }

  });

Principe…

 

ooActionListener est une interface qui contient une seule méthode nnvoid actionPerformed(ActionEvent e)  nncette méthode définit le comportement voulu si on presse le bouton

ooIl faut que le Button jButton1 associe l'événement correspondant au fait que le bouton est pressé  l'ActionListener voulu: addActionListener

Dans l'exemple

 

1.     jButton1ActionPerformed est la méthode qui doit être activée

2.     Création d'un objet de type ActionListener:

1.     (Re)définition de ActionPerformed dans l'interface ActionListener: appel de jButton1ActionPerformed

2.    classe anonyme pour ActionListener

3.    operateur new

3.     ajout de cet ActionListener comme écouteur des événements de ce bouton jButton1.addActionListener

Chapitre IV

 

1.      Interfaces

2.    Classes imbriquées

3.    Objets, clonage

Le clonage

 

ooles variables sont des références sur des objets -> l'affectation ne modifie pas l'objet

oola méthode clone retourne un nouvel objet dont la valeur initiale est une copie de l'objet

Points techniques

 

ooPar défaut la méthode clone de Object duplique les champs de l'objet (et dépend donc de la classe de l'objet) ooL'interface Cloneable doit être implémentée pour pouvoir utiliser la méthode clone de Object

nnSinon la méthode clone de Object lance une exception CloneNotSupportedException

ooDe plus, la méthode clone est protected -> elle ne peut être utilisée que dans les méthodes définies dans la classe ou ses descendantes (ou dans le même package).

En conséquence

 

oo 

en implémentant Cloneable, Object.clone() est possible pour la classe et les classes descendantes  nnSi CloneNotSupportedException est captée, le clonage est possible pour la classe et les descendants

nnSi on laisse passer CloneNotSupportedException, le clonage peut être possible pour la classe (et les

descendants) (exemple dans  une collection le clonage sera possible si les éléments de la collection le sont) 

oo 

en n'implémentant pas Cloneable,

Object.clone() lance uniquement l’exception,  en définissant une méthode clone qui lance  une CloneNotSupportedException, le clonage n'est plus possible

Exemple

 

class A implements Cloneable{     int i,j;     A(int i,int j){         this.i=i; this.j=j;

    }

    public String toString(){         return "(i="+i+",j="+j+")";

    }

    protected Object clone()    throws CloneNotSupportedException{

        return super.clone();

    } 

}

Suite

 

        A a1=new A(1,2);         A a2=null;         try {// nécessaire!

            a2 =(A) a1.clone();

        } catch (CloneNotSupportedException ex) {             ex.printStackTrace();

        }

donnera:

a1=(i=1,j=2) a2=(i=1,j=2)

Suite

 

class D extends A{     int k;     D(int i,int j){          super(i,j);         k=0;     }

     public String toString(){

        return ("(k="+k+")"+super.toString());

     }

}

//…

     D d1=new D(1,2);      D d2=null;      try { //nécessaire             d2=(D) d1.clone();

     } catch (CloneNotSupportedException ex) {             ex.printStackTrace();

      }

     .println("d1="+d1+" d2="+d2);

}

Remarques

 

oosuper.clone();dans A est nécessaire il duplique tous les champs d'un objet de D

ooPour faire un clone d'un objet D il faut capter l'exception.

Suite

 

class B implements Cloneable{     int i,j;     B(int i,int j){         this.i=i; this.j=j;

    }

    public String toString(){         return "(i="+i+",j="+j+")";

    }     

    protected Object clone(){         try {

            return super.clone();

        } catch (CloneNotSupportedException ex) {

            ex.printStackTrace();             return null;

        }

    }

}

Suite

 

class C extends B{     int k;     C(int i,int j){         super(i,j);         k=0;     }

    public String toString(){

        return ("(k="+k+")"+super.toString());

    } }//

 B b1=new B(1,2);

B   b2 =(B) b1.clone();  C c1=new C(1,2);

C   c2 =(C) c1.clone();

Pourquoi le clonage?

 

ooPartager ou copier?

ooCopie profonde ou superficielle? nnpar défaut la copie est superficielle: 

Exemple

 

class IntegerStack implements Cloneable{     private int[] buffer;     private int sommet;     public IntegerStack(int max){         buffer=new int[max];         sommet=-1;

    }

    public void empiler(int v){         buffer[++sommet]=v;

    }

    public int dépiler(){         return buffer[sommet--];

    }

    public IntegerStack clone(){         try{

            return (IntegerStack)super.clone();         }catch(CloneNotSupportedException e){             throw new InternalError(e.toString());

        }

    }

}

Problème:

 

IntegerStack un=new IntegerStack(10); un.emplier(3); un.empiler(9)

InetegerStack deux=un.clone();

Les deux piles partagent les mêmes données…

Solution…

 

 public IntegerStack clone(){

   try{

      IntegerStack nObj = (IntegerStack)super.clone();       nObj.buffer=buffer.clone();

      return nObj;

   }catch(CloneNotSupportedException e){

        //impossible

        throw new InternalError(e.toString());

    }

  }

Copie profonde

 

public class CopieProfonde implements Cloneable{

    int val;     CopieProfonde n=null;     public CopieProfonde(int i) {         val=i;

    }

    public CopieProfonde(int i, CopieProfonde n){         =i;         this.n=n;     }

    public Object clone(){         CopieProfonde tmp=null;         try{

            tmp=(CopieProfonde)super.clone();             if(tmp.n!=null)

                tmp.n=(CopieProfonde)(tmp.n).clone();

        }catch(CloneNotSupportedException ex){}         return tmp;

    }

}

Suite

 

class essai{

    static void affiche(CopieProfonde l){         while(l!=null){

            .println(l.val+" ");             l=l.n;

        }     }

    public static void main(String[] st){

        CopieProfonde l=new CopieProfonde(0);         CopieProfonde tmp;         for(int i=0;i<10;i++){             tmp=new CopieProfonde(i,l);             l=tmp;

        }         affiche(l);

        CopieProfonde n=(CopieProfonde)l.clone();         affiche(n);

    }

}


 

Types énumérés

 

ooExemple:

nn  enum Couleur {PIQUE, CŒUR, CARREAU, TREFLE,} nndéfinit des constantes énumérées (champs static de la classe)

nnon peut définir des méthodes dans un enum nndes méthodes

oopublic static E[] values() retourne les constantes dans l'ordre de leur énumeration oopublic static E valueOf(String nom) la constante associé au nom nnun type enum étend implicitement (aucune classe ne peut étendre cette classe)

Tableaux

 

oocollection ordonnée d'éléments, ooles tableaux sont des Object ooles composants peuvent être de types primitifs, des références à des objets (y compris des références à des tableaux),

Tableaux

 

ooint [] tab= new int t[3]; nndéclaration d'un tableau d'int nninitialisé à un tableau de 3 int ooindices commencent à 0 oocontrôle de dépassement nnArrayIndexOutOfBoundException oolength donne la taille du tableau

Tableaux

 

oo 

un tableau final: la référence ne peut être changée (mais le tableau référencé peut l'être)

oo 

tableaux de tableaux:

oo 

exemple:

 public static int[][] duplique(int[][] mat){         int[][] res= new int[mat.length][];         for(int i=0;i<mat.length;i++){             res[i]=new int[mat[i].length];             for (int j=0;j<mat[i].length;j++)                 res[i][j]=mat[i][j];

        }

        return res;

    }

Tableaux

 

ooexemple:

 public static void affiche(int [][] tab){         for(int[] d:tab){

            .println();             for(int v:d)

                .print(v+" ");

        }

    }

Initialisations

 

 static int[][] pascal={

        {1},

        {1,1},

        {1,2,1},

        {1,3,3,1},        

    };

 String[] nombre= {"un", "deux", "trois", "quatre"};

Exemple

 

 for(int i=1;i<p.length;i++){       p[i]=new int[i+1];       p[i][0]=1;       for(int j=1; j<i;j++){           p[i][j]=p[i-1][j-1]+p[i-1][j];

      }       p[i][i]=1;

 }

Tableau et héritage

 

oo 

Y[] yA=new Y[3];

oo 

X[] xA=yA; //ok

oo 

xA[0]=new Y();

oo 

xA[1]=new X(); //non

oo 

xA[1]=new Z(); //non

Object

int[]

Y       Z Y[]        Z[]

Noms

 

ooil ya 6 espaces de noms nnpackage nntype nnchamps nnméthode nnvariable locale nnétiquette

Noms!?

 

package divers; class divers{

    divers divers(divers divers){         divers:

            for(;;){

            if (divers.divers(divers)==divers)

                break divers;

            }

            return divers;

    }

}

Trouver la bonne méthode

 

ooIl faut pouvoir déterminer une seule méthode à partir d'une invocation avec des paramètres

ooproblèmes: héritage et surcharge

nn(en plus des problèmes liés à la généricité)

ooprincipe trouver la méthode "la plus spécifique"

Règles

 

1.       déterminer dans quelle classe chercher la méthode

(uniquement par le nom)

2.      trouver les méthodes dans la classe qui peuvent s'appliquer

1.     sans "boxing" sans nombre variable d'arguments

2.    avec boxing

3.    avec un nombre variable d'arguments

3.      si une méthode a des types de paramètres qui peuvent être affectés à une autre des méthodes de l'ensemble -> la supprimer

4.      s'il ne reste qu'une méthode c'est elle (sinon ambiguïté sauf s'il s'agit de méthodes abstraites)

Exemple

 

void f(A a,AD2 ad2)//un void f(AD1 ad1,A a)//deux void f(ADD1 add1, AD2 s)//trois void f(A … a)//quatre

A

AD1

AD2

f(Aref, AD2ref);//a f(ADD1ref, Aref);//b f(ADD1ref, ADD2ref);//c

f(AD1ref, AD2ref);//d f(AD2ref, AD1ref);//e

               ADD1                ADD2

Exemple (suite)

 

oo(a) correspond exactement à (un) oo(b) correspond à (deux) oo(c) peut correspondre aux trois premiers mais (un) est moins spécifique que (trois) idem entre (un) et (trois) d'où résultat (trois)

oo(d) (un) et (deux) ne peuvent s'éliminer oo(e) uniquement (quatre)


 

VI) Exceptions

 

1.      Principes généraux

2.    Déclarations de throws

3.    try, catch et finally

4.    Transfert d'information: chainage, pile

5.    Assertions

Exceptions et assertions

 

ooprincipe:

nntraitement des "erreurs" ooquand une exception est lancée: nnrupture de l'exécution séquentielle nn"dépiler" les méthodes et les blocs nnjusqu'à un traite exception adapté nnerreur: oorupture du contrat:

                                              nnprécondition violée

Exceptions

 

oochecked ou unchecked

nnchecked: cas exceptionnel, mais dont l'occurrence est prévue et peut être traitée (exemple: valeur en dehors des conditions de la précondition, …) ooUne méthode qui peut lancer une checked exception doit le déclarer

nnunchecked: il n'y a rien à faire, (exemple une erreur interne de la JVM) ou une erreur à l'exécution (dépassement de tableau) ooUne méthode qui peut lancer une unchecked exception ne doit pas le déclarer

Exceptions

 

ooUne exception est un objet d'une classe dérivée de Throwable (mais, en fait, en général de Exception)

ooLe mécanisme est le même que pour tout objets:

nnon peut définir des sous-classes nndes constructeurs nnredéfinir des méthodes nnajouter des méthodes

Exceptions et traite-exceptions

 

ooUn traite exception déclare dans son entête un paramètre

ooLe type du paramètre détermine si le traite-exception correspond à l'exception 

nnmême mécanisme que pour les méthodes et l'héritage

Throw

 

ooCertaines exceptions et errors sont lancées par la JVM

ooL'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

Environnement

 

ooPar définition une exception va transférer le contrôle vers un autre contexte

nnle contexte dans lequel l'exception est traitée est différent du contexte dans lequel elle est lancée

nnl'exception elle-même peut permettre de passer de l'information par son instanciation

nnl'état de la pile au moment de l'exception est aussi transmis 

public StackTraceElement[] getStackTrace() et public void printStackTrace()

Hiérarchie:

 

.Throwable (implements .Serializable

nn 

.Error 

.AssertionError  .LinkageError  .ThreadDeath  .VirtualMachineError  .StackOverflowError 

nn 

.Exception 

.ClassNotFoundException  .CloneNotSupportedException  .IllegalAccessException  .InstantiationException  .InterruptedException  .NoSuchFieldException  .NoSuchMethodException  .RuntimeException 

                                               nnexemple: .IndexOutOfBoundsException 

Hiérarchie

 

ooThrowable: nnla super classe des erreurs et des exceptions

nnError : unchecked nnException :checked sauf RuntimeException

Exemple

 

public class MonException extends Exception{     public final String nom;     public MonException(String st) {         super("le nombre "+st+" ne figure pas");         nom=st;

    }

}

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){

            .println(e);

        }

    }

}

Résultat

 

ooDonnera:

exceptions.MonException: le nombre zwei ne figure pas

ooe.printStackTrace(); dans le try bloc donnera:

exceptions.MonException: le nombre zwei ne figure pas         at exceptions.Essai.chercher(:29)         at (:34)

Throws

 

ooprincipe: nntoute 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.

oo(les initialiseurs statiques ne peuvent donc pas générer d'exceptions)

nnLa vérification a lieu à la compilation

Clause throws

 

ooUne méthode qui appelle une méthode qui peut lancer une exception peut nnattraper (catch) cette exception dans un try bloc englobant la méthode qui peut lancer cette exception

nnattraper cette exception et la transformer en une exception déclarée dans la clause throws de la méthode

nndéclarer cette exception dans la clause throws de sa déclaration

Clause throws et héritage

 

ooSi 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

nncompatible = les exceptions de la clause throws sont dérivées de celles de la méthode d'origine nnpourquoi?

try, catch, finally

 

ooOn attrape les exceptions dans des try-bloc:

try{

 instructions

}catch(exception-type1 id1){     instructions

} catch(exception-type2 id2){

   

}finally{  instructions

}

Principe:

 

oole corps du try est exécuté jusqu'à ce qu'il termine ou qu'une exception est lancée

ooSi une exception est lancée les clauses "catch" sont examinées dans l'ordre nnla première dont le type peut correspondre à l'exception est choisie et son code exécuté

nnsi aucun catch ne peut correspondre l'exception est propagée

nnsi une clause finally figure son code est ensuite exécuté (toujours avec ou sans exception)

Exemple

 

class A extends Exception{

}

class B extends A{

} class essai{

    public static void main(String[] st){         try{

            throw new B();

        }catch (A a){

            .println(a);

//        }catch (B b){

//            .println(b);

        }finally{

            .println("finally..");

        }

    }

}

finally

 

 public boolean rechercher(String fichier,    String mot) throws StreamException{

        Stream input=null;         try{

            input=new Stream(fichier);             while(!())                 if(().equals(mot))

                    return true;             return false;         }finally{             if (input != null)                 input.close();

        }

    }

Chaînage d'exceptions

 

ooUne exception peut être causée par une autre. ooil peut être utile dans ce cas de transmettre la cause de l'exception

nnméthode:

public ThrowableinitCause(Throwable cause)

Transmission d'information

 

ooen définissant une extension de la classe et en définissant des constructeurs

oopar défaut on a les constructeurs public Throwable() 

public Throwable(String message) public Throwable(String message,

Throwable cause) 

Transmission d'information

 

ooOn peut récupérer ces informations:

public String getMessage() public Throwable getCause() ooOn peut obtenir l'état de la pile:

public void printStackTrace()  public StackTraceElement[] getStackTrace() 

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);

    }

}

Suite

 

try{       throw new A();            }catch (A a){          try {              throw new X(a);          } catch (X ex) {                 ex.printStackTrace();

           }

   }

 }

----- X: A

        at (:61) Caused by: A

        at (:58)

Remarque

 

ooà la place de:  throw new X(a);

ooon pourrait mettre throw (X) new X().initCause(a);

(pourquoi le cast (X) est nécessaire?)

Assertions

 

ooUne autre façon de garantir le contrat est de définir des assertions qui vérifient les invariants (ou les préconditions)

ooSi l'assertion n'est pas vérifiée une AssertionError est lancée oo(une option de compilation permet de vérifier ou non les assertions)

Assertions

 

ooSyntaxe: assert expr [: detail]; nnexpr est une expression boolean  nndetail est optionnel et sera passé au constructeur de AssertionError 

(une string ou un Throwable) ooExemple:

 assert i!=0 : "i ="+i+" i devrait être non nul";

Assertions

 

oopar défaut les assertions ne sont pas évaluées

oopour les évaluer: nn-enableassertions:nom_du_package nn-disableassertions:nom_du_package avec en argument le ou les paquetages concernés.


 

Principes de base

 

ooDes composants graphiques 

(exemple: JFrame, JButton …)

ooHiérarchie de classes

ooDes événements et les actions à effectuer 

(exemple presser un bouton) oo(Et d'autres choses…)

Principes

 

ooDéfinir les composants (instance de classes) ooLes placer à la main (layout Manager) dans un JPanel ou un content pane ou en utilisant des outils comme eclipse ou netbeans

ooDéfinir les actions associées aux événements (Listener) et les associer aux composants graphiques

Principes

 

ooDans une interface graphique, le programme réagit aux interactions avec l'utilisateur

ooLes interactions génèrent des événements

ooLe programme est dirigé par les événements (event-driven)

Afficher…

 

ooPour pouvoir être affiché, il faut que le composant soit dans un top-level conteneur:

(JFrame, JDialog et JApplet) ooHiérarchie des composants: arbre racine top-level

Exemple

 

oo  Correspond à la hiérarchie   

Le code

 

import .*; 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.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

 

ooDans un système d'interface graphique: nnQuand l'utilisateur presse un bouton, un "événement" est posté et va dans une boucle d'événements 

nnLes événements dans la boucle d'événements sont transmis aux applications qui se sont enregistrées pour écouter. 

Evénements

 

ooChaque composant génère des événements: nnPresser un JButton génère un ActionEvent

(système d'interface graphique)

ooCet ActionEvent contient des infos (quel bouton, position de la souris, modificateurs…)

nnUn event listener (implémente ActionListener)  oodéfinit une méthode actionPerformed  ooS'enregistre auprès du bouton addActionListener

nnQuand le bouton est "clické",l'actionPerformed sera exécuté (avec l'ActionEvent comme paramètre)

Exemples Buttons

   

Le code:

 

ooUn JButton ooUn JLabel

ooImplementer ActionListener

nnactionPerfomed définit ce qui se passe quand le bouton est cliqué

ooPlacer le bouton et le label

Code:

 

import .*; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JButton; import javax.swing.Jcomponent; import .Toolkit; import .BorderLayout; import .event.ActionListener; import .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.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…

 

                                                                                                                         POO-L3 H. Fauconnier                                              245


 

Un exemple

 

ooUn traceur de fonctions nnUne interface graphique swing 

 

Organisation

 

ooGrapheSwing contient un

GraphePanel extension de Jpanel nnGraphePanel méthode paintComponent qui affiche le graphe de la fonction ooGraphe est la classe contenant le gaphe et définissant une méthode draw pour l'affichage ooCette méthode appelle tracer de la classe abstraite Traceur 

                                              nnFonctionTraceur étend Traceur

                                                                                                                      POO-L3 H. Fauconnier                                                248

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();

        p.setGridSpacingX(0.5);

        p.setGridSpacingY(0.5);

        p.setTitle("Une parabole et une sinusoide");         Graphe graphe = new Graphe(p);         (new Parabole());         (new FonctionTraceur() {             public double getY(double x) {                 return (x);

            }

            public String getName() {                 return "Sin(x)";

            }

        });

        return graphe;

    }

                                                                                                                      POO-L3 H. Fauconnier                                                249

Composants

 

ooModèle Vue Contrôleur

 

Préliminaires…

 

ooLightweight et heavyweight composants nnDépendent ou non du système d’interface graphique ooLightweight écrit en Java et dessiné dans un heavyweight composant- indépendant de la plateforme

ooLes heavyweight composants s’adressent directement à l’interface graphique du système

nn(certaines caractéristiques dépendent du « look and feel »).

Look and feel

 

ooLook 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

 

ooAttention au « modèle, contrôleur, vue » en cas de multithreading: nnTous les événements de dessin de l’interface graphiques sont dans une unique file d’event-dispatching dans une seule thread. nnLa 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

 

ooSwing prend en charge la gestion des composants qui sont dessinés en code

Java (lightweight) ooLes composants AWT sont eux liés aux composants natifs (heavyweight)

ooSwing dessine le composants dans un canevas AWT et utilise le traitement des événements de AWT

Suite

Les  threads ooMain application thread ooToolkit thread ooEvent dispatcher thread ooToutes Les opérations  d'affichage ont lieu dans une seule thread l'EDT

Principes

 

ooUne tâche longue ne doit pas être exécutée dans l'EDT

ooUn 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

 

ooNormalement 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 VII

 

1.Principes généraux

2.    Types génériques imbriqués

3.    Types paramètres bornés

4.    Méthodes génériques

Principes

 

ooParamétrer une classe ou une méthode par un type:

nnune pile de X

ooEn java toute classe étant dérivée de Object, cela permet d'obtenir une forme de généricité sans contrôle des types

nnune pile d'Object

ooLa généricité en Java est un mécanisme

"statique" assez complexe oola généricité existe dans d'autres langages (exemple C++ et Ada) (mais de façon différente)

Exemple: File

 

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;

    }

}

Suite

 

class File<E>{     protected Cellule<E> tete;     protected Cellule<E> queue;     private int taille=0;     public boolean estVide(){         return taille==0;

    }

    public void enfiler(E item){         Cellule<E> c=new Cellule<E>(item);         if (estVide())             tete=queue=c;         else{

            queue.setSuivant(c);             queue=c;         }         taille++;

    } //..

suite

 

   public E defiler(){         if (estVide())             return null;         Cellule<E> tmp=tete;         tete=tete.getSuivant();

        taille--;

        return tmp.getElement();

    }

     public int getTaille(){         return taille;

    }

}

Usage

 

Cellule<Integer> cel=new Cellule<Integer>(23);

File<Integer> fi=new File<Integer>();

File<String> fs=new File<String>();

File<Object> fobj=new File<Object>();

String[] st={"zéro","un","deux",

            "trois","quatre","cinq"}; for(int i=0;i<st.length;i++){      fs.enfiler(st[i]);      fi.enfiler(i);

 }

Remarques

 

ooUne déclaration de type générique peut avoir plusieurs paramètres:

nnMap<K,V>

ooContrôle de type nnfs.enfiler(4) est refusé à la compilation


Types génériques, pourquoi?

 

ooVérification de type:

 List myIntList = new LinkedList();   (new Integer(0)); 

 Integer x = (Integer) myIntList.iterator().next();  Et:

 List<Integer> myIntList = new LinkedList<Integer>(); (new Integer(0)); 

 x=myIntList.iterator().next(); 

Invocation et type en paramètre

 

public interface List <E>{                 void add(E x);                  Iterator<E> iterator();

}

public interface Iterator<E>{ E next();    boolean hasNext();}

List<Integer> pourrait correspondre à (comme en C++):

public interface IntegerList {      void add(Integer x);      Iterator<Integer> iterator();

}

Mais… une déclaration d'un type générique crée un vrai type (qui est compilé comme un tout) et il n'y a pas de type pour List<Integer>

Typage

 

ooUne invocation ne crée pas un nouveau type:

nn(fs.getClass()==fi.getClass()) est vrai nnla classe est ici File

nnil s'agit surtout d'un contrôle (effectué à la compilation)

nnà l'exécution fi n'a plus aucune information sur quelle invocation a permis sa construction


Conséquences

 

ooAucune instanciation n'est possible pour un type argument nnDans l'exemple: E v=new E();  est impossible

nnPas de tableau de E

Exemple

 

public E[] toArray(File<E> f){

      E[] tab=new E[f.getTaille()]; //non

      for(int i=0;i<f.getTaille();i++)                     tab[i]=f.defiler();

}

ooComment construire un tableau sans connaître le type de base? ooLa classe Array et la méthode

Array.newInstance() permettraient de résoudre ce problème (mais sans contrôle de type)  ooOn peut aussi utiliser la classe Object.

Object

 

 public static <E> Object[] toArray(File<E> f){   Object[] tab=new  Object[f.getTaille()];   for(int i=0;i<f.getTaille();i++)       tab[i]=f.defiler();   return tab;

}

mais on perd l'avantage du contrôle de type.

Contrôle du type

 

ooPourtant, on peut passer un objet d'un type avec paramètre à une méthode. ooComment se fait le passage des paramètres? nnle compilateur passe le type le plus général (Object)  et utilise le cast pour assurer le contrôle du typage.

Chapitre VII

 

1.Principes généraux

2.Types génériques imbriqués

3.    Types paramètres bornés

4.    Méthodes génériques

Types génériques imbriqués

 

public class FileSimpleChainageb <E>{     public class Cellule{         private Cellule 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;         }//

Suite

 

   public Cellule getSuivant(){             return suivant;

        }

   public void setSuivant(Cellule s){             this.suivant=s;

        }     }

    protected Cellule tete;     protected Cellule queue;     private int taille=0;     public boolean estVide(){         return taille==0;

    }

    public int getTaille(){         return taille;

    }

Fin…

 

    public void enfiler(E item){         Cellule c=new Cellule(item);         if (estVide())             tete=queue=c;         else{             queue.setSuivant(c);             queue=c;         }         taille++;     }     public E defiler(){         if (estVide())             return null;         Cellule tmp=tete;         tete=tete.getSuivant();         taille--;         return tmp.getElement();

    }

}

Chapitre VII

 

1.      Principes généraux

2.    Types génériques imbriqués

3.    Types en paramètres bornés

4.    Méthodes génériques


Sous-typage

 

List<String> ls = new ArrayList<String>(); List<Object> lo = ls; //1 (new Object());//2 String s = (0); //3 !

Si A est une extension de B, F<A> n'est pas une extension de F<B>:

//1 est interdit

Pour les tableaux:

nnsi A est une extension de B un tableau de A est une extension de tableau de B. 

              nn//1 est autorisé, mais ensuite //2 est interdit

Joker '?'

 

void printCollection(Collection<Object> c) {  for (Object e : c) { .println(e);}

}

Ne fonctionne pas avec une Collection<Integer> Une collection de n'importe quoi ('?')

void printCollection(Collection<?> c) {   for (Object e : c){ .println(e);}

}

est possible (n'importe quoi est un objet). Mais

Collection<?> c = new ArrayList<String>(); c.add(new Object()); // erreur compilation

Mais

 

ooCe n'est pas suffisant… nnOn peut vouloir borner le type paramètre: comparable est une interface générique qui indique la possibilité de comparer des objets

class valeur implements Comparable<Valeur>{..}

nnUne SortedCollection est construite sur des classes E qui implémentent Comparable<E> d'où:

interface SortedCollection<E extends Comparable<E>>{}


Exemple

 

    static double somme(List<Number> l){         double res=0.0;         for(Number n:l)             res+=n.doubleValue();

        return res;

    }

    public static void main(String[] st){

        List<Integer> l= new ArrayList<Integer>();

        for(int i=0;i<10;i++)l.add(i);         double s=somme(l); //incorrect

    }

Mais

Type paramètre borné

ooAu moins un number:

ooList<? extends Number> une liste constituée de n'importe quel type dérivé de Number

 static double somme2(List<? extends Number> l){         double res=0.0;         for(Number n:l)             res+=n.doubleValue();         return res;

    }

Types bornés

 

ooList<? extends Number>

nnindique que le type doit au moins être un Number (tout type qui dérive de Number) nnborné par le bas : au moins un Number

ooOn peut aussi imposer que le type soit une superclasse d'un autre type nn  List<? super Integer>

nnborné par le haut : au plus un Integer

(super-classe de Integer)

Sous-typage

 

ooList<?> est une super classe de

 List<Object>

Et:

ooList<?> nn  List<? extends Number> ooList<Number>

ooList<? extends Integer> nn  List<Integer>

Types en paramètres bornés

 

ooExemple: nnSortedCollection est composée d'éléments du type E et ces éléments peuvent être comparés. 

Mais <E extends comparable<E>> est trop fort: il suffit que E extends Comparable<T> pour T égal à E ou T superclasse de E

(si E extends Comparable<Object> a fortiori on peut comparer les éléments de E) d'où:

<E extends Comparable<? super E> >

Mais attention

 

 File<?> str=new File<String>();

 str.enfiler("un");

provoque une erreur à la compilation:

enfiler(capture of ?) in <capture of ?> cannot be applied to (.String)

de même:

File<? extends Number> num=new File<Number>(); num.enfiler(Integer.valueOf(12));

en effet File<? extends Number> peut être par exemple une File d'un type dérivé de Number.

Par contre:

File<? super Number> num=new File<Number>(); num.enfiler(Integer.valueOf(12)); 

est correct

Joker '?'

 

enfiler(capture of ?) in <capture of ?

> cannot be applied to (.String) oosignifie que le type de str est File<capture of ?> qui n'est pas compatible avec String

Quelques explications

 

oo? peut correspondre à n'importe quel type enfiler(a) où a est de type A ne peut fonctionner si le type correspondant à ? est dérivé de A

oode même ?  dans <? extends X> ne peut fonctionner car si ? est Y dérivé de X il faut un paramètre d'une classe dérivée de Y

oopar contre ? dans <? super X> ne pouvant correspondre qu'à une classe "avant" X, tout

Z dérivé de X fonctionne

Mais

 

ooinversement pour la valeur retournée

(avec la méthode défiler par exemple)

nnpour <?> quelque soit le type X correspondant on peut l'affecter à Object et à X

nnidem pour <? extends X> nnmais pour <? super Y> si Z correspond à ? pour T  un type quelconque on ne peut savoir si T peut être affecté par un Z

Chapitre VII

 

1.      Principes généraux

2.    Types génériques imbriqués

3.    Types paramètres bornés

4.    Méthodes génériques

Méthodes génériques

 

ooSupposons que l'on veuille convertir en tableau une File de E

nnon a vu précédemment que l'on ne pouvait ni instancier un objet E ni créer un tableau de E

nnon peut cependant passer un tableau de la taille appropriée à une méthode qui retourne ce tableau:

enTableau1

 

 public E[] enTableau1(E[] tab){       Object[] tmp = tab;       int i=0;

      for(Cellule<E> c= tete; c != null && i< tab.length;       c=c.getSuivant())

           tab[i++] = c.getElement();       return tab;       

    } ooenTableau1 est une nouvelle méthode de File:

 File<String> fs=new File<String>();  String[]  u;

 u=fs.enTableau1(new String[fs.getTaille()]);

enTableau

 

ooMais, nnil faut que le tableau passé en paramètre soit un tableau de E, alors qu'un tableau d'une super-classe de E devrait fonctionner (si F est une superclasse de E un tableau de F peut contenir des objets E).



nnavec une méthode générique:

enTableau

    public <T> T[] enTableau(T[] tab){

        Object[] tmp = tab;

        int i=0;

        for(Cellule<E> c= tete; c != null && i< tab.length;         c=c.getSuivant())             tmp[i++] = c.getElement();         return tab;        

    }


oo   la déclaration impose que le type du tableau retourné soit du type du tableau de l'argument oo    Notons que tmp est un tableau d'Object ce qui est nécessaire


pour le getSuivant

oo 

de E (à l'exécution il peut y avoir une erreur).

oo 

Notons enfin que 'T' ne sert pas dans le corps de la méthode.

Notons que normalement il faudrait que T soit une superclasse

Remarque

 

 public <T> T[] enTableaubis(T[] tab){            int i=0;

        for(Cellule<E> c= tete; 

     c != null && i< tab.length;             c=c.getSuivant())             tab[i++] = (T)c.getElement();         return tab;

 }

ooprovoque un warning " uses unchecked or unsafe operations". oo(l'"effacement" ne permet pas de vérifier le type)

Avec Reflection…

 

ooUne autre solution peut être, si on veut créer un vrai tableau, d'utiliser Array.newInstance de la classe: .reflect

Exemple avec Reflection

 

 public E[] enTableau2(Class<E> type){         int taille = getTaille();

        E[] arr=(E[])Array.newInstance(type,taille);         int i=0;

        for(Cellule<E> c= tete; c != null && i< taille;         c=c.getSuivant())

            arr[i++] = c.getElement();         return arr;

 }

ooon crée ainsi un tableau de "E"  oo"unchecked warning": le cast (E[]) n'a pas le sens usuel oopour fs déclaré comme précédemment on aura:  String[] u=fs.enTableau2(String.class); //ok  Object[] v=fs.enTableau2(Object.class); //non

oocar le type doit être exact

Avec une méthode générique

 

   public <T> T[] enTableau3(Class<T> type){         int taille = getTaille();

        T[] arr=(T[])Array.newInstance(type,taille);         int i=0;

        Object[] tmp=arr;         for(Cellule<E> c= tete; c != null && i< taille;         c=c.getSuivant())             tmp[i++] = c.getElement();         return arr;

    }

Inférence de type

 

ooComment invoquer une méthode générique? ooExemple:

 static <T> T identite(T obj){         return obj;

    }

Invocations

 

ooOn peut explicitement préciser le type:

        String s1="Bonjour";

        String s2= Main.<String>identite(s1); ooMais le compilateur peut, lui-même, trouver le type le plus spécifique:

        String s1=identite("Bonjour");ooOn aura:

        Object o1=identite(s1);          //ok         Object o2=identite((Object)s1);  //ok         s2=identite((Object) s1);        //non!!!

        s2=(String)identite((Object) s1);//ok

Comment ça marche?

 

oo 

Mécanisme de l'effacement ("erasure") 

oo 

Pour chaque type générique il n'y a qu'une classe:

Cellule<String> et Cellule<Integer> ont la même classe

oo 

Effacement:

nnCellule<String> -> Cellule ooCellule est un type brut

nnPour une variable type:

            oo<E> -> Object 

            oo<E extends Number> -> Number

oo 

Le compilateur remplace chaque variable type par son effacement

Comment ça marche?

 

ooSi le résultat de l'effacement du générique ne correspond pas à la variable type, le compilateur génère un cast: nnpar effacement le type variable de File<E> est Object

nnpour un "defiler" sur un objet File<String> le compilateur insère un cast sur String

Comment ça marche?

 

ooA cause de l'effacement, rien de ce qui nécessite de connaître la valeur d'un argument type n'est autorisé. Par exemple: nnon ne peut pas instancier un type en paramètre: pas de new T() ou de new T[]

nnon ne peut pas utiliser instanceof pour une instance de type paramétré

nnon ne peut pas créer de tableau sur un type paramétré sauf s'il est non borné new List<String>[10] est interdit mais new List<?>[10] est possible.

Comment ça marche?

 

ooles "cast" sont possibles mais n'ont pas la même signification que pour les  types non paramétrés:

nnle cast est remplacé par un cast vers le type obtenu par effacement et génère un "unchecked warning" à la compilation.  nnExemple: 

ooon peut caster paramètre File<?> vers un File<String> pour un enfiler (ce qui génère le warning)

ooA l'exécution si le type effectif est File<Number> cela passe… mais le defiler provoquera un ClassCastException.

Comment ça marche?

 

ooExemple:

        List<String> l=new ArrayList<String>();

        Object o=identite(l);

        List<String> l1=(List<String>)o;// warning

        List<String> l2=(List)o;//warning

        List<?> l3=(List) o; //ok 

        List<?> l4=(List<?>)o; //ok

Application: surcharge

 

ooavoir la même signature s'étend aux méthodes avec variables types

oomême signature pour des variables types = même type et même borne

(modulo bien sûr renommage!) oosignatures équivalentes par annulation: mêmes signatures où l'effacement des  signatures sont identiques

Surcharge

 

class Base<T>{     void m(int x){};     void m(T t){};     void m(String s){};

    <N extends Number> void m(N n){};     void m(File<?> q){};

} ----- m(int) m(Object) m(String) m(Number) m(File)

Et héritage…

 

ooexemple:

class D<T> extends Base<T>{     void m(Integer i){} //nouveau     void m(Object t){}  // redéfinit m(T t)     void m(Number n){}   // redéfinit m(N n)

}


 

Plan

 

ooA) String

ooB) Expressions régulières ooC) Chaînes et tableaux (char et byte) ooD) Chaînes modifiables

String

 

ooUne String est une chaîne de caractères non modifiable

nn(attention les caractères en java sont en Unicode) ooStringBuilder et StringBuffer sont des classes de chaînes qui peuvent être modifiées. ooString StringBuilder et StringBuffer implémentent l'interface CharSequence

CharSequence

 

ooInterface:

nnchar charAt(int index) 

          Retourne le char the char en position index.  nnint length() 

          Retourne la longueur de la séquence.  nnCharSequencesubSequence(int start, int end) 

          Retourne une sous CharSequence nnStringtoString() 

          Retourne la string correspondant à la séquence 

String

 

ooDe nombreuses méthodes pour manipuler les chaines (attention un objet String n'est pas modifiable)

nnconstructeurs

nnindexOf, lastIndexOf retourne la première

(dernière) position nnconversion valueOf( valeur d'un type primitif) nnreplace, trim, split  nntoLowerCase, toupperCase() nn…

Comparaison

 

oo'==' ne compare les contenus, MAIS deux littéraux ayant le même contenu sont identiques:

     String st1="bonjour";

   String st2="bonjour" if(st1==st2).println("égal");

   else .println("différent");

donnera égal

La méthode intern permet de retourner un String de même référence

Manipulations sur les chaînes

 

oochar charAt(int index)

ooint compareTo(String anotherString) comparaison lexicographique

ooboolean contains(CharSequence s)  ooboolean equals(Object anObject)  ooint length()

ooboolean matches(String regex) 

oobooleanregionMatches(boolean ignoreCase, int toffset,

String other, int ooffset, int len) oobooleanregionMatches(boolean ignoreCase, int toffset,

String other, int ooffset, int len)  ooStringreplace(CharSequence target,

CharSequence replacement)   ooString[] split(String regex) ooStringtrim() 

Exemples

 

   String string = "Madam, I am Adam";

    boolean  b = string.startsWith("Mad");  // true     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.*");

Exemple: remplacement

 

 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();  }

Exemple

 

    Strinf st1="bonjour";

    String st3=new String("bonjour");     if(st1==st3).println("égal");     else .println("différent");     String st4=st3.intern();     if(st1==st4).println("égal");     else .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)

Expressions régulières

 

ooLes expressions régulières permettent de définir un motif (pattern) objet de la classe Pattern. ooUn motif est créé par la méthode compile nnPattern pat = Pattern.compile("[a-z]*")

Expressions régulières

oola syntaxe des expressions régulières (rationnelles) est assez large:

nn 

caractères ooexemples \t , a ,\xhh ,

nn 

classes de caractères ooexemples [a-z], [^a-z], [a-z&&0-9]

nn 

classes de caractères prédéfinis ooexemples . , \d, \D, \w, \W, \s, \S

nn 

classes prédéfinies ASCII, Character ooexemples \p{Blank}, \p{javaLowerCase}

nn 

bords ooexemples  ^, $,\b (bord d'un mot)

nn 

itérations ooexemples [a-z]?, [1-9][0-9]+, \W*,

nn 

capture et restitution oo(X) définit la capture de X oo\n correspond à la n-ième capture

Recherche de motif

 

ooPrincipe:

Pattern pat=Pattern.compile(regex); Matcher matcher=pat.match(entrée);

boolean trouve = ();

la classe Matcher contient les méthodes pour chercher (find()), retourner la sousséquence trouvée (group())

Exemple: rechercher

 

 String patternStr = "b";

 Pattern pattern = Pattern.compile(patternStr);    

 CharSequence inputStr = "a b c b";

 Matcher matcher = pattern.matcher(inputStr);  boolean matchFound = ();    // true      String match = matcher.group();         // b      int start = matcher.start();            // 2  int end = ();                // 3  matchFound = ();            // true 

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 = ())) {

     String replaceStr = matcher.group();      replaceStr = replaceStr.toUpperCase();      matcher.appendReplacement(buf, replaceStr);

 }

 matcher.appendTail(buf);  String result = buf.toString(); 

// AB12 cd EFG34 

Chaines et tableaux de char

 

ooUne string n'est pas un tableau de char mais on peut passer de l'un à l'autre

ooconstructeurs String(char[] value) 

String(char[] value, int offset, int count)  oométhode:

void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

Chaînes et tableaux de byte

 

ooles chaines contiennent des caractères codés en UTF-16.  ooOn peut convertir ces caractères en byte suivant un codage

ooDe même on peut coder des bytes en caractères unicode.

oo(par exemple un byte Latin-1 se code en

Unicode en ajoutant un octet de 0)

Charset

 

oola classe Charset permet de faire correspondre des séquences d'unicode et des bytes. En standard: nnUS-ASCII  nnISO-8859-1  nnUTF-8 nnUTF-16BE nnUTF-16LE nnUTF-16

tableau de byte

 

oo 

constructeurs: nnString(byte[] bytes) (conversion suivant le jeu de caractère par défaut)

nn  String(byte[] bytes, int offset, int length)  nn  String(byte[] bytes, String charsetName) 

(suivant le charset)

nn  String(byte[] bytes, int offset, int length,

String charsetName) (suivant le charset)

oo 

méthodes

nn  byte[]getBytes() 

nn  byte[]getBytes(String charsetName) 

Exemple:

 

 try {

    // Conversion Unicode en x-MacRoman

    String string = "abcéçùà\u563b";     .println(string);

    byte[] mac = string.getBytes("x-MacRoman");

    .println(new String(mac));

    // Conversion x-MacRoman vers Unicode     string = new String(utf8, "x-MacRoman");     .println(string);

} catch (UnsupportedEncodingException e) {

} ooabcéçùà? ooabcŽ??ˆ? ooabcéçùà? 

Exemples:

 

 for(String nom: Charset.availableCharsets().keySet())

            .println(nom); affichera la liste des jeux de caractères:

oo 

EUC-JP

oo 

EUC-KR

oo 

GB18030

oo 

GB2312

oo 

GBK

oo 

IBM-Thai

oo 

IBM00858

oo 

IBM01140

oo 

IBM01141

oo 

IBM01142

oo 

IBM01143

oo 

IBM01144

oo 

IBM01145

oo 

IBM01146

oo 

IBM01147

oo 

IBM01148

oo 

Exemple

 

    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(("une chaîne"));

        // Convertit ISO-LATIN-1 bytes en string.

        CharBuffer cbuf = decoder.decode(bbuf);

        String s = cbuf.toString();

    } catch (CharacterCodingException e) {     }

Exemple:

 

 try {

        // Conversion vers ISO-LATIN-1 de bytes         ByteBuffer bbuf = encoder.encode(("une chaîne"));

        // Conversion de ISO-LATIN-1 vers bytes 

        CharBuffer cbuf = decoder.decode(bbuf);

        String s = cbuf.toString();

        .println(s);

    } catch (CharacterCodingException e) {     }

StringBuilder

 

ooLa classe StringBuilder peut contenir des chaînes qui peuvent être modifiées. ooIl s'agit d'une structure de données dynamique: la taille de la chaîne est augmentée automatiquement

ooLa taille initiale peut être précisée dans le constructeur (16 par défaut). oo(Il existe aussi une classe StringBuffer qui est "thread-safe") oométhodes insert, append, delete


 

Principes généraux

 

ooentrées sorties nnstreams dans

nnchannels dans ("n" pour non-blocking) oostreams: séquences de données ordonnées avec une source (stream d'entrée) ou une destination (stream de sortie)

oochannels et buffer. Buffer contient les données et le channel correspond à des connections

Streams

 

ooDeux grandes sortes de Stream

nncharacter Streams contiennet des caractères UTF-16

nnbyte Streams contiennent des octets

ooCharacter versus byte nnimput ou output stream pour les byte nnreader, writer pour les character nndeux hiérarchies qui se correspondent

Hiérarchie

 

.InputStream (implements .Closeable)  .ByteArrayInputStream  .FileInputStream  .FilterInputStream  .BufferedInputStream 

.DataInputStream (implements .DataInput)  .LineNumberInputStream  .PushbackInputStream

.ObjectInputStream (implements .ObjectInput, .ObjectStreamConstants

.PipedInputStream  .SequenceInputStream  .StringBufferInputStream

Hiérarchie

 

.OutputStream (implements .Closeable, .Flushable

.ByteArrayOutputStream  .FileOutputStream  .FilterOutputStream  .BufferedOutputStream 

.DataOutputStream (implements .DataOutput)  .PrintStream (implements .Appendable, .Closeable

.ObjectOutputStream (implements .ObjectOutput, .ObjectStreamConstants)  .PipedOutputStream

Hiérachie…

 

.Reader (implements .Closeable, .Readable)  .BufferedReader  .LineNumberReader

.CharArrayReader  .FilterReader  .PushbackReader

.InputStreamReader  .FileReader

.PipedReader  .StringReader

Hiérarchie

 

.Writer (implements .Appendable, .Closeable, .Flushable)  .BufferedWriter  .CharArrayWriter  .FilterWriter  .OutputStreamWriter  .FileWriter

.PipedWriter  .PrintWriter  .StringWriter

Streams d'octets

 

ooClass InputStream

(toutes ces méthodes peuvent lancer IOEXception) nnabstract  int read() lit un octet

nnint read(byte[] b) lit et écrit dans b, (le nombre d'octets lus dépend de b et est retourné 

nnint read(byte[] b, int off, int len) nnlong skip(long n) 

nnint available() n d'octets pouvant être lus nnvoid mark(int readlimit) et  void reset() pose d'une marque et retour à la marque nnvoidclose() 

Stream d'octets

 

ooOutputStream

(toutes ces méthodes peuvent lancer

IOEXception) nnabstract  void write(int b) écrit un octet nnvoid write(byte[] b) 

nnvoid write(byte[] b, int off, int len)  nnvoidclose()  nnvoidflush() 

Exemples

 

   public static int compteIS(String st)    throws IOException{         InputStream in;         int n=0;

        if (st==null);         else

            in= new FileInputStream(st);         for(; () != -1;n++);         return n;

    }

Exemples

 

    public static void trOS(String f, char from, char to){         int b;

        OutputStream out=null;

        try{

          if(f==null) ;            else

            out=new FileOutputStream(f);             while((b= ())!=-1)                 out.write(b==from? to:b);

            out.flush();             out.close();

        }catch(IOException ex){                 ex.printStackTrace();

        }

    }

Reader-Writer

 

ooReader et Writer sont les deux classes abstraites pour les streams de caractères: nnle 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

Reader

 

ooessentiellement les mêmes méthodes que pour InputStream: 

nnint read()  nnint read(char[] cbuf) 

nnabstract  int read(char[] cbuf, int off, int len) nnint read(CharBuffer target)  nnboolean ready() si prêt à lire nnvoidreset() 

nnvoidmark(int readAheadLimit)  nnbooleanmarkSupported()  nnlongskip(long n) 

Writer

 

oosimilaire à OutputStream mais avec des caractères au lieu d'octets.

              nnvoid write(char[] cbuf) 

nnabstract  void write(char[] cbuf, int off, int len)  nnvoid write(int c) nnvoid write(int c)  nnvoid write(String str)

nnvoid write(String str, int off, int len) nnWriterappend(char c)  nnWriterappend(CharSequence csq) 

nnWriterappend(CharSequence csq, int start, int end)  nnabstract  void close() nnabstract  void flush() 

Exemples

 

    public static int compteR(String st)   throws IOException{

      Reader in;       int n=0;       if (st==null)

       in=new InputStreamReader();

      else

       in= new FileReader(st);       for(; () != -1;n++);

      return n;

    }

Exemples

 

    public static void trWr(String f, char from, char to){         int b;

        Writer out=null;

        try {             if(f==null) 

                out= new OutputStreamWriter();

            else

                out=new FileWriter(f);             while((b= ())!=-1)                     out.write(b==from? to:b);             out.flush();             out.close();

       }catch(IOException e){.println(e);}           }

Remarques

 

ooles streams standard et

sont des streams d'octets ooInputStreamReader permet de passer de InputStream à Reader

et sont des PrintStream (obsolète à remplacer par la version caractère PrintWriter)


InputStreamReader   et OutputStreamWriter 

 

oo 

conversion entre caractères et octets, la conversion est donnée par un charset

oo 

Constructeurs: 

nnInputStreamReader(InputStream in)  nnInputStreamReader(InputStream in, Charset cs)  nnInputStreamReader(InputStream in, String charsetName)  nnOutputStreamWriter(OutputStream out)  nnOutputStreamWriter(OutputStream out, Charset cs) 

nnOutputStreamWriter(OutputStream out,

CharsetEncoder enc) nnOutputStreamWriter(OutputStream out,

String charsetName) 

Autres classes

 

ooFileInputStream  ooFileOutputStream  ooFileReader  ooFileWriter 

ooCes 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)

Quelques autres classes

 

oo 

Les filtres  nnFilterInputStream  nnFilterOutputStream  nnFilterReader  nnFilterWriter 

oo 

Buffered

nnBufferedInputStream  nnBufferedOutputStream  nnBufferedReader  nnBufferedWriter 

oo 

Tubes

nnPipedInputStream  nnPipedOutputStreamnnPipedReader   nnPipedWriter 

Exemple d'un filtre

 

class conversionMaj extends FilterReader{     public conversionMaj(Reader in){

        super(in);

    }

    public int read() throws IOException{

        int ();

        return(c==-1?c:Character.toUpperCase((char)c));

    }

    public int read(char[] buf, int offset, int count)throws

IOException{         int (buf,offset,count);

        int last=offset+nread;         for(int i=offset; i<last;i++)

            buf[i] = Character.toUpperCase(buf[i]);

        return nread;

    }

}

Exemple suite:

 

StringReader source=new StringReader("ma chaîne");

FilterReader filtre=new conversionMaj(source); int c; try{

  while((())!= -1)       .print((char)c);

  }catch(IOException e){

  e.printStackTrace();

 }

Pipe (tube)

 

ooUn tube associe une entrée et un sortie: on lit à une extrémité et on écrit à l'autre.

Exemple pipe

 

class PipeExemple extends Thread{     private Writer out;     private Reader in;

    public PipeExemple(Writer out,Reader in){         =out;         =in;

    }

    public void run(){         int c;         try{             try{

                while ((())!=-1){

                    out.write(Character.toUpperCase((char)c));

                }

            }finally{out.close();}         }catch(IOException e){e.printStackTrace();}

    }

}

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);

                .print((char)(()));

            }            

        }finally {             out2.close();

        }

ByteArray, String…

 

oo 

.InputStream (implements .Closeable)  .ByteArrayInputStream .StringBufferInputStream 

oo 

.OutputStream (implements .Closeable, .Flushable

.ByteArrayOutputStream

oo 

.Reader (implements .Closeable, .Readable) .CharArrayReader.StringReader 

oo 

.Writer (implements .Appendable, .Closeable, .Flushable

              .CharArrayWriter 

              .StringWriter          

Print Streams

 

.PrintStream (implements .Appendable, .Closeable

.PrintWriter  nnméthode println()

Streams pour les données

 

ooDataInput: interface pour lire des bytes d'une stream binaire et les transformer en données java de type primitif

ooDataOutput: interface pour convertir des valeurs de type primitif en stream binaire.

Sérialisation

 

oosauvegarder des objets java en flot d'octets:

nnobjet vers byte: sérialisation nnbyte vers objet: désérialisation

.ObjectInputStream (implements .ObjectInput, .ObjectStreamConstants)

.ObjectInputStream (implements .ObjectInput, .ObjectStreamConstants)

Sauver des objets

 

oola serialisation-désérialisation doit permettre de sauvegarder et restituer des objets. oosauver et restituer des objets n'est pas si simple. Pourquoi? oointerface serializable oo(alternative XML)

Manipuler des fichiers…

 

.File (implements .Comparable<T>, .Serializable

nio

 

ooentrée sorties de haute performance avec contrôle sur les buffers.


 

Collections

 

ootypes de données nninterfaces nnimplémentations nnalgorithmes ooInterfaces:

 

Collections: les interfaces

 

Les collections sont des interfaces génériques ooCollection<E>: add, remove size toArray… nnSet<E>: éléments sans duplication ooSortedSet<E>: ensembles ordonnés

               nnList<E>: des listes éléments non ordonnés et avec duplication

               nnQueue<E>:  files avec tête: peek, poll (défiler), offer (enfiler)

ooMap<K,V>:association clés valeurs ooSortedMap<K,V> avec clés triées

Certaines méthodes sont optionnelles (si elles ne sont pas implémentées UnsupportedOperationException).

En plus: ooIterator<E>: interface qui retourne successivement les éléments next(), hasNext(), remove()

ooListIterator<E>: itérateur pour des List, set(E) previous, add(E)

Collection

 

public interface Collection<E> extends Iterable<E> {

    // operations de base     int size();     boolean isEmpty();     boolean contains(Object element);     boolean add(E element);         //optionnel     boolean remove(Object element); //optionnel

    Iterator<E> iterator();

    // operations des collections     boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c); //optionnel     boolean removeAll(Collection<?> c);        //optionnel     boolean retainAll(Collection<?> c);        //optionnel     void clear();                              //optionnel

    // Array

    Object[] toArray();

    <T> T[] toArray(T[] a);

}

Collection

 

ooLes collections sont génériques ooParcours:

nnOn peut parcourir les éléments par « for »:

for (Object o : collection)     .println(o); nnOu avec un Iterator:

static void filter(Collection<?> c) {

    for (Iterator<?> it = c.iterator(); it.hasNext();)

         if (!cond(()))        it.remove();

}

Collection

 

ooOn peut convertir une collection en tableau nnEn tableaux de Object

nnEn tableaux d’objet du type paramètre de la collection

ooIl existe aussi une classe Collections qui contient des méthodes statiques utiles

Set

 

ooInterface pour contenir des objets différents nnOpérations ensemblistes

nnSortedSet pour des ensembles ordonnés

ooImplémentations:

nnHashSet par hachage (preformances) nnTreeSet arbre rouge-noir nnLinkedHashSet ordonnés par ordre d’insertion

Set

 

public interface Set<E> extends Collection<E> {

    // opérations de base

    int size();     boolean isEmpty();

    boolean contains(Object element);     boolean add(E element);         //optionnel     boolean remove(Object element); //optionnel

    Iterator<E> iterator();

    // autres

    boolean containsAll(Collection<?> c); // sous-ensemble     boolean addAll(Collection<? extends E> c); //optionnel- union     boolean removeAll(Collection<?> c);        //optionnel- différence     boolean retainAll(Collection<?> c);        //optionnel- intersection     void clear();                              //optionnel

    // Array

    Object[] toArray();

    <T> T[] toArray(T[] a);

}

Exemple:

 

 public static void chercheDoublons(String st){

        Set<String> s = new HashSet<String>();

        for (String a : st)             if (!s.add(a))

                .println("Doublon: " + a);

        .println("il y a "() + " mots différents: " + s);

 }

 public static void chercheDoublonsbis(String st[]){

        Set<String> s=new HashSet<String>();

        Set<String> sdup=new HashSet<String>();

        for(String a :st)             if (!s.add(a))                 (a);

        s.removeAll(sdup);

        .println("Mots uniques:    " + s);

        .println("Mots dupliqués: " + sdup);   }

Lists

 

ooEn plus de Collection: nnAccès par position de l ’élément nnRecherche qui retourne la position de l’élément

nnSous-liste entre deux positions

ooImplémentations:

nnArrayList  nnLinkedList 

List

 

public interface List<E> extends Collection<E> {

    // accès par position

    E get(int index);

    E set(int index, E element);    //optional     boolean add(E element);         //optional     void add(int index, E element); //optional     E remove(int index);            //optional

    boolean addAll(int index,

        Collection<? extends E> c); //optional

    // recherche     int indexOf(Object o);     int lastIndexOf(Object o);

    // Iteration

    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);

    // sous-liste

    List<E> subList(int from, int to);

}

Itérateur pour listes

 

public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();     E next();

    boolean hasPrevious();     E previous();     int nextIndex();     int previousIndex();     void remove(); //optional     void set(E e); //optional     void add(E e); //optional

}

Exemple

 

 public static <E> void swap(List<E> a, int i, int j) {

        E tmp = a.get(i);

        a.set(i, a.get(j));

        a.set(j, tmp);  }

 public static void melange(List<?> list, Random rnd) {

        for (int i = (); i > 1; i--)             swap(list, i - 1, rnd.nextInt(i));  }

Suite…

 

 public static <E> List<E> uneMain(List<E> deck, int n) {         int deckSize = ();

        List<E> handView = deck.subList(deckSize - n, deckSize);         List<E> hand = new ArrayList<E>(handView);         handView.clear();         return hand;

 }

 public static void distribuer(int nMains, int nCartes) {

        String[] couleurs = new String[]{"pique","coeur","carreau","trèfle"};

        String[] rank = new String[]

        {"as","2","3","4","5","6","7","8", "9","10","valet","dame","roi"};

        List<String> deck = new ArrayList<String>();         for (int i = 0; i < couleurs.length; i++)             for (int j = 0; j < rank.length; j++)

                (rank[j] + " de " + couleurs[i]);     

        melange(deck,new Random());                for (int i=0; i < nMains; i++)

            .println(uneMain(deck,nCartes));     }

Map

 

ooMap associe des clés à des valeurs

nnAssociation injective: à une clé correspond exactement une valeur. nnTrois implémentations, comme pour set ooHashMap,  ooTreeMap,  ooLinkedHashMap  nnRemplace Hash

Map

 

public interface Map<K,V> {     // Basic operations

    V put(K key, V value);

    V get(Object key);     V remove(Object key);     boolean containsKey(Object key);     boolean containsValue(Object value);     int size();     boolean isEmpty();     // Bulk operations

    void putAll(Map<? extends K, ? extends V> m);     void clear();     // Collection Views     public Set<K> keySet();     public Collection<V> values();     public Set<Map.Entry<K,V>> entrySet();     // Interface for entrySet elements     public interface Entry {

        K getKey();

        V getValue();

        V setValue(V value);

    }

}

Exemples

 

 public static void mapFreq(String t) {

        Map<String, Integer> m = new HashMap<String,        

                                                                     Integer>();

        for (String a : t) {             Integer freq = m.get(a);

            m.put(a, (freq == null) ? 1 : freq + 1);

        }

        .println("Il y a: " + m.size() + 

            " mots différents:\n"+m);

    }

// ordre arbitraire

Exemples

 

 public static void mapFreq(String t) {

        Map<String, Integer> m = new TreeMap<String,

                                                                     Integer>();

        for (String a : t) {             Integer freq = m.get(a);

            m.put(a, (freq == null) ? 1 : freq + 1);

        }

        .println("Il y a: " + m.size() + 

            " mots différents:\n"+m);

    }

// ordre arbitraire

Exemples

 

 public static void mapFreq(String t) {

        Map<String, Integer> m = new LinkedHashMap<String,

                                                                     Integer>();

        for (String a : t) {             Integer freq = m.get(a);

            m.put(a, (freq == null) ? 1 : freq + 1);

        }

        .println("Il y a: " + m.size() + 

            " mots différents:\n"+m);

    }

// ordre arbitraire

Queue

 

ooPour représenter une file (en principe FIFO): 

nnInsertion: offer -add nnExtraction: poll - remove nnPour voir: peek –element nn(retourne une valeur - exception

ooPriorityQueue implémentation pour une file à priorité

Interface Queue

 

public interface Queue<E> extends Collection<E> {

    E element();     boolean offer(E e);

    E peek();

    E poll();

    E remove();

}

Exemple

 

 public static void compteur(int n)             throws InterruptedException {

        Queue<Integer> file = new           

              LinkedList<Integer>();         for (int i = n; i >= 0; i--)

            (i);         while (!file.isEmpty()) {

            .println(file.remove());

            Thread.sleep(1000);

        }

    }

Exemple

 

static <E> List<E> heapSort(Collection<E> c) {     Queue<E> queue = new PriorityQueue<E>(c);

    List<E> result = new ArrayList<E>();

    while (!queue.isEmpty())         (queue.remove());

    return result;

}

oo 

HashSet<E>: implémentation de Set comme table de hachage. Recherche/ ajout suppression en temps constant

oo 

TreeSet<E>: SortedSet comme arbre binaire équilibré O(log(n))

oo 

ArrayList<E>: liste implémentée par des tableaux à taille variable accès en O(1) ajout et suppression en O(n-i) (i position considérée)

LinkedList<E>: liste doublement chaînée implémente List et

Des implémentations

 

oo 

Queue accès en O(i) oo         HashMap<K,V>: implémentation de Map par table de hachage ajout suppression et recherche en O(1)

TreeMap<K,V>: implémentation de SortedMap à partir d'arbres


oo oo oo 

équilibrés ajout, suppression et recherche en O(log(n)) WeakHashMap<K,V>: implémentation de Map par table de hachage

PriorityQueue<E>: tas à priorité.


Comparaisons

 

ooInterface Comparable<T>  contient la méthode

nnpublic int compareTo(T e) nn"ordre naturel"

ooInterface Comparator<T> contient la méthode

nnpublic int compare(T o1, T o2)

Quelques autres packages

 

ooSystem méthodes static pour le système:

nnentrée-sorties standard nnmanipulation des propriétés systèmes nnutilitaires "Runtime" exit(), gc() …

Runtime, Process

 

ooRuntime permet de créer des processus pour exécuter des commande: exec

ooProcess retourné par un exec méthodes

nndestroy() nnexitValue() nngetInputStream() nngetOutputStream() nngetErrorStream()

Exemple

 

ooexécuter une commande (du système local)

nnassocier l'entrée de la commande sur

nnassocier la sortie sur .

Exemple

 

class plugTogether extends Thread {

    InputStream from;

    OutputStream to;

    plugTogether(OutputStream to, InputStream from ) {         = from; = to;

    }

    public void run() {         byte b;         try {

            while ((b= (byte) ()) !=  -1) to.write(b);

        } catch (IOException e) {

            .println(e);

        } finally {             try {                 to.close();                 from.close();             } catch (IOException e) {

                .println(e);

            }

        }

    }

}

Exemple suite

 

public class Main {

    public static Process userProg(String cmd)     throws IOException {

      Process proc = Runtime.getRuntime().exec(cmd);

      Thread thread1 = new plugTogether(proc.getOutputStream(), );

      Thread thread2 = new plugTogether(, proc.getInputStream());       Thread thread3 = new plugTogether(, proc.getErrorStream());       thread1.start(); thread2.start(); thread3.start();               try {proc.waitFor();} catch (InterruptedException e) {}         return proc;

    }

    public static void main(String args[])     throws IOException {

       String cmd = args[0];

       .println("Execution de: "+cmd);

       Process proc = userProg(cmd);   

    }

}


 

Threads

 

oothreads: plusieurs activités qui coexistent et partagent des données nnexemples: oopendant un chargement long faire autre chose oocoopérer

                            ooprocessus versus threads

nnproblème de l'accès aux ressources partagées

ooverrous oomoniteur

                            oosynchronisation 

Principes de base

 

ooextension de la classe Thread nnméthode run est le code qui sera exécuté. nnla création d'un objet dont la superclasse est

Thread crée la thread (mais ne la démarre pas) nnla méthode start démarre la thread (et retourne immédiatement)

nnla méthode join permet d'attendre la fin de la thread

nnles exécutions des threads sont asynchrones et concurrentes

Exemple

 

class ThreadAffiche extends Thread{     private String mot;     private int delay;

    public ThreadAffiche(String w,int duree){         mot=w;         delay=duree;

    }     public void run(){         try{             for(;;){

                .println(mot);                 Thread.sleep(delay);

            }

        }catch(InterruptedException e){

        }

    }

}

Suite

 

 public static void main(String[] args) {        new ThreadAffiche("PING", 10).start();        new ThreadAffiche("PONG", 30).start();        new ThreadAffiche("Splash!",60).start();   }

Alternative: Runnable

 

ooUne autre solution: nncréer une classe qui implémente l'interface Runnable (cette interface contient la méthode run)

nncréer une Thread à partir du constructeur Thread avec un Runnable comme argument.

Exemple

 

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(;;){

                .println(mot);                 Thread.sleep(delay);

            }

        }catch(InterruptedException e){

        }

    }

}

Suite

 

 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();

}

Synchronisation

 

ooles threads s'exécutent concurremment et peuvent accéder concurremment à des objets:

nnil faut contrôler l'accès:

nnthread un lit une variable  (R1) puis modifie cette variable (W1)

                                              nnthread deux lit la même variable (R2) puis la modifie

(W2) nnR1-R2-W2-W1 nnR1-W1-R2-W2 résultat différent!

Exemple

 

    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(){             ;

            .println("thread:"+nom+" valeur x="+i);             try{

            Thread.sleep(10);

            }catch(Exception e){}

            x.val=i+1;

            .println("thread:"+nom+" valeur x=");

        }

    }

Suite

 

 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{             ();

            ();            

        }catch (InterruptedException e){}

        .println("X=");

    }

donnera (par exemple) oothread:un valeur x=0 oothread:deux valeur x=0 oothread:un valeur x=1 oothread:deux valeur x=1 ooX=1

Deuxième exemple

 

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(){

        .println("thread:"+nom+" valeur="+y.increment());

    }

}

Suite

 

  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{             ();             ();

        }catch (InterruptedException e){}

        .println("Y="+y.getVal());

    }

----------- oothread:un valeur=1 oothread:deux valeur=1 ooY=1

Verrous

 

ooà chaque objet est associé un verrou nnsynchronized(expr) {instructions} ooexpr doit s'évaluer comme une référence à un objet ooverrou sur cet objet pour la durée de l'exécution de instructions

nndéclarer les méthodes comme synchronized: la thread obtient le verrou et le relâche quand la méthode se termine

synchronised(x)

 

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){             ;

            .println("thread:"+nom+" valeur x="+i);             try{

                Thread.sleep(10);             }catch(Exception e){}

            x.val=i+1;

            .println("thread:"+nom+" valeur x=");

        }

    }

}

Méthode synchronisée

 

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;}

}

------------ oothread:un valeur=1 oothread:deux valeur=2 ooY=2

Mais…

 

oola synchronisation par des verrous peut entraîner un blocage: nnla thread un (XA) pose un verrou sur l'objet  A et

(YB) demande un verrou sur l'objet B nnla thread deux (XB) pose un verrou sur l'objet B et (YA) demande un verrou sur l'objet A

nnsi XA –XB : ni YA ni YB ne peuvent êter satisfaites -> blocage

oo(pour une méthode synchronisée, le verrou concerne l'objet globalement et pas seulement la méthode)

Exemple

 

class Dead{     Dead partenaire;     String nom;     public Dead(String st){         nom=st;

    }

    public synchronized void f(){

        try{

            Thread.currentThread().sleep(100);

        }catch(Exception e){}

        .println(Thread.currentThread().getName()+

                " de "+ nom+".f() invoque "+ +".g()");         partenaire.g();    }     public synchronized void g(){

        .println(Thread.currentThread().getName()+

                " de "+ nom+".g()");

    }

    public void setPartenaire(Dead d){         partenaire=d;

    }

}

Exemple (suite)

 

        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();

------------

ooT1 de un.f() invoque deux.g() ooT2 de deux.f() invoque un.g()

Synchronisation…

 

oowait, notifyAll notify

nnattendre une condition / notifier le changement de condition:

synchronized void fairesurcondition(){ while(!condition){ wait(); faire ce qu'il faut quand la condition est vraie }

-----------------

synchronized void changercondition(){

 … changer quelque chose concernant la condition  notifyAll(); // ou notify()

}

Exemple (file: rappel Cellule)

 

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;

    } 

File synchronisées

 

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();

 }

File (suite)

 

 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();

 }


2638