corrige tp java

102
Exercices simples sur les bases procédurales de Java – Solutions Solution de l’ex. 1 Conversion euros/franc Une solution possible est la suivante : import java.util.*; public class ConversionMain { public static void main(String[] args) { // Objet Scanner pour les entrees clavier Scanner sc = new Scanner(System.in); // Requete faite a l’utilisateur System.out.print("Veuillez entrer un montant : "); // L’utilisateur entre un montant double x = sc.nextDouble(); // On affiche le resultat de la conversion System.out.println("Somme convertie en francs : " + x * 6.55957); } } Solution de l’ex. 2 Moyenne d’un tableau Une solution possible est la suivante : import java.util.*; public class MoyenneMain { public static void main(String[] args) { // Objet Scanner pour les entrees clavier Scanner sc = new Scanner(System.in); // Requete faite a l’utilisateur System.out.print("Veuillez entrer un nbre d’elts : "); // L’utilisateur entre une taille int nbElts = sc.nextInt(); // On cree un tableau double tab[] = new double[nbElts]; // Entree des valeurs du tableau for(int i = 0; i < nbElts; i++) { System.out.print("Veuillez entrer l’elt no " + i + " : "); tab[i] = sc.nextDouble(); } 14 Exercices de travaux pratiques Java // On calcule la somme des elts du tableau int somme = 0; for(int i = 0; i < nbElts; i++) { somme += tab[i]; }

Upload: maya-medjdoub

Post on 03-Jul-2015

1.895 views

Category:

Software


15 download

DESCRIPTION

cours java et tp

TRANSCRIPT

Page 1: Corrige tp java

Exercices simples sur les bases procédurales de Java – Solutions

Solution de l’ex. 1 Conversion euros/franc Une solution possible est la suivante : import java.util.*; public class ConversionMain { public static void main(String[] args) { // Objet Scanner pour les entrees clavier Scanner sc = new Scanner(System.in); // Requete faite a l’utilisateur System.out.print("Veuillez entrer un montant : "); // L’utilisateur entre un montant double x = sc.nextDouble(); // On affiche le resultat de la conversion System.out.println("Somme convertie en francs : " + x * 6.55957); } } Solution de l’ex. 2 Moyenne d’un tableau Une solution possible est la suivante : import java.util.*; public class MoyenneMain { public static void main(String[] args) { // Objet Scanner pour les entrees clavier Scanner sc = new Scanner(System.in); // Requete faite a l’utilisateur System.out.print("Veuillez entrer un nbre d’elts : "); // L’utilisateur entre une taille int nbElts = sc.nextInt(); // On cree un tableau double tab[] = new double[nbElts]; // Entree des valeurs du tableau for(int i = 0; i < nbElts; i++) { System.out.print("Veuillez entrer l’elt no " + i + " : "); tab[i] = sc.nextDouble(); } 14 Exercices de travaux pratiques Java // On calcule la somme des elts du tableau int somme = 0; for(int i = 0; i < nbElts; i++) { somme += tab[i]; }

Page 2: Corrige tp java

// On affiche la moyenne System.out.println("Moyenne : " + somme/(double)nbElts); } } Solution de l’ex. 3 Menu d’opérations arithmétiques Une solution possible est la suivante : import java.util.*; public class ArithmetiqueMain { public static void main(String[] args) { // Objet Scanner pour les entrees clavier Scanner sc = new Scanner(System.in); // Menu utilisateur System.out.print("1 Somme de deux réels\n" + "2 Soustraction de deux réels\n" + "3 Multiplication de deux réels\n" + "4 Division de deux réels\n" + "5 Sortie du programme\n\n" + "Veuillez entrer votre choix : "); // L’utilisateur entre un choix int choix = sc.nextInt(); // Puis les deux reels System.out.print("Veuillez entrer le 1er réel : "); double x = sc.nextDouble(); System.out.print("Veuillez entrer le 2e réel : "); double y = sc.nextDouble(); // Realisation de l’operation double res = 0; switch(choix) { case 1 : res = x + y; break; case 2 : res = x - y; break; case 3 : res = x * y; break; case 4 : res = x / y; break; case 5 : System.exit(0); default : System.out.println("Choix incorrect"); System.exit(1); } // On affiche le resultat System.out.println("Resultat : " + res); } }

Exercices simples supplémentaires

Page 3: Corrige tp java

sur les bases procédurales de Java – Solutions

Solution de l’ex. 1 Table de multiplication Une solution possible est la suivante : import java.util.*; public class TabMultMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Veuillez entrer un entier : "); int n = sc.nextInt(); for(int i = 0; i < 10; i++) { System.out.print(n*i + " "); } System.out.println(""); } }

Solution de l’ex. 2 Décomposition en base dix Une solution possible est la suivante : import java.util.Scanner; public class BaseDixMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = 1000; while (n < -999 || n > 999) { System.out.print("Veuillez entrer un entier à 3 chiffres n = sc.nextInt(); if (n < -999 || n > 999) continue; int c = n / 100; int d = (n - 100 * c) / 10; int u = n - 100 * c - 10 * d; System.out.print(c + "*10^2 + " + d + "*10 + " + u); } System.out.println(""); } } Solution de l’ex. 3 Etoiles Une solution possible est la suivante : import java.util.Scanner; public class EtoilesMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Veuillez entrer un entier : "); int n = sc.nextInt();

Page 4: Corrige tp java

for(int i = 0; i < n; i++) { for(int j = 0; j <= i; j++) { System.out.print("*"); } System.out.println(""); } System.out.println(""); } } Solution de l’ex. 4 Opérations élémentaires Une solution possible est la suivante : import java.util.Scanner; public class OperElemMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Veuillez entrer un réel : "); double x = sc.nextDouble(); System.out.print("\nVeuillez entrer un entier : "); int n = sc.nextInt(); System.out.println(x + "^2 = " + carre(x)); System.out.println(x + "^" + n + " = " + puissance(x, n)); System.out.println(n + "! = " + fact(n)); } public static double carre(double x) { return (x * x); } 20 Exercices de travaux pratiques Java public static double puissance(double x, int n) { double res = 1; for (int i = 0; i < n; i++) { res *= x; } return res; } public static int fact(int n) { if (n == 1) return 1; int res = n * fact(n - 1); return res; } }

Exercices sur les bases procédurales de Java – Solutions

Solution de l’ex. 1 Évaluation polynômiale simple Réponse à la première question import java.util.Scanner;

Page 5: Corrige tp java

/** * Classe polynomiale du 1er degre **/ class PolyLineaire { int a, b; // champs : coefficients de a*x + b // Constructeur : initialisation des champs PolyLineaire(int a, int b) { this.a = a; this.b = b; } // methode int evaluer(int x) { return(a*x + b); } int evaluerCarre(int x) { int axPlusb = evaluer(x); return(axPlusb*axPlusb); } } /** * Ce programme affiche les carres au fur et a mesure que * l’utilisateur entre des valeurs de maniere interactive **/ public class PolyLineaireMainUn { public static void main(String[] args) { System.out.println("Veuillez entrer a, b et x"); // Creation d’un objet pour les entrees clavier Scanner entClav = new Scanner(System.in); // recuperation des arguments au format entier int a = entClav.nextInt(); int b = entClav.nextInt(); 26 Exercices de travaux pratiques Java int x = entClav.nextInt(); // Creation d’un objet de type PolyLineaire PolyLineaire p = new PolyLineaire(a, b); // Calcul et affichage du resultat System.out.println("(" + a + "*" + x + "+" + b + ")^2 = " + p.evaluerCarre(x)); } } Réponse à la deuxième question /** * Ce programme affiche les carres au fur et a mesure que * l’utilisateur entre des valeurs de maniere interactive **/ public class PolyLineaireMainDeux { public static void main(String[] args) { // test du nombre d’arguments if (args.length != 3) { System.out.println("Mauvais nombre d’arguments"); System.exit(1); } // recuperation des arguments au format entier

Page 6: Corrige tp java

int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); int x = Integer.parseInt(args[2]); // Creation d’un objet de type PolyLineaire PolyLineaire p = new PolyLineaire(a, b); // Calcul et affichage du resultat System.out.println("(" + a + "*" + x + "+" + b + ")^2 = " + p.evaluerCarre(x)); } } Réponse à la troisième question import java.util.Scanner; /** * Classe polynomiale du 1er degre **/ /** * Ce programme affiche les carres au fur et a mesure que * l’utilisateur entre des valeurs de maniere interactive **/ public class PolyLineaireMainTrois { public static void main(String[] args) { // Creation d’un objet pour les entrees clavier Scanner entClav = new Scanner(System.in); while(true) { System.out.println("Veuiilez entrer a, b et x ou quitter"); String s = entClav.next(); if (s.equals("quitter")) break; int a = Integer.parseInt(s); int b = entClav.nextInt(); int x = entClav.nextInt(); // Creation d’un objet de type PolyLineaire PolyLineaire p = new PolyLineaire(a, b); // Calcul et affichage du resultat System.out.println("(" + a + "*" + x + "+" + b + ")^2 = " + p.evaluerCarre(x)); } System.out.println("Sortie du programme"); } } Réponse à la première question utilisant la classe BufferedReader au lieu de Scanner import java.io.*; /** * Classe polynomiale du 1er degre **/ class PolyLineaireBuffRead { int a, b; // champs : coefficients de a*x + b // Constructeur : initialisation des champs PolyLineaireBuffRead(int a, int b) { this.a = a; this.b = b;

Page 7: Corrige tp java

} // methode int evaluer(int x) { return(a*x + b); } int evaluerCarre(int x) { int axPlusb = evaluer(x); 28 Exercices de travaux pratiques Java return(axPlusb*axPlusb); } } /** * Ce programme affiche les carres au fur et a mesure que * l’utilisateur entre des valeurs de maniere interactive **/ public class PolyLineaireMainBuffRead { public static void main(String[] args) throws IOException { // On utilise un BufferedReader pour lire des lignes de texte // System.in est l’entree standard BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // Boucle infinie for(;;) { System.out.println("Veuillez entrer a, b et x"); // Afficher une invite a l’utilisateur System.out.print("PolyLineaireInter > "); // Lire une ligne entree par l’utilisateur String line = in.readLine(); // Si l’on rencontre une fin de fichier, ou si l’utilisateur // entre "quit", on sort if ((line == null) || line.equals("quit")) break; // On essaie de formatter l’entree de l’utilisateur, // puis on calcule le carre String[] theArgs = line.split(" "); // decoupe la ligne selon " " try { int a = Integer.parseInt(theArgs[0]); int b = Integer.parseInt(theArgs[1]); int x = Integer.parseInt(theArgs[2]); PolyLineaireBuffRead p = new PolyLineaireBuffRead(a, b); System.out.println("(" + a + "*" + x + "+" + b + ")^2 = " + p.evaluerCarre(x)); } // Affichage d’un message d’erreur en cas de probleme catch(Exception e) { System.out.println("Entree Invalide"); } } } } Solution de l’ex. 2 Tri d’un tableau par bulle import java.io.*; class BubbleSortAlgorithm {

Page 8: Corrige tp java

void sort(InputOutputIntArray array) { int[] a = array.getArray(); for (int i = a.length; --i >= 0; ) { boolean swapped = false; for (int j = 0; j < i; j++) { if (a[j] > a[j+1]) { int T = a[j]; a[j] = a[j+1]; a[j+1] = T; swapped = true; } } if (!swapped) return; } } } class InputOutputIntArray { int[] intArray; InputOutputIntArray(int nbElts) { intArray = new int[nbElts]; } int [] getArray() { return(intArray); } void inputKeyboard() { // On utilise un BufferedReader pour lire des lignes de texte // System.in est l’entree standard BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); // Afficher une invite a l’utilisateur System.out.println("Entrez les elements du tableau "+ "ou q pour sortir "); for(int i = 0; i < intArray.length; i++) { try { System.out.print("Entrez l’element no " + (i+1) + " : "); // Lire une ligne entree par l’utilisateur String line = in.readLine(); // Si l’on rencontre une fin de fichier, // ou si l’utilisateur entre "quit", on sort if ((line == null) || line.equals("q")) break; // On essaie de formatter l’entree de l’utilisateur, // puis on remplit l’elt correspondant du tableau int elt = Integer.parseInt(line); intArray[i] = elt;

Page 9: Corrige tp java

} catch(IOException e) { // Message d’erreur System.out.println("Entree invalide"); i--; } }// for() } void outputScreen(String message) { System.out.println(message); for(int i = 0; i < intArray.length; i++) { System.out.print("t[" + i + "] " + intArray[i] + " "); } System.out.println("\n\n"); } } public class BubbleSortText { int[] arrayToSort; public static void main(String[] args) throws IOException { int nbElts; // Traitement des arguments if (args.length < 1) nbElts = 10; else nbElts = Integer.parseInt(args[0]); BubbleSortAlgorithm algorithm = new BubbleSortAlgorithm(); InputOutputIntArray arrayToSort = new InputOutputIntArray(nbElts); // Entree au clavier arrayToSort.inputKeyboard(); // Tri algorithm.sort(arrayToSort); // Affichage du resultat arrayToSort.outputScreen("\n\nVoici le tableau trie "); } } Solution de l’ex. 3 Affichage du graphe d’une fonction Portion de code HTML associée à l’applet <HTML> <HEAD> </HEAD> <BODY BGCOLOR="000000"> <CENTER> <APPLET code = "GrahApplet.class" width = "500" height = "300" > </APPLET> </CENTER> </BODY> </HTML> Solution pour le source java import java.awt.Graphics;

Page 10: Corrige tp java

public class GraphApplet extends java.applet.Applet { double f(double x) { return (Math.cos(x/5) + Math.sin(x/7) + 2) * getSize().height / 4; } public void paint(Graphics g) { for (int x = 0 ; x < getSize().width ; x++) { g.drawLine(x, (int)f(x), x + 1, (int)f(x + 1)); } } public String getAppletInfo() { return "Dessine le graphe d’une fonction de type sinusiodal."; } }

Exercices complémentaires sur les bases procédurales Java – Solutions

Solution de l’ex. 1 Les tours de Hanoï class Piquet { int m_nDiscs; int Anneaux[]; String m_Name; Piquet(String s, int maxPiquets) { m_Name = s; m_nDiscs = 0; Anneaux = new int[maxPiquets]; } void viderPiquet() { m_nDiscs = 0; } void remplirPiquet(int i) { m_nDiscs = i; for(int j = 0; j < m_nDiscs; j++) { Anneaux[j] = j; } } int popAnneau() { int ann = Anneaux[m_nDiscs - 1]; m_nDiscs--; return ann; } void pushAnneau(int ann) { m_nDiscs++; Anneaux[m_nDiscs - 1] = ann; } String nom() { return m_Name;

Page 11: Corrige tp java

} void dessinePiquet() { System.out.print(m_Name + " : "); for(int i = 0; i < m_nDiscs; i++) System.out.print(Anneaux[i] + " "); System.out.println(" "); } } class JeuHanoi { int N; Piquet A, B, C; public JeuHanoi(int NbDisques) { N = NbDisques; A = new Piquet("Gauche", N); B = new Piquet("Milieu", N); C = new Piquet("Droit", N); A.remplirPiquet(N); B.viderPiquet(); C.viderPiquet(); dessinerJeu(); deplacerTour(N, A, B, C); } public void deplacerTour(int i, Piquet piqA, Piquet piqB, Piquet piqC) { if(i == 0) { return; } else { deplacerTour(i - 1, piqA, piqC, piqB); deplacerAnneau(piqA, piqB); deplacerTour(i - 1, piqC, piqB, piqA); return; } } public void deplacerAnneau(Piquet piq, Piquet piqA) { int anneau = piq.popAnneau(); piqA.pushAnneau(anneau); dessinerJeu(); } public void dessinerJeu() { A.dessinePiquet(); 36 Exercices de travaux pratiques Java B.dessinePiquet(); C.dessinePiquet(); System.out.println(" "); } } public class HanoiMain {

Page 12: Corrige tp java

public static void main(String args[]) { int nbDisques; if (args.length == 0) nbDisques = 3; else try { nbDisques = Integer.parseInt(args[0]); } catch (NumberFormatException e) { nbDisques = 3; } new JeuHanoi(nbDisques); } } Solution de l’ex. 2 Évaluation de polynôme par le schéma de Horner import java.util.Scanner; /** * Evaluation de polynomes par la methode de Horner */ class Horner { double a[]; // coefficients du polynome int N; // ordre du polynome public Horner(int nouvN, double nouvA[]) { N = nouvN; a = new double[N]; for(int i = 0; i < N; i++) { a[i] = nouvA[i]; } } double evalBrute(double x) { double resultat = 0; for(int i = 0; i < N; i++) { resultat += a[i]*Math.pow(x, (double)i); } return resultat; } double evalHorner(double x) { double b[] = new double[N+1]; int i; i = N-2; b[i+1] = a[N-1]; while(i >= 0) { i--; b[i+1] = b[i+2]*x + a[i+1]; } return b[0]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); double eps = 1e-14; System.out.print("Veuillez entrer l’ordre du polynome ");

Page 13: Corrige tp java

int ordre = sc.nextInt(); double coeffs[] = new double[ordre+1]; for(int i = 0; i < ordre+1; i++) { System.out.print("Veuillez entrer le coeff no " + i + " "); coeffs[i] = sc.nextDouble(); } Horner h = new Horner(ordre+1, coeffs); System.out.print("Veuillez entrer x "); double x = sc.nextDouble(); double resBrute = h.evalBrute(x); double resHorner = h.evalHorner(x); System.out.print("Evaluation de p(x) = "); for(int i = 0; i < ordre+1; i++) { System.out.print(h.a[i] + "*x^" + i + " + "); } System.out.print("\n en x = " + x); double Pb = h.evalBrute(x); double Ph = h.evalHorner(x); System.out.println("eval Brute --> Pb(" + x + ")=" + Pb); System.out.println("eval Horner --> Ph(" + x + ")=" + Ph); System.out.println("test --> |Pb(x)-Ph(x)| < 1e-14 : " + (Math.abs(Ph-Pb) < eps) ); } }

Exercices d’introduction orientée objet en Java : manipulations de classes –

Solutions Solution de l’ex. 1 Classe Tableau import java.util.*; public class Tableau { int[] tab; public Tableau(int n1, int n2, int n3, int n4) { tab = new int[4]; tab[0] = n1; tab[1] = n2; tab[2] = n3; tab[3] = n4; } public void trouverZero() { for (int i = 0; i < tab.length; i++) { if (tab[i] == 0) { System.out.println("tab[" + i + "] == 0"); return; }

Page 14: Corrige tp java

} System.out.println("-1 (indice non trouve)"); return; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Veuillez entrer l’entier 1 : "); int n1 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 2 : "); int n2 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 3 : "); int n3 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 4 : "); int n4 = sc.nextInt(); Tableau t = new Tableau(n1, n2, n3, n4); t.trouverZero(); } } Solution de l’ex. 2 Variante de la classe Tableau import java.util.Scanner; class TableauBis { int[] tab; public TableauBis(int n1, int n2, int n3, int n4) { tab = new int[4]; tab[0] = n1; tab[1] = n2; tab[2] = n3; tab[3] = n4; } public int trouverZero() { for (int i = 0; i < tab.length; i++) { if (tab[i] == 0) { return i; } } return -1; } } public class TableauBisMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Veuillez entrer l’entier 1 : "); int n1 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 2 : "); int n2 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 3 : "); int n3 = sc.nextInt(); System.out.print("Veuillez entrer l’entier 4 : "); int n4 = sc.nextInt(); TableauBis t = new TableauBis(n1, n2, n3, n4); int ind = t.trouverZero(); System.out.print("Indice trouve : " + ind); }

Page 15: Corrige tp java

} public class PersonnelMain { public static void main(String[] args) { Personnel p1 = new Personnel(1, 12, 53432); Personnel p2 = new Personnel(2, 24, 55438); p1.printPersonnel(); p2.printPersonnel(); p1.setIdent(44); p2.setPosteTel(56787); p1.printPersonnel(); p2.printPersonnel(); } } class Personnel { int genre; int ident; int posteTel; public Personnel(int g, int id, int pt) { if (g != 1 && g != 2) genre = 1; else genre = g; ident = id; posteTel = pt; } public int getGenre() { return genre; } public int getIdent() { return ident; } public int getPosteTel() { return posteTel; } public void setIdent(int newIdent) { ident = newIdent; } public void setPosteTel(int newPosteTel) { posteTel = newPosteTel; } public void printPersonnel() { System.out.println("genre : " + genre + " identifiant : " + ident + " poste telephonique : " + posteTel); } } Solution de l’ex. 4 Classe Complexe public class Complexe { /* * Champs de la classe */

Page 16: Corrige tp java

protected double partieReelle; protected double partieImaginaire; /* * Constructeurs */ Complexe(double r, double i) { partieReelle = r; partieImaginaire = i; } Complexe() { this(0, 0); } Complexe(Complexe z) { this(z.partieReelle, z.partieImaginaire); } public Complexe ajouter(Complexe z) { double re = 0, im = 0; re = this.partieReelle + z.partieReelle; im = this.partieReelle + z.partieImaginaire; Complexe somme = new Complexe(re, im); return somme; } public void afficher() { System.out.println("(" + partieReelle + ", " + partieImaginaire public void afficherSansCR() { System.out.print("(" + partieReelle + ", " + partieImaginaire + } /* public static void main(String[] args) { Complexe c1 = new Complexe(1, 1); Complexe c2 = new Complexe(7, 6); Complexe c3 = c1.ajouter(c2); c1.afficher(); c2.afficher(); c3.afficher(); } */ }// fin de la classe Complexe Solution de l’ex. 5 Classe Matrice public class MatriceCarree { int[][] tab; int nbElts; public MatriceCarree(int n, int[] elts) { nbElts = n; tab = new int[nbElts][nbElts]; for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { tab[i][j] = elts[i * nbElts + j]; } } } public MatriceCarree(int n) {

Page 17: Corrige tp java

nbElts = n; tab = new int[nbElts][nbElts]; } public void afficher() { for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { System.out.print(tab[i][j] + "\t"); } System.out.println(""); } System.out.println(""); } public MatriceCarree ajouter(MatriceCarree m) { MatriceCarree r = new MatriceCarree(nbElts); for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { r.tab[i][j] = tab[i][j] + m.tab[i][j]; } } return r; } public static void main(String[] args) { int[] elts1 = new int[4]; int[] elts2 = new int[4]; for (int i = 0; i < 4; i++) { elts1[i] = 2 * i; elts2[i] = 7 * i; } MatriceCarree m1 = new MatriceCarree(2, elts1); MatriceCarree m2 = new MatriceCarree(2, elts2); MatriceCarree m3 = m1.ajouter(m2); m1.afficher(); m2.afficher(); m3.afficher(); } } Solution de l’ex. 6 Matrice de complexes public class MatriceCarreeComplexe { Complexe[][] tab; int nbElts; public MatriceCarreeComplexe(int n, Complexe[] elts) { nbElts = n; tab = new Complexe[nbElts][nbElts]; for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { tab[i][j] = new Complexe(elts[i * nbElts + j]); } } } public MatriceCarreeComplexe(int n) { nbElts = n; tab = new Complexe[nbElts][nbElts]; }

Page 18: Corrige tp java

public void afficher() { for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { tab[i][j].afficherSansCR(); System.out.print("\t"); } System.out.println(""); } System.out.println(""); } public MatriceCarreeComplexe ajouter(MatriceCarreeComplexe m) { MatriceCarreeComplexe r = new MatriceCarreeComplexe(nbElts); for (int i = 0; i < nbElts; i++) { for (int j = 0; j < nbElts; j++) { r.tab[i][j] = tab[i][j].ajouter(m.tab[i][j]); } } return r; } public static void main(String[] args) { Complexe[] elts1 = new Complexe[4]; Complexe[] elts2 = new Complexe[4]; for (int i = 0; i < 4; i++) { elts1[i] = new Complexe(i, 2 * i); elts2[i] = new Complexe(3 * i, 5 * i); } MatriceCarreeComplexe m1 = new MatriceCarreeComplexe(2, elts1); MatriceCarreeComplexe m2 = new MatriceCarreeComplexe(2, elts2); MatriceCarreeComplexe m3 = m1.ajouter(m2); m1.afficher(); m2.afficher(); m3.afficher(); } }

Exercices d’introduction orientée objet en Java : personnes, enseignants et

Page 19: Corrige tp java

étudiants – Solutions Solution de l’ex. 1 Classe Personne (constructeurs) Réponse à la question 1 Classe PersonneMain1 public class PersonneMain1 { public static void main(String[] args) { // Creation d’une instance de Personne1 Personne1 sage = new Personne1("Agecanonix", 80); // Appel de la methode afficher sage.afficher(); } } Classe Personne1 class Personne1 { String nom; int age; // Constructeur exhaustif Personne1(String leNom, int lAge) { nom = new String(leNom); age = lAge; } void afficher() { System.out.println("Nom : " + nom); System.out.println("Age : " + age); } } Notez que dans le constructeur de Personne1, l’initialisation du champ nom a été réalisée par nom = new String(leNom) ; et non par nom = leNom ; // sachant que la dernière ligne ne fait que copier les références alors que la première effectue une réelle duplication de la chaîne. Il se trouve que sont intégrés au sein du langage des mécanismes liés au ramasse miettes qui ne libèrent la mémoire que lorsqu’il n’y a plus de référence. Mais attention, lorsqu’on ne copie que les références, on accède à chaque fois au même objet. Réponse à la question 2 Classe PersonneMain2 public class PersonneMain2 { public static void main(String[] args) { double[] mesComptes = new double[2]; mesComptes[0] = 100; mesComptes[1] = 92; // Creation de deux instances de Personne2 Personne2 sage = new Personne2("Agecanonix", 80, mesComptes); Personne2 sageBis = new Personne2("Agecanonix", 80, mesComptes);

Page 20: Corrige tp java

sage.diviserParDeux(); // Appel de la methode afficher sage.afficher(); System.out.println(""); sageBis.afficher(); System.out.println(""); } } Classe Personne2 class Personne2 { String nom; int age; double[] comptes; // Constructeur exhaustif Personne2(String leNom, int lAge, double[] lesComptes) { // La ligne suivante est a proscrire, quoiqu’il soit // difficile de s’en rendre compte // nom = leNom; // La bonne maniere de faire est : nom = new String(leNom); age = lAge; // La ligne suivante est a proscrire // nombres = lesNombres; // La bonne maniere de faire est : comptes = new double[lesComptes.length]; for(int i = 0; i < comptes.length; i++) { comptes[i] = lesComptes[i]; } } void diviserParDeux() { for(int i = 0; i < comptes.length; i++) { comptes[i] /= 2.0; } } void afficher() { System.out.println("Nom : " + nom); System.out.println("Age : " + age); for(int i = 0; i < comptes.length; i++) { System.out.println("Compte no " + i + " : " + comptes[i]); } } } Réponse à la question 3 public class PersonneMain3 { public static void main(String[] args) { double[] mesNombres = {100, 92}; // Creation de 3 instances de Personne4 Personne3 sage = new Personne3("Agecanonix", 80); Personne3 intrepide = new Personne3(); Personne3 humain = new Personne3(intrepide); // Appel de la methode afficher sage.afficher(); System.out.println(""); intrepide.afficher(); System.out.println(""); humain.afficher(); System.out.println("");

Page 21: Corrige tp java

} } class Personne3 { String nom; int age; // Constructeur exhaustif Personne3(String leNom, int lAge) { nom = new String(leNom); age = lAge; } // Constructeur par defaut Personne3() { this("Asterix", 30); } // Constructeur de recopie Personne3(Personne3 p) { nom = new String(p.nom); age = p.age; } void afficher() { System.out.println("Nom : " + nom); System.out.println("Age : " + age); } } Solution de l’ex. 2 Classes Enseignants et étudiants (Héritage) Réponse à la question 1 Classe ProfEleveMain3 public class ProfEleveMain3 { public static void main(String[] args) { Personne3 reveur = new Personne3("Nimbus", 45); Enseignant3 prof = new Enseignant3("Nimbus", 45, 150, true); Etudiant3 eleve = new Etudiant3("Soupaloigonycrouton", 20, 5, true); reveur.afficher(); System.out.println(""); prof.afficher(); System.out.println(""); eleve.afficher(); System.out.println(""); } } Classe Enseignant3 class Enseignant3 extends Personne3 { int nbHeuresCours; boolean grincheux; Enseignant3(String leNom, int lAge, int heures, boolean ouin) { super(leNom, lAge); nbHeuresCours = heures; grincheux = ouin; } } Classe Etudiant3 class Etudiant3 extends Personne3 {

Page 22: Corrige tp java

int noteMoyenne; boolean faineant; Etudiant3(String leNom, int lAge, int note, boolean poilAlaMain) { super(leNom, lAge); noteMoyenne = note; faineant = poilAlaMain; } } Réponse à la question 2 public class ProfEleveMain4 { public static void main(String[] args) { Personne3[] tabPers = new Personne3[5]; tabPers[0] = new Enseignant3("Nimbus", 45, 150, true); tabPers[1] = new Enseignant3("Tournesol", 55, 270, false); tabPers[2] = new Etudiant3("Gauss", 21, 22, false); tabPers[3] = new Etudiant3("GrosZero", 27, 3, true); tabPers[4] = new Etudiant3("Gaston", 28, 5, false); for(int i = 0; i < 5; i++) { tabPers[i].afficher(); System.out.print("Statut : "); if (tabPers[i] instanceof Enseignant3) System.out.println("Enseignant"); else if (tabPers[i] instanceof Etudiant3) System.out.println("Etudiant"); else System.out.println("Inconnu"); System.out.println(""); } } } Solution de l’ex. 3 Différents affichages (Surcharge et redéfinition) Réponse à la question 1 class Personne5 { String nom; int age; // Constructeur exhaustif Personne5(String leNom, int lAge) { nom = new String(leNom); age = lAge; } // Constructeur par defaut Personne5() { this("Asterix", 30); } // Constructeur de recopie Personne5(Personne5 p) { nom = new String(p.nom); age = p.age; } void afficher() { System.out.println("Nom : " + nom);

Page 23: Corrige tp java

System.out.println("Age : " + age); } void afficher(boolean compact) { if (compact == false) afficher(); else { System.out.print("[" + nom + ", " + age + "]"); } } } Réponse à la question 2 class Enseignant5 extends Personne5 { int nbHeuresCours; boolean grincheux; Enseignant5(String leNom, int lAge, int heures, boolean ouin) { super(leNom, lAge); nbHeuresCours = heures; grincheux = ouin; } void afficher() { super.afficher(); System.out.println("Enseignant\n"); } } Réponse à la question 3 Classe Etudiant5 class Etudiant5 extends Personne5 { double noteMoyenne; boolean faineant; Etudiant5(String leNom, int lAge, int moyenne, boolean poilAlaMain) { super(leNom, lAge); noteMoyenne = moyenne; faineant = poilAlaMain; } void afficher() { super.afficher(); System.out.println("Etudiant\n"); } } Classe ProfEleveMain5 public class ProfEleveMain5 { public static void main(String[] args) { Personne5[] tabPers = new Personne5[5]; tabPers[0] = new Enseignant5("Nimbus", 45, 150, true); tabPers[1] = new Enseignant5("Tournesol", 55, 270, false); tabPers[2] = new Etudiant5("Gauss", 21, 22, false); tabPers[3] = new Etudiant5("GrosZero", 27, 3, true); tabPers[4] = new Etudiant5("Gaston", 28, 5, false); for(int i = 0; i < 5; i++) {

Page 24: Corrige tp java

tabPers[i].afficher(true); // Affichage compact } } } Solution de l’ex. 4 Délégation d’affichage (Classes abstraites) Classe Personne6 abstract class Personne6 { String nom; int age; // Constructeur exhaustif Personne6(String leNom, int lAge) { nom = new String(leNom); age = lAge; } // Affichage du type delegue aux sous classes abstract void afficherType(); void afficher() { System.out.println("Nom : " + nom); System.out.println("Age : " + age); afficherType(); } } Classe Enseignant6 class Enseignant6 extends Personne6 { int nbHeuresCours; boolean grincheux; Enseignant6(String leNom, int lAge, int heures, boolean ouin) { super(leNom, lAge); nbHeuresCours = heures; grincheux = ouin; } void afficherType() { System.out.println("Enseignant"); } } Classe Etudiant6 class Etudiant6 extends Personne6 { int noteMoyenne; boolean faineant; Etudiant6(String leNom, int lAge, int note, boolean poilAlaMain) { super(leNom, lAge); noteMoyenne = note; faineant = poilAlaMain; } void afficherType() { System.out.println("Etudiant"); } } Classe ProfEleveMain6 public class ProfEleveMain6 {

Page 25: Corrige tp java

public static void main(String[] args) { Personne6[] tabPers = new Personne6[5]; tabPers[0] = new Enseignant6("Nimbus", 45, 50, true); tabPers[1] = new Enseignant6("Tournesol", 55, 292, false); tabPers[2] = new Etudiant6("Gauss", 21, 22, false); tabPers[3] = new Etudiant6("GrosZero", 27, 1, true); tabPers[4] = new Etudiant6("Gaston", 28, 4, false); for(int i = 0; i < 5; i++) { tabPers[i].afficher(); } } }

Exercices de base orientée objet Java autour de complexes – Solutions

Solution de l’ex. 1 Première manipulations de complexes (création de classes, constructeurs, méthodes et champs statiques) Voici la réponse aux différentes questions : Classe Complexe class Complexe1 { /* * Champs de la classe */ protected double partieReelle; protected double partieImaginaire; private static int nbComplexes = 0; /* * Constructeurs */ Complexe1(double r, double i) { partieReelle = r; partieImaginaire = i; nbComplexes++; } Complexe1() { this(0, 0); } Complexe1(Complexe1 z) { this(z.partieReelle, z.partieImaginaire); } public String toString() { return ("[" + nbComplexes + "](" + Double.toString(partieReelle) + ", " + Double.toString(partieImaginaire) + ")"); } // methode appelee a la liberation memoire d’un complexe // on decremente le compteur d’objets protected void finalize() { System.out.println("Morituri " + this);

Page 26: Corrige tp java

nbComplexes--; } public Complexe1 multiplier(Complexe1 z) { double re = 0, im = 0; re = this.partieReelle * z.partieReelle - this.partieImaginaire * z.partieImaginaire; im = this.partieReelle * z.partieImaginaire + this.partieImaginaire * z.partieReelle; Complexe1 produit = new Complexe1(re, im); return produit; } public static Complexe1 racNiemeUnite(int n) { double re = 0, im = 0, phase = 0; phase = (2*Math.PI)/n; re = Math.cos(phase); im = Math.sin(phase); // renvoi avec creation d’instance implicite return(new Complexe1(re, im)); } }// fin de la classe Complexe Classe ComplexeMain public class ComplexeMain1 { public static void main(String[] args) { Complexe1 resultat = null; switch(args.length) { case 1 : int n = Integer.parseInt(args[0]); resultat = Complexe1.racNiemeUnite(n); break; case 4 : double re1 = Double.parseDouble(args[0]); double im1 = Double.parseDouble(args[1]); double re2 = Double.parseDouble(args[2]); double im2 = Double.parseDouble(args[3]); Complexe1 z1 = new Complexe1(re1, im1); Complexe1 z2 = new Complexe1(re2, im2); resultat = z1.multiplier(z2); // On libere la memoire en dereferencant les 2 objets // intermediaires puis en appelant le ramasse-miettes z1 = null; z2 = null; System.gc(); break; default : System.out.println("1 ou 4 parametres"); System.exit(1); } System.out.println("Resultat : " + resultat); } }// fin de la classe ComplexeMain Solution de l’ex. 2 Tableaux génériques (tableaux) Voici la réponse aux différentes questions : Classe Complexe class Complexe {

Page 27: Corrige tp java

/* * Champs de la classe */ protected double partieReelle; protected double partieImaginaire; /* * Constructeurs */ Complexe(double r, double i) { partieReelle = r; partieImaginaire = i; } Complexe() { this(0, 0); } Complexe(Complexe z) { this(z.partieReelle, z.partieImaginaire); } public String toString() { return ("(" + Double.toString(partieReelle) + ", " + Double.toString(partieImaginaire) + ")"); } public boolean equals(Complexe z) { return (this.partieReelle == z.partieReelle && this.partieImaginaire == z.partieImaginaire); } public void change(double nouvPReelle, double nouvPImag) { partieReelle = nouvPReelle; partieImaginaire = nouvPImag; } public Complexe multiplier(Complexe z) { double re = 0, im = 0; re = this.partieReelle * z.partieReelle - this.partieImaginaire * z.partieImaginaire; im = this.partieReelle * z.partieImaginaire + this.partieImaginaire * z.partieReelle; Complexe produit = new Complexe(re, im); return produit; } }// fin de la classe Complexe Classe Tableau un tableau d’objets (de type Objet). class Tableau { private Object[] donnees = null; private int nbElts; public Tableau(int nb, Object[] tabObjets) { nbElts = nb; donnees = tabObjets; } public Tableau(Tableau t) { this(t.nbElts, t.donnees); } public Tableau() {

Page 28: Corrige tp java

this(0, null); } for(int i = 0; i < tab.size(); i++) { System.out.println("tab[" + i + "]" + tab.get(i)); } Complexe cplxeBis = new Complexe(5, 5); Tableau tabBis = new Tableau(tab); tabBis.set(2, cplxeBis); for(int i = 0; i < tab.size(); i++) { System.out.print("tab[" + i + "]" + tab.get(i)); System.out.println(" -- tabBis[" + i + "]" + tabBis.get(i)); } } } Solution de l’ex. 3 Tableaux dynamiques (interfaces, polymorphisme) Solution standard Interface TailleVariable // qui spécifie les méthodes add() et remove(). interface TailleVariable { public void add(int i, Object elt); public Object remove(int index); } Classe TableauDynamique qui implante les méthodes add() et remove(). class TableauDynamique extends Tableau implements TailleVariable { public TableauDynamique(int nb, Object[] tabObjets) { super(nb, tabObjets); } public void add(int index, Object elt) { // allocation d’un nouveau tableau de references int nouvNbElts = size() + 1; Object[] nouvDonnees = new Object[nouvNbElts]; // remplissage du tableau elargi for (int i = 0; i < index; i++) nouvDonnees[i] = get(i); nouvDonnees[index] = elt; for (int i = index+1; i < nouvNbElts; i++) nouvDonnees[i] = get(i-1); Tableau nouvTableau = new Tableau(nouvNbElts, nouvDonnees); muer(nouvTableau); } public Object remove(int index) { Object ejecte = null; // allocation d’un nouveau tableau de references int nouvNbElts = size() - 1; Object[] nouvDonnees = new Object[nouvNbElts]; // remplissage du tableau elargi for (int i = 0; i < index; i++) nouvDonnees[i] = get(i); ejecte = get(index);

Page 29: Corrige tp java

for (int i = index; i < nouvNbElts; i++) nouvDonnees[i] = get(i+1); Tableau nouvTableau = new Tableau(nouvNbElts, nouvDonnees); muer(nouvTableau); return ejecte; } } Classe TableauComplexeDyn Un tableau dynamique de Complexe. class TableauComplexeDyn extends TableauDynamique { TableauComplexeDyn(int nb, double[] tabRe, double[] tabIm) { super(nb, new Complexe[nb]); for(int i = 0; i < size(); i++) set(i, new Complexe(tabRe[i], tabIm[i])); } public void add(int index, Object elt) { if ((elt instanceof Complexe) == false) System.out.println("Attention, vous ajouter un non complexe : \"" + elt + "\" a l’indice " + index); super.add(index, elt); } public String toString() { StringBuffer s = new StringBuffer("\n"); for(int i = 0; i < size(); i++) s.append(i + ": " + get(i).toString() + "\n"); return s.toString(); } } Classe TableauComplexeDynMain La classe contenant le main(). public class TableauComplexeDynMain { public static void main(String[] args) { double[] tabPartRe, tabPartIm; int nbEltsTab = 0; if (args.length < 1) nbEltsTab = 5; else nbEltsTab = Integer.parseInt(args[0]); tabPartRe = new double[nbEltsTab]; tabPartIm = new double[nbEltsTab]; for (int i = 0; i < nbEltsTab; i++) { tabPartRe[i] = Math.random(); tabPartIm[i] = Math.random(); } TableauComplexeDyn t = new TableauComplexeDyn(nbEltsTab, tabPartRe, tabPartIm); System.out.println("Tab : " + t); t.add(4, new Complexe(2, 2)); t.add(4, new Integer(2)); t.add(3, new String("L’homme regarde la fleur, la fleur sourit.")); System.out.println("Tab : " + t);

Page 30: Corrige tp java

} } Extrait de la classe ArrayList Pour comparaison, voici un extrait de la classe ArrayList du paquetage java.util (n’ont été retirées de cet extrait que les méthodes les moins importantes). On notera que les méthodes set() et get() sont, dans l’esprit, identiques. On notera également la présence d’une méthode clone() qui effectue une copie superficielle (elle copie les différents éléments du tableau interne elementData ; si les éléments stockés sont des types primitifs, une copie indépendante est réalisée ; si les éléments stockés sont des références à des objets, seules les références sont copiées). Extrait de la classe java.util.ArrayList /* * @(#)ArrayList.java 1.36 01/12/03 * Copyright 2002 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.util; public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable { private transient Object elementData[]; private int size; public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public ArrayList() { this(10); } public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; elementData = new Object[newCapacity]; System.arraycopy(oldData, 0, elementData, 0, size); } }

Page 31: Corrige tp java

public int size() { return size; } public boolean isEmpty() { return size == 0; } public boolean contains(Object elem) { return indexOf(elem) >= 0; } public int indexOf(Object elem) { if (elem == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (elem.equals(elementData[i])) return i; } return -1; } public Object clone() { try { ArrayList v = (ArrayList)super.clone(); v.elementData = new Object[size]; System.arraycopy(elementData, 0, v.elementData, 0, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn’t happen, since we are Cloneable throw new InternalError(); } } public Object[] toArray() { Object[] result = new Object[size]; System.arraycopy(elementData, 0, result, 0, size); return result; } // Positional Access Operations public Object get(int index) { RangeCheck(index); return elementData[index]; } public Object set(int index, Object element) { RangeCheck(index); Object oldValue = elementData[index]; elementData[index] = element; return oldValue; } public boolean add(Object o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; }

Page 32: Corrige tp java

public void add(int index, Object element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } public Object remove(int index) { RangeCheck(index); modCount++; Object oldValue = elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } public void clear() { modCount++; // Let gc do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } private void RangeCheck(int index) { if (index >= size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); } } Solution avec copie profonde par clonage d’objets Voici maintenant une solution réalisant une copie profonde en se servant de la méthode clone() de Object. Pour cloner un objet, il faut au préalable que ce dernier implante l’interface Cloneable. La solution retenue ici est que la classe Tableau (nommée ci-dessous TableauClonable) implante cette interface. Les objets potentiels d’un tel tableau dérivent eux de ObjetClonable dont la seule fonction est, au travers de sa méthode clone(), d’appeler la méthode clone() d’Object. Cette dernière effectue une copie de références. Notez que la redéfinition de clone() au sein de ComplexeClonable se contente d’appeler la méthode clone() de la classe ObjetClonable, c’est-à-dire clone() d’Object. Ceci est suffisant, car les champs de Complexe sont tous des types primitifs. S’il y avait eu des références à des objets ou des

Page 33: Corrige tp java

tableaux, il aurait fallu également réaliser la copie profonde de ces derniers. Classe ObjetClonable, comportant la méthode clone() C’est cette classe dont devront hériter les objets à cloner : class ObjetClonable { protected Object clone() throws CloneNotSupportedException { return super.clone(); } } Classe ComplexeClonable L’objet complexe que l’on peut cloner : class ComplexeClonable extends ObjetClonable { /* * Champs de la classe */ protected double partieReelle; protected double partieImaginaire; /* * Constructeurs */ ComplexeClonable(double r, double i) { partieReelle = r; partieImaginaire = i; } ComplexeClonable() { this(0, 0); } ComplexeClonable(ComplexeClonable z) { this(z.partieReelle, z.partieImaginaire); } public String toString() { return ("(" + Double.toString(partieReelle) + ", " + Double.toString(partieImaginaire) + ")"); } public boolean equals(ComplexeClonable z) { return (this.partieReelle == z.partieReelle && this.partieImaginaire == z.partieImaginaire); } public ComplexeClonable multiplier(ComplexeClonable z) { double re = 0, im = 0; re = this.partieReelle * z.partieReelle - this.partieImaginaire * z.partieImaginaire; im = this.partieReelle * z.partieImaginaire + this.partieImaginaire * z.partieReelle; ComplexeClonable produit = new ComplexeClonable(re, im); return produit; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } }// fin de la classe ComplexeClonable La classe TableauClonable, Un tableau d’objets clonable (de type ObjetClonable). Il implante l’interface java Cloneable qui impose de redéfinir la méthode clone(). Selon

Page 34: Corrige tp java

l’usage, cette méthode est censée réaliser une copie profonde de ses objets (par opposition à une copie superficielle, qui ne copie que les références). class TableauClonable implements Cloneable { private ObjetClonable[] donnees = null; private int nbElts; public TableauClonable(int nb, ObjetClonable[] tabObjets) { nbElts = nb; donnees = tabObjets; } public TableauClonable(TableauClonable t) { this(t.nbElts, t.donnees); } public TableauClonable() { this(0, null); } protected Object clone() throws CloneNotSupportedException { TableauClonable theClone = null; try { theClone = (TableauClonable)super.clone(); ObjetClonable[] tab = theClone.donnees; for (int i = 0; i < tab.length; i++) { ObjetClonable o = donnees[i]; tab[i] = (ObjetClonable)o.clone(); } } catch (CloneNotSupportedException e) { System.err.println(e.getMessage()); } return theClone; } int size() { return nbElts; } public int indexOf(ObjetClonable elt) { for (int i = 0; i < size(); i++) if (get(i).equals(elt)) return i; return -1; } ObjetClonable get(int index) { return donnees[index]; } ObjetClonable set(int index, ObjetClonable element) { ObjetClonable vieux = donnees[index]; donnees[index] = element; return vieux; } protected void muer(TableauClonable nouv) { ObjetClonable[] vieux = donnees; donnees = nouv.donnees; nbElts = nouv.nbElts; vieux = null; }

Page 35: Corrige tp java

}// fin de classe TableauClonable Interface TailleVariableClonable //Elle spécifie les méthodes add() et remove(). Notez que remove() renvoie une référence //de type ObjetClonable. interface TailleVariableClonable { public void add(int i, Object elt); public ObjetClonable remove(int index); } Classe TableauDynamiqueClonable Elle implante les méthodes add() et remove(). class TableauDynamiqueClonable extends TableauClonable implements TailleVariableClonable { public TableauDynamiqueClonable(int nb, ObjetClonable[] tabObjets) { super(nb, tabObjets); } public void add(int index, Object elt) { if ((elt instanceof ObjetClonable) == false) { System.out.println("Ajount de l’objet \"" + elt + "\" ne derivant pas d’ObjetClonable impossible "); return; } // allocation d’un nouveau tableau de references int nouvNbElts = size() + 1; ObjetClonable[] nouvDonnees = new ObjetClonable[nouvNbElts]; // remplissage du tableau elargi for (int i = 0; i < index; i++) nouvDonnees[i] = get(i); nouvDonnees[index] = (ObjetClonable) elt; for (int i = index + 1; i < nouvNbElts; i++) nouvDonnees[i] = get(i - 1); TableauClonable nouvTableau = new TableauClonable(nouvNbElts, nouvDonnees); muer(nouvTableau); } public ObjetClonable remove(int index) { ObjetClonable ejecte = null; // allocation d’un nouveau tableau de references int nouvNbElts = size() - 1; ObjetClonable[] nouvDonnees = new ObjetClonable[nouvNbElts]; // remplissage du tableau elargi for (int i = 0; i < index; i++) nouvDonnees[i] = get(i); ejecte = get(index); for (int i = index-1; i < nouvNbElts; i++) nouvDonnees[i] = get(i+1); TableauClonable nouvTableau = new TableauClonable(nouvNbElts, nouvDonnees); muer(nouvTableau); return ejecte; } }

Page 36: Corrige tp java

Classe TableauComplexeDynClonable //Un tableau dynamique de ComplexeClonable. class TableauComplexeDynClonable extends TableauDynamiqueClonable { TableauComplexeDynClonable(int nb, double[] tabRe, double[] tabIm) { super(nb, new ComplexeClonable[nb]); for(int i = 0; i < size(); i++) set(i, new ComplexeClonable(tabRe[i], tabIm[i])); } public void add(int index, Object elt) { if ((elt instanceof ComplexeClonable) == false) System.out.println("Attention, vous ajoutez un non complexe : \"" + elt + "\" a l’indice " + index); try { super.add(index, (ObjetClonable)elt); } catch (ClassCastException e) { System.out.println("Une exception devrait être générée, " + " l’objet ajouté n’implante pas ObjetClonable"); } } public String toString() { StringBuffer s = new StringBuffer("\n"); for(int i = 0; i < size(); i++) s.append(i + ": " + get(i).toString() + "\n"); return s.toString(); } } Classe TableauComplexeDynClonableMain La classe contenant le main(). public class TableauComplexeDynClonableMain { public static void main(String[] args) { double[] tabPartRe, tabPartIm; int nbEltsTab = 0; if (args.length < 1) nbEltsTab = 5; else nbEltsTab = Integer.parseInt(args[0]); tabPartRe = new double[nbEltsTab]; tabPartIm = new double[nbEltsTab]; for (int i = 0; i < nbEltsTab; i++) { tabPartRe[i] = Math.random(); tabPartIm[i] = Math.random(); } TableauComplexeDynClonable t = new TableauComplexeDynClonable(nbEltsTab, tabPartRe, tabPartIm); System.out.println("Tab : " + t); t.add(4, new ComplexeClonable(2, 2)); t.add(4, new Integer(2)); t.add(3, new String("L’homme regarde la fleur, la fleur sourit."));

Page 37: Corrige tp java

System.out.println("Tab : " + t); } }

Gestion locale de banque simple en Java – Solutions

Solution de l’ex. 1 Gestion simple de banque : solution locale Une solution possible, avec un tableau pour stocker les comptes, est la suivante : // Gestion simpliste de banque en local import java.io.*; /** * Classe conteneur. Contient : * - Client le client * - Server la banque **/ /** * Classe imbriquee pour stocker les donnees d’un compte bancaire **/ class SimpleAccount { String name; String password; // mot de passe int balance; // solde du compte SimpleAccount(String name, String password) { this.name = name; this.password = password; this.balance = 0; } } /** * Serveur bancaire simpliste realise en local **/ class SimpleBankLocalServer { /** * Cette table stocke tous les comptes ouverts **/ SimpleAccount allAccounts[] = new SimpleAccount[100]; /** * Ouvre un compte avec le nom et le mot de passe specifie **/ public void openAccount(String name, String password) { // Verifier s’il exsite deja un compte ayant ce nom int i; for (i = 0; i < allAccounts.length; i++) if (allAccounts[i] != null && ((allAccounts[i]).name).equals(name) == System.out.println("Le compte existe deja.");

Page 38: Corrige tp java

System.exit(1); } // Cercher une case libre pour le nouveau compte for (i = 0; i < allAccounts.length; i++) if (allAccounts[i] == null) break; if (i == allAccounts.length) { System.out.println("Tableau des comptes plein !"); System.out.flush(); System.exit(2); } // S’il n’existe pas, le creer SimpleAccount acct = new SimpleAccount(name, password); // Et l’enregsitrer allAccounts[i] = acct; } /** * Cette methode utilitaire renvoie l’indice de l’objet Account dans * le tableau des comptes **/ public int verify(String name, String password) { boolean nonExistant = true; SimpleAccount acct = null; int accIndex = 0; for (accIndex = 0; accIndex < allAccounts.length; accIndex++) { acct = allAccounts[accIndex]; if (acct != null && (acct.name).equals(name) == true) { nonExistant = false; break; } } if (nonExistant == true ) { System.out.println("Compte inexistant"); System.out.flush(); System.exit(3); } if (!password.equals(acct.password)) { System.out.println("Mot de passe invalide"); System.out.flush(); System.exit(4); } return accIndex; } /** * Ferme le compte dont on donne le nom. Methode synchronisee **/ public int closeAccount(String name, String password) { SimpleAccount acct = null; int index = verify(name, password); acct = allAccounts[index]; int balance = acct.balance; acct.balance = 0; allAccounts[index] = null;

Page 39: Corrige tp java

return balance; } /** Deposer le montant specifie su le compte dont on donne le nom */ public void deposit(String name, String password, int money) { int index = verify(name, password); SimpleAccount acct = allAccounts[index]; acct.balance += money; } /** Effectue un retrait d’un montant specifie */ public int withdraw(String name, String password, int amount) { int index = verify(name, password); SimpleAccount acct = allAccounts[index]; if (acct.balance < amount) System.out.println("Solde insuffisant"); acct.balance -= amount; return amount; } /** Renvoie le solde du compte dont on donne le nom */ public int getBalance(String name, String password) { int index = verify(name, password); SimpleAccount acct = allAccounts[index]; return acct.balance; } }// class Server /** * Client simple interagissant avec un serveur **/ public class SimpleBankLocal { public static String getName(BufferedReader in) { String name = null; try { System.out.println("Veuillez entrer le nom du compte : "); name = new String(in.readLine().toLowerCase()); } catch (IOException e) { System.err.println("Erreur en readLine()"); } return name; } public static String getPassword(BufferedReader in) { String password = null; try { System.out.println("Veuillez entrer le mot de passe : "); password = new String(in.readLine().toLowerCase()); } catch (IOException e) { System.err.println("Erreur en readLine()"); } return password; } public static void main(String[] args) { try { SimpleBankLocalServer bank = new SimpleBankLocalServer();

Page 40: Corrige tp java

BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String cmd = "nothing"; while(true) { System.out.println("\nVeuillez entrer une commande : \n" + "open (ouverture de compte)\n" + "close (cloture de compte)\n" + "deposit (depot sur le compte)\n" + "withdraw (retrait sur le compte)\n" + "balance (solde du compte)\n" + "quit (sortie du programme)\n"); // Convertir la commande utilisateur en minuscules cmd = stdin.readLine().toLowerCase(); // Differentes actions possibles if (cmd.equals("open")) { // ouverture de compte String name = getName(stdin); String password = getPassword(stdin); bank.openAccount(name, password); System.out.println("Account opened."); } else if (cmd.equals("close")) { // fermeture de compte String name = getName(stdin); String password = getPassword(stdin); int money = bank.closeAccount(name, password); System.out.println(money + " pieces vous sont rendues."); System.out.println("Au revoir."); } else if (cmd.equals("deposit")) { // depot d’argent String name = getName(stdin); String password = getPassword(stdin); System.out.println("Veuillez entrer le montant : "); String amount = new String(stdin.readLine().toLowerCase()); int money = Integer.parseInt(amount); bank.deposit(name, password, money); System.out.println("Depot de " + money + " pieces."); } else if (cmd.equals("withdraw")) { // retarait d’argent String name = getName(stdin); String password = getPassword(stdin); System.out.println("Veuillez entrer le montant : "); String amount = new String(stdin.readLine().toLowerCase()); int money = bank.withdraw(name, password, Integer.parseInt(amount)); System.out.println("Retrait de " + money + " pieces."); } else if (cmd.equals("balance")) { // solde du compte String name = getName(stdin); String password = getPassword(stdin); int amt = bank.getBalance(name, password); System.out.println("Vous avez "+amt+" de pieces a cette banque."); } else if (cmd.equals("quit")) { // break System.out.println("Au revoir\n");

Page 41: Corrige tp java

break; } else System.out.println("Action inconnue"); } }// while not quitted // Autres exceptions, erreurs de syntaxe, affichage d’utilisation catch (Exception e) { System.err.println(e); System.err.println("Utilisation : java BankLocal"); } } }// class Client Solution de l’ex. 2 Gestion simple de banque : compléments Une solution possible, avec une HashMap pour stocker les comptes, est la suivante : Classe BankLocal // Gestion simpliste de banque en local import java.util.*; import java.io.*; /** * Client simple interagissant avec un serveur **/ public class BankLocal { public static String getName(BufferedReader in) { String name = null; try { System.out.println("Veuillez entrer le nom du compte : "); name = new String(in.readLine().toLowerCase()); } catch (IOException e) { System.err.println("Erreur en readLine()"); } return name; } public static String getPassword(BufferedReader in) { String password = null; try { System.out.println("Veuillez entrer le mot de passe : "); password = new String(in.readLine().toLowerCase()); } catch (IOException e) { System.err.println("Erreur en readLine()"); } return password; } public static void main(String[] args) { try { BankLocalServer bank = new BankLocalServer(); BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String cmd = "nothing";

Page 42: Corrige tp java

while(true) { System.out.println("\nVeuillez entrer une commande : \n" + "open (ouverture de compte)\n" + "close (cloture de compte)\n" + "deposit (depot sur le compte)\n" + "withdraw (retrait sur le compte)\n" + "balance (solde du compte)\n" + "history (historique des transactions)\n" + "quit (sortie du programme)\n"); // Convertir la commande utilisateur en minuscules cmd = stdin.readLine().toLowerCase(); // Differentes actions possibles if (cmd.equals("open")) { // ouverture de compte String name = getName(stdin); String password = getPassword(stdin); bank.openAccount(name, password); System.out.println("Account opened."); } else if (cmd.equals("close")) { // fermeture de compte String name = getName(stdin); String password = getPassword(stdin); FunnyMoney money = bank.closeAccount(name, password); System.out.println(money.amount+" pieces vous sont rendues."); System.out.println("Au revoir."); } else if (cmd.equals("deposit")) { // depot d’argent String name = getName(stdin); String password = getPassword(stdin); System.out.println("Veuillez entrer le montant : "); String amount = new String(stdin.readLine().toLowerCase()); FunnyMoney money = new FunnyMoney(Integer.parseInt(amount)); bank.deposit(name, password, money); System.out.println("Depot de " + money.amount + " pieces."); } else if (cmd.equals("withdraw")) { // retarait d’argent String name = getName(stdin); String password = getPassword(stdin); System.out.println("Veuillez entrer le montant : "); String amount = new String(stdin.readLine().toLowerCase()); FunnyMoney money = bank.withdraw(name, password, Integer.parseInt(amount)); System.out.println("Retrait de " + money.amount + " pieces."); } else if (cmd.equals("balance")) { // solde du compte String name = getName(stdin); String password = getPassword(stdin); int amt = bank.getBalance(name, password); System.out.println("Vous avez "+amt+" de pieces a cette banque."); } else if (cmd.equals("history")) { // historique des transactions

Page 43: Corrige tp java

String name = getName(stdin); String password = getPassword(stdin); ArrayList transactions = bank.getTransactionHistory(name, password); for(int i = 0; i < transactions.size(); i++) System.out.println(transactions.get(i)); } else if (cmd.equals("quit")) { // break System.out.println("Au revoir\n"); break; } else System.out.println("Action inconnue"); } }// while not quitted // Gestion des exceptions banacires catch (BankingException e) { System.err.println(e.getMessage()); } // Autres exceptions, erreurs de syntaxe, affichage d’utilisation catch (Exception e) { System.err.println(e); System.err.println("Utilisation : java BankLocal"); } } }// class Client Classe BankLocalServer // Gestion simpliste de banque en local import java.util.*; /** * Classe stockant les donnees d’un compte bancaire **/ class Account { String password; // mot de passe int balance; // solde du compte ArrayList transactions = new ArrayList(); // historique des transactions Account(String password) { this.password = password; this.balance = 0; transactions.add("Compte ouvert le " + new Date()); } } /** * Serveur bancaire simpliste realise en local **/ class BankLocalServer { /** * Cette table de hachage stocke tous les comptes ouverts et relie * chaque noms de compte a l’objet Account correspondant **/ HashMap accounts = new HashMap();

Page 44: Corrige tp java

/** * Ouvre un compte avec le nom et le mot de passe specifie * Cette methode est synchronisee de facon qu’une seule thread * ne modifie a la fois la table des comptes. **/ public synchronized void openAccount(String name, String password) throws BankingException { // Verifier s’il exsite deja un compte ayant ce nom if (accounts.get(name) != null) throw new BankingException("Le compte existe deja."); // S’il n’existe pas, le creer Account acct = new Account(password); // Et l’enregsitrer accounts.put(name, acct); } /** * Cette methode utilitaire n’est pas une methode accessible de maniere * distante. Etant donnes un nom et un mot de passe, verifie s’il existe * un compte correspondant. Si oui, renvoie l’objet Account. Sinon, * leve une exception. **/ public Account verify(String name, String password) throws BankingException { synchronized(accounts) { Account acct = (Account)accounts.get(name); if (acct == null) throw new BankingException("Compte inexistant"); if (!password.equals(acct.password)) throw new BankingException("Mot de passe invalide"); return acct; } } /** * Ferme le compte dont on donne le nom. Methode synchronisee **/ public synchronized FunnyMoney closeAccount(String name, String password) throws BankingException { Account acct; acct = verify(name, password); accounts.remove(name); // Avant de changer le solde ou effectuer une transaction sur un compte, // il faut d’abord acquerir un verrou sur ce compte synchronized (acct) { int balance = acct.balance; acct.balance = 0; return new FunnyMoney(balance); }

Page 45: Corrige tp java

} /** Deposer le montant specifie su le compte dont on donne le nom */ public void deposit(String name, String password, FunnyMoney money) throws BankingException { Account acct = verify(name, password); synchronized(acct) { acct.balance += money.amount; acct.transactions.add(money.amount + " pieces deposees le " + new Date()); } } /** Effectue un retrait d’un montant specifie */ public FunnyMoney withdraw(String name, String password, int amount) throws BankingException { Account acct = verify(name, password); synchronized(acct) { if (acct.balance < amount) throw new BankingException("Solde insuffisant"); acct.balance -= amount; acct.transactions.add("Retrait de " + amount + " le "+new Date()); return new FunnyMoney(amount); } } /** Renvoie le solde du compte dont on donne le nom */ public int getBalance(String name, String password) throws BankingException { Account acct = verify(name, password); synchronized(acct) { return acct.balance; } } /** * Renvoie un vecteur de String contenant l’historique pour * le compte dont on donne le nom **/ public ArrayList getTransactionHistory(String name, String password) throws BankingException { Account acct = verify(name, password); synchronized(acct) { return acct.transactions; } } }// class Server Classe BankingException // Gestion simpliste de banque en local /** * Type d’exception bancaire, comme "Solde insuffisant" ou "Mot de passe invalide" **/ class BankingException extends Exception { public BankingException(String msg) { super(msg); } }

Page 46: Corrige tp java

Classe FunnyMoney // Gestion simpliste de banque en local /** * Cette classe simple represente un montant monetaire. N’est qu’un emballage * d’un entier. **/ class FunnyMoney { public int amount; public FunnyMoney(int amount) { this.amount = amount; } }

Conception d’interfaces graphiques et entrées-sorties

Exercices d’introduction à la conception d’interfaces graphiques sous Eclipse –

Solutions Solution de l’ex. 1 Somme d’entiers Classe SommeGraphiqueMain enrobant la méthode main() import javax.swing.UIManager; import java.awt.*; public class SommeGraphiqueMain { boolean packFrame = false;

Page 47: Corrige tp java

//Construct the application public SommeGraphiqueMain() { FrameSommeGraphique frame = new FrameSommeGraphique(); //Validate frames that have preset sizes //Pack frames that have useful preferred size info, e.g. from their layout if (packFrame) { frame.pack(); } else { frame.validate(); } //Center the window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height frame.setVisible(true); } //Main method public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } new SommeGraphiqueMain(); } } Classe JFrameSomme import javax.swing.WindowConstants; import javax.swing.JDesktopPane; import java.awt.BorderLayout; import javax.swing.JLabel; import javax.swing.border.BevelBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.border.LineBorder; import javax.swing.BorderFactory; import javax.swing.JTextField; /** * This code was generated using CloudGarden’s Jigloo * SWT/Swing GUI Builder, which is free for non-commercial

Page 48: Corrige tp java

* use. If Jigloo is being used commercially (ie, by a corporation, * company or business for any purpose whatever) then you * should purchase a license for each developer using Jigloo. * Please visit www.cloudgarden.com for details. * Use of Jigloo implies acceptance of these licensing terms. * ************************************* * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED * for this machine, so Jigloo or this code cannot be used legally * for any corporate or commercial purpose. * ************************************* */ public class JFrameSomme extends javax.swing.JFrame { private JDesktopPane jDesktopPaneSomme; private JLabel jLabelNombres; private JLabel jLabelResultats; private JLabel jLabelNombreNo2; private JTextField jTextFieldNombreNo1; private JButton jButtonQuitter; private JButton jButtonSommer; private JLabel jLabelValeurResultat; private JLabel jLabelSomme; private JTextField jTextFieldNombreNo2; private JLabel jLabelNombreNo1; /** * Auto-generated main method to display this JFrame */ public static void main(String[] args) { JFrameSomme inst = new JFrameSomme(); inst.setVisible(true); } public JFrameSomme() { super(); initGUI(); } private void initGUI() { try { this.setSize(400, 300); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); this.getContentPane().setBackground(new java.awt.Color(128,128,128)); { jDesktopPaneSomme = new JDesktopPane(); this.getContentPane().add(jDesktopPaneSomme, BorderLayout.jDesktopPaneSomme.setBorder(BorderFactory.createEtchedBorder({ jLabelNombres = new JLabel(); jDesktopPaneSomme.add(jLabelNombres); jLabelNombres.setText("Nombres"); jLabelNombres.setBounds(73, 9, 73, 30); jLabelNombres.setFont(new java.awt.Font("} { jLabelResultats = new JLabel();

Page 49: Corrige tp java

jDesktopPaneSomme.add(jLabelResultats); jLabelResultats.setText("Resultats"); jLabelResultats.setBounds(277, 6, 79, 30); jLabelResultats.setFont(new java.awt.Font("} { jLabelNombreNo1 = new JLabel(); jDesktopPaneSomme.add(jLabelNombreNo1); jLabelNombreNo1.setText("NombreNo1"); jLabelNombreNo1.setBounds(73, 72, 76, 30); } { jLabelNombreNo2 = new JLabel(); jDesktopPaneSomme.add(jLabelNombreNo2); jLabelNombreNo2.setText("NombreNo2"); jLabelNombreNo2.setBounds(73, 114, 79, 30); } { jTextFieldNombreNo1 = new JTextField(); jDesktopPaneSomme.add(jTextFieldNombreNo1); jTextFieldNombreNo1.setText(" "); jTextFieldNombreNo1.setBounds(165, 72, 60, 30); } { jTextFieldNombreNo2 = new JTextField(); jDesktopPaneSomme.add(jTextFieldNombreNo2); jTextFieldNombreNo2.setText(" "); jTextFieldNombreNo2.setBounds(165, 114, 60, 30); } { jLabelSomme = new JLabel(); jDesktopPaneSomme.add(jLabelSomme); jLabelSomme.setText("Somme"); jLabelSomme.setBounds(165, 160, 60, 30); jLabelSomme.setFont(new java.awt.Font("Dialog",1,14)); } { jLabelValeurResultat = new JLabel(); jDesktopPaneSomme.add(jLabelValeurResultat); jLabelValeurResultat.setText(" "); jLabelValeurResultat.setBounds(277, 163, 60, 30); jLabelValeurResultat.setBackground(new java.awt.Color(192,192,192)); jLabelValeurResultat.setBorder(new LineBorder(new java.awt.Color(0,0,0), 1, false)); } { jButtonQuitter = new JButton(); jDesktopPaneSomme.add(jButtonQuitter); jButtonQuitter.setText("Quitter"); jButtonQuitter.setBounds(23, 218, 77, 30); jButtonQuitter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { System.exit(0); }

Page 50: Corrige tp java

}); } { jButtonSommer = new JButton(); jDesktopPaneSomme.add(jButtonSommer); jButtonSommer.setText("Sommer"); jButtonSommer.setBounds(278, 218, 85, 30); jButtonSommer.addActionListener(new ActionListener() public void actionPerformed(ActionEvent String texteSomme = "Idéfini"; int somme = 0; String chaineUn = jTextFieldNombreNo1.String chaineUnNettoyee = chaineUn.String chaineDeux = jTextFieldNombreNo2.String chaineDeuxNettoyee = try { int nombreUn = Integer.parseInt(int nombreDeux = Integer.parseInt(somme = nombreUn + nombreDeux; texteSomme = Integer.toString(jLabelValeurResultat.setText(jTextFieldNombreNo1.setText(""); jTextFieldNombreNo2.setText(""); } catch (NumberFormatException jTextFieldNombreNo1.jTextFieldNombreNo2.jLabelValeurResultat.return; } } }); } } } catch (Exception e) { e.printStackTrace(); } } /** * Auto-generated method for setting the popup menu for a component */ private void setComponentPopupMenu( final java.awt.Component parent, final javax.swing.JPopupMenu menu) { parent.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } public void mouseReleased(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } }); } }

Exercice de conception d’interfaces

Page 51: Corrige tp java

graphiques pour application bancaire – Solutions

Solution de l’ex. 1 Conception d’une interface pour application bancaire simple Interface graphique Classe GUIBanqueFrame import javax.swing.WindowConstants; /** * This code was generated using CloudGarden’s Jigloo * SWT/Swing GUI Builder, which is free for non-commercial * use. If Jigloo is being used commercially (ie, by a corporation, * company or business for any purpose whatever) then you * should purchase a license for each developer using Jigloo. * Please visit www.cloudgarden.com for details. * Use of Jigloo implies acceptance of these licensing terms. * ************************************* * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED * for this machine, so Jigloo or this code cannot be used legally * for any corporate or commercial purpose. * ************************************* */ import javax.swing.JMenuBar; import javax.swing.JMenu; import javax.swing.JMenuItem; public class GUIBanqueFrame extends javax.swing.JFrame { private JMenuBar jMenuGUIBanque; private JMenu jMenuFichier; private JMenuItem jMenuOperationsItemSolde; private JMenuItem jMenuOperationsItemHistorique; private JMenuItem jMenuOperationsItemRetrait; private JMenuItem jMenuOperationsItemDepot; private JMenuItem jMenuOperationsItemFermer; private JMenuItem jMenuOperationsItemOuvrir; private JMenuItem jMenuFichierItemQuitter; private JMenu jMenuOperations; /** * Auto-generated main method to display this JFrame */ public static void main(String[] args) { GUIBanqueFrame inst = new GUIBanqueFrame(); inst.setVisible(true); } public GUIBanqueFrame() { super(); initGUI(); } private void initGUI() { try { setSize(400, 300); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); {

Page 52: Corrige tp java

jMenuGUIBanque = new JMenuBar(); setJMenuBar(jMenuGUIBanque); jMenuGUIBanque.setPreferredSize(new java.awt.Dimension(390, 18)); { jMenuFichier = new JMenu(); jMenuGUIBanque.add(jMenuFichier); jMenuFichier.setText("Fichier"); { jMenuFichierItemQuitter = new JMenuItem(); jMenuFichier.add(jMenuFichierItemQuitter); jMenuFichierItemQuitter.setText(" } } { jMenuOperations = new JMenu(); jMenuGUIBanque.add(jMenuOperations); jMenuOperations.setText("Operations"); { jMenuOperationsItemOuvrir = new jMenuOperations.add(jMenuOperat jMenuOperationsItemOuvrir.setTex } { jMenuOperationsItemFermer = new jMenuOperations.add(jMenuOperati jMenuOperationsItemFermer.setTex } { jMenuOperationsItemSolde = new J jMenuOperations.add(jMenuOperationsItemSolde); jMenuOperationsItemSolde.setText("} { jMenuOperationsItemDepot = new JMenuItem(); jMenuOperations.add(jMenuOperationsItemDepot); jMenuOperationsItemDepot.setText("} { jMenuOperationsItemRetrait = new jMenuOperations.add(jMenuOperationsItemRetrait); jMenuOperationsItemRetrait .setText("Retrait d’un compte"); } { jMenuOperationsItemHistorique = jMenuOperations.add(jMenuOperationsItemHistorique); jMenuOperationsItemHistorique .setText("Historique d’un } } } } catch (Exception e) { e.printStackTrace(); } } }

Page 53: Corrige tp java

Classe GUIBankLocalServer import java.util.*; /** * Classe conteneur. Contient : * - FunnyMoney la monnaie utilisee * - BankingException une exception bancaire * - Server la banque **/ /** * Cette classe simple represente un montant monetaire. N’est qu’un emballage * d’un entier. **/ class FunnyMoney { public int amount; public FunnyMoney(int amount) { this.amount = amount; } } public class GUIBankLocalServer { /** * Classe imbriquee pour stocker les donnees d’un compte bancaire **/ class Account { String password; // mot de passe int balance; // solde du compte ArrayList transactions = new ArrayList(); // historique des transactions Account(String password) { this.password = password; this.balance = 0; transactions.add("Compte ouvert le " + new Date()); } } /** * Cette table de hachage stocke tous les comptes ouverts et relie * chaque noms de compte a l’objet Account correspondant **/ HashMap accounts = new HashMap(); /** * Ouvre un compte avec le nom et le mot de passe specifie * Cette methode est synchronisee de facon qu’une seule thread * ne modifie a la fois la table des comptes. **/ public synchronized void openAccount(String name, String password) throws GUIBankingException { // Verifier s’il exsite deja un compte ayant ce nom if (accounts.get(name) != null) throw new GUIBankingException("Le compte existe deja."); // S’il n’existe pas, le creer Account acct = new Account(password);

Page 54: Corrige tp java

// Et l’enregsitrer accounts.put(name, acct); } /** * Cette methode utilitaire n’est pas une methode accessible de maniere * distante. Etant donnes un nom et un mot de passe, verifie s’il existe * un compte correspondant. Si oui, renvoie l’objet Account. Sinon, * leve une exception. **/ public Account verify(String name, String password) throws GUIBankingException { synchronized(accounts) { Account acct = (Account)accounts.get(name); if (acct == null) throw new GUIBankingException("Compte inexistant"); if (!password.equals(acct.password)) throw new GUIBankingException("Mot de passe invalide"); return acct; } } /** * Ferme le compte dont on donne le nom. Methode synchronisee **/ public synchronized FunnyMoney closeAccount(String name, String password) throws GUIBankingException { Account acct; acct = verify(name, password); accounts.remove(name); // Avant de changer le solde ou effectuer une transaction sur un compte, // il faut d’abord acquerir un verrou sur ce compte synchronized (acct) { int balance = acct.balance; acct.balance = 0; return new FunnyMoney(balance); } } /** Deposer le montant specifie su le compte dont on donne le nom */ public void deposit(String name, String password, FunnyMoney money) throws GUIBankingException { Account acct = verify(name, password); synchronized(acct) { acct.balance += money.amount; acct.transactions.add(money.amount + " pieces deposees le " + new Date()); } } /** Effectue un retrait d’un montant specifie */

Page 55: Corrige tp java

public FunnyMoney withdraw(String name, String password, FunnyMoney money) throws GUIBankingException { int amount = money.amount; Account acct = verify(name, password); synchronized(acct) { if (acct.balance < amount) throw new GUIBankingException("Solde insuffisant"); acct.balance -= amount; acct.transactions.add("Retrait de " + amount + " le "+new Date()); return new FunnyMoney(amount); } } /** Renvoie le solde du compte dont on donne le nom */ public FunnyMoney getBalance(String name, String password) throws GUIBankingException { Account acct = verify(name, password); synchronized(acct) { return new FunnyMoney(acct.balance); } } /** * Renvoie un vecteur de String contenant l’historique pour * le compte dont on donne le nom **/ public ArrayList getTransactionHistory(String name, String password) throws GUIBankingException { Account acct = verify(name, password); synchronized(acct) { return acct.transactions; } } } Fenêtres de dialogue Classe NomMotPasseDialog import javax.swing.JFrame; /** * This code was generated using CloudGarden’s Jigloo * SWT/Swing GUI Builder, which is free for non-commercial * use. If Jigloo is being used commercially (ie, by a corporation, * company or business for any purpose whatever) then you * should purchase a license for each developer using Jigloo. * Please visit www.cloudgarden.com for details. * Use of Jigloo implies acceptance of these licensing terms. * ************************************* * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED * for this machine, so Jigloo or this code cannot be used legally * for any corporate or commercial purpose. * ************************************* */ import javax.swing.JLabel; import javax.swing.JButton; import javax.swing.JTextField;

Page 56: Corrige tp java

import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class NomMotPasseDialog extends javax.swing.JDialog { private JPanel jPanelNomMotPasseDialog; private JLabel jLabelStrNom; private JButton jButtonOK; private JTextField jTextFieldMontant; private JTextField jTextFieldMotDePasse; private JTextField jTextFieldNom; private JLabel jLabelStrMontant; private JLabel jLabelStrMotDePasse; protected String name = null; protected String password = null; protected int montant = -1; public NomMotPasseDialog(JFrame frame, boolean modal) { super(frame, modal); initGUI(); } void actionPerformedNomPass(ActionEvent e) { name = new String(jTextFieldNom.getText().trim()); password = new String(jTextFieldMotDePasse.getText().trim()); if (jTextFieldMontant.isVisible()) { montant = Integer.parseInt(jTextFieldMontant.getText().trim()); jTextFieldMontant.setText(""); } jTextFieldNom.setText(""); jTextFieldMotDePasse.setText(""); this.setVisible(false); } public void partialShow() { this.jLabelStrMontant.setVisible(false); this.jTextFieldMontant.setVisible(false); this.setVisible(true); this.jLabelStrMontant.setVisible(true); this.jTextFieldMontant.setVisible(true); } public String getName() { return name; } public String getPassword() { return password; } public FunnyMoney getAmount() { return new FunnyMoney(montant); } private void initGUI() { try { setSize(400, 300); { jPanelNomMotPasseDialog = new JPanel(); this.getContentPane().add( jPanelNomMotPasseDialog, BorderLayout.CENTER); jPanelNomMotPasseDialog.setLayout(null);

Page 57: Corrige tp java

jPanelNomMotPasseDialog.setPreferredSize(new java.awt.Dimension(315, 200)); { jLabelStrNom = new JLabel(); jPanelNomMotPasseDialog.add(jLabelStrNom); jLabelStrNom.setText("Nom"); jLabelStrNom.setBounds(43, 31, 60, 30); } { jLabelStrMotDePasse = new JLabel(); jPanelNomMotPasseDialog.add(jLabelStrMotDePasse); jLabelStrMotDePasse.setText("Mot de passe"); jLabelStrMotDePasse.setBounds(43, 71, 93, 30); } { jLabelStrMontant = new JLabel(); jPanelNomMotPasseDialog.add(jLabelStrMontant); jLabelStrMontant.setText("Montant"); jLabelStrMontant.setBounds(43, 114, 60, 30); } { jTextFieldNom = new JTextField(); jPanelNomMotPasseDialog.add(jTextFieldNom); jTextFieldNom.setText(" "); jTextFieldNom.setBounds(141, 31, 60, 30); } { jTextFieldMotDePasse = new JTextField(); jPanelNomMotPasseDialog.add(jTextFieldMo jTextFieldMotDePasse.setText(" jTextFieldMotDePasse.setBounds(141, 71, } { jTextFieldMontant = new JTextField(); jPanelNomMotPasseDialog.add(jTextFieldMontant); jTextFieldMontant.setText(" jTextFieldMontant.setBounds(141, 114, 60, } { jButtonOK = new JButton(); jPanelNomMotPasseDialog.add(jButtonOK); jButtonOK.setText("OK"); jButtonOK.setBounds(267, 184, 60, 30); jButtonOK.addActionListener(new ActionListener() public void actionPerformed(ActionEvent actionPerformedNomPass(evt); }); } } } catch (Exception e) { e.printStackTrace(); } } /** * Auto-generated method for setting the popup menu for a component */ private void setComponentPopupMenu(

Page 58: Corrige tp java

final java.awt.Component parent, final javax.swing.JPopupMenu menu) { parent.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } public void mouseReleased(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } }); } } Classe GUIBankingException /** * Type d’exception bancaire, comme "Solde insuffisant" ou "Mot de passe invalide" **/ public class GUIBankingException extends Exception { static BankingExceptionDialog dialog = new BankingExceptionDialog(null, true); protected String message; public GUIBankingException(String msg) { message = msg; } public String getMessage() { return message; } public void showErrorMessage(String msg) { dialog.setMessage(msg); dialog.setVisible(true); } } Classe BankingExceptionDialog import javax.swing.JFrame; /** * This code was generated using CloudGarden’s Jigloo * SWT/Swing GUI Builder, which is free for non-commercial * use. If Jigloo is being used commercially (ie, by a corporation, * company or business for any purpose whatever) then you * should purchase a license for each developer using Jigloo. * Please visit www.cloudgarden.com for details. * Use of Jigloo implies acceptance of these licensing terms. * ************************************* * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED * for this machine, so Jigloo or this code cannot be used legally * for any corporate or commercial purpose. * ************************************* */ import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JButton;

Page 59: Corrige tp java

import java.awt.BorderLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class BankingExceptionDialog extends javax.swing.JDialog { private JPanel jPanelBankingExceptionDialog; private JButton jButtonOK; private JLabel jLabelMessageErreur; public BankingExceptionDialog(JFrame frame, boolean modal) { super(frame, modal); initGUI(); } void actionPerformedOK(ActionEvent e) { this.setVisible(false); } public void setMessage(String m) { jLabelMessageErreur.setText(m); } private void initGUI() { try { setSize(400, 300); { jPanelBankingExceptionDialog = new JPanel(); this.getContentPane().add( jPanelBankingExceptionDialog, BorderLayout.CENTER); jPanelBankingExceptionDialog.setLayout(null); { jLabelMessageErreur = new JLabel(); jPanelBankingExceptionDialog.add(jLabelMessageErreur); jLabelMessageErreur.setText(" "); jLabelMessageErreur.setBounds(47, 52, 303, } { jButtonOK = new JButton(); jPanelBankingExceptionDialog.add(jButtonOK); jButtonOK.setText("OK"); jButtonOK.setBounds(162, 197, 60, 30); jButtonOK.addActionListener(new ActionListener() public void actionPerformed(ActionEvent actionPerformedOK(evt); } }); } } } catch (Exception e) { e.printStackTrace(); } } /** * Auto-generated method for setting the popup menu for a component */ private void setComponentPopupMenu( final java.awt.Component parent,

Page 60: Corrige tp java

final javax.swing.JPopupMenu menu) { parent.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } public void mouseReleased(java.awt.event.MouseEvent e) { if (e.isPopupTrigger()) menu.show(parent, e.getX(), e.getY()); } }); } }

Gestion de threads et programmation concurrente

Exercices d’introduction aux activités (threads) Java – Solutions

Solution de l’ex. 1 Une horloge simpliste /* A class with one thread, implementing a Digital Clock */ import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DigitalThread extends java.applet.Applet implements Runnable { Font theFont = new Font("TimesRoman",Font.BOLD,24); Date theDate; Thread runner; // override the applet start method public void start() { if (runner == null);

Page 61: Corrige tp java

{ // construct an instance of a thread and use the run method // from "this" applet runner = new Thread(this); runner.start(); // call the thread start method } } // override the applet stop method public void stop() { if (runner != null) { runner.stop(); // call the thread stop method runner = null; } } // provide a method run to be the body of the thread // this method required by the runnable interface public void run() { while (true) { theDate = new Date(); // this method will call applet method update, // which will call paint below repaint(); // current thread will sleep for 1 second try { Thread.sleep(1000); } catch (InterruptedException e) { } } } // provide the applet paint method public void paint(Graphics g) { g.setFont(theFont); g.drawString(theDate.toString(),10,50); } } Solution de l’ex. 2 Affichage d’une série d’images : Duke fait la roue import java.io.InputStream; import java.applet.Applet; import java.awt.*; import java.net.*; /** * Une applet simple pour jouer en bocle une serie d’images, * le tag "img" indique que suite d’images doit etre jouee * */ public class TDuke extends Applet implements Runnable { /** * The current loop slot. */

Page 62: Corrige tp java

int loopslot = 0; String dir; // Rep ou URL des images Thread kicker = null; // Activite animatrice int pause; // pause entre les images int offset; int off; int speed; int nimgs; Image imgs[]; // tableau des images int maxWidth; public void run() { dir = "ImagesTumbleDuke"; nimgs = 16; setBackground(Color.gray); Thread.currentThread().setPriority(Thread.NORM_PRIORITY-1); imgs = new Image[nimgs]; for (int i = 1; i < nimgs; i++) { imgs[i] = getImage(getDocumentBase(), dir + "/T" + i + ".gif"); } Dimension d = getSize(); while (kicker != null) { if (++loopslot >= nimgs) { loopslot = 0; } repaint(); try { Thread.sleep(300); } catch (InterruptedException e) { break; } }// while (kicker != null) } public void paint(Graphics g) { if ((imgs != null) && (loopslot < nimgs) && (imgs[loopslot] != null)) { g.drawImage(imgs[loopslot], 0, 0, this); } } public void start() { if (kicker == null) { kicker = new Thread(this); kicker.start(); } } public void stop() { if (kicker != null) { kicker.stop(); kicker = null; } } }

Page 63: Corrige tp java

Solution de l’ex. 3 Une horloge avec affichage graphique import java.awt.*; import java.applet.*; import java.util.Date; public class GraphicClock extends Applet implements Runnable { Thread myThread; public void init() { } public void start() { myThread = new Thread(this); myThread.start(); } Date date; int hours, minutes, seconds, clockHours, clockMinutes, clockSeconds; String time; public void run() { for (;;) { // Prendre la date et l’heure systeme date = new Date(); hours = date.getHours(); // Conversion des heures, minutes, secondes en degres // (de 0 a 360) // Le signe - est necessaire a cause de fillArc() clockHours = -(hours>=12 ? hours - 12 : hours) * 30; minutes = date.getMinutes(); clockMinutes = -minutes * 6; seconds = date.getSeconds(); clockSeconds = -seconds * 6; time = "" + hours + ":" + minutes + ":" + seconds; repaint(); try { myThread.sleep(1000); } catch (InterruptedException e) {} } } public void stop() { if (myThread!= null) { myThread.stop(); myThread = null; } } public void paint(Graphics g) { g.setColor(Color.blue); g.fillArc(10,10,100,100,90,clockSeconds); g.setColor(Color.red); g.fillArc(20,20,80,80,90,clockMinutes); g.setColor(Color.yellow); g.fillArc(30,30,60,60,90,clockHours); g.setColor(Color.blue); g.drawString(time,40, 125);

Page 64: Corrige tp java

} }

Exercices sur les threads autour d’une balle – Solutions

Solution de l’ex. 1 Une balle rebondissante (utilisation d’activité ou thread) Voici le bout de code HTML pour lancer l’applet à partir d’un navigateur : <APPLET CODE="BallField.class" WIDTH=300 HEIGHT=300></APPLET> Voici le code Java de la classe Ball, archétype d’une balle en mouvement. Notez que la balle elle-même n’est pas responsable de son mouvement. Elle est animée par la classe BallField dont le code est fourni ensuite. Cette architecture est de type maître/esclave, le maître étant ici BallField. Un autre type d’architecture est celle de type purement distribuée, où les balles sont chacune responsables de leur propre animation. Concrètement, cela impliquerait que chaque balle implante Runnable, alors qu’ici seul BallField implante Runnable. Un autre remarque cruciale : remarquez bien que l’accès à chaque champ ne peut (quasiment) se faire qu’au travers d’une méthode, que ce soit pour l’obtention d’une valeur ou la modification d’une valeur d’un champ. Code de Ball // // Ball : Disque en mouvement // import java.awt.*; public class Ball { protected int x, y; // position de la balle protected int size; // diametre de la balle protected int dx, dy; // vecteur deplacement protected int dt; // intervalle entre 2 affichages protected Color color; // couleur protected Color backgroundColor; // couleur du fond public Ball (int Xpos, int Ypos, int diameter, Color backColor) { x = Xpos; y = Ypos; size = diameter; dx = 0; dy = 0; dt = 0; // Initialemetnt inerte color = Color.red; // Initialement rouge backgroundColor = backColor; } // methodes fixant des attributs

Page 65: Corrige tp java

// public void setXY(int nPosX, int nPosY) { x = nPosX; y = nPosY; } public void setSize(int newSize) { size = newSize; } public void setDxDy (int ndx, int ndy) { dx = ndx; dy = ndy; } public void setDt (int ndt) { dt = ndt; } public void setColor (Color newColor) { color = newColor; } // methodes accedant aux attributs (accesseurs) // public int getX() { return x; } public int getY() { return y; } public int getSize() { return size; } public int getDx() { return dx; } public int getDy() { return dy; } public int getDt() { return dt; } public Color getColor() { return color; } // methodes modifiant des attributs // public void move() { x += dx; y += dy; } // Afficher la balle a sa position courante // public void paint(Graphics g) { // Astuce : pour eviter de voir un croissant rouge derriere la balle, // on dessine une balle en couleur de fond a l’endroit // precedent (c.a.d. aux coordonnees -dx, -dy) g.setColor(backgroundColor); g.fillOval(x-(size/2)-dx, y-(size/2)-dy, size, size); // Affichage proprement dit de la balle g.setColor(color); g.fillOval(x-(size/2), y-(size/2), size, size); } // Traiter le rebond sur les bords // public void xBounce() { dx = -dx; } public void yBounce() { dy = -dy; } }// public class Ball Code de BallField Elle anime la balle précédente. import java.applet.*; import java.awt.*; /* * Terrain a balle : responsable de lŠanimation de la balle */ public class BallField extends Applet implements Runnable { int x = 150, y = 50, size = 50; // position et rayon de la balle int dx = 11, dy = 7; // trajectoire de la balle int dt = 90; // nbre de ms entre 2 affichages Thread animationThread = null; // thread pour l’animation Ball theBall = null; volatile boolean stopped=true;

Page 66: Corrige tp java

/* * Initialisation de l’applet */ public void init() { animationThread = new Thread(this, "Animation de balle"); theBall = new Ball(x, y, size, Color.black); theBall.setDxDy(dx, dy); theBall.setDt(dt); // Fixer la couleur de fond ; cf. paint() de Ball setBackground(Color.black); } /* * Bouger, faire rebondir la balle et demander de redessiner. */ public void paint(Graphics g) { Dimension d = getSize(); int x, y, dx, dy, r; // position, direction et rayon de la balle // Initialisations x = theBall.getX(); y = theBall.getY(); dx = theBall.getDx(); dy = theBall.getDy(); r = theBall.getSize() / 2; // On rebondit si l’on a heurte un cote if ((x - r + dx < 0) || (x + r + dx > d.width)) { theBall.xBounce(); } if ((y - r + dy < 0) || (y + r + dy > d.height)) { theBall.yBounce(); } // Bouger la balle theBall.move(); // Demander au navigateur d’appeler la methode paint() pour // afficher la balle a sa nouvelle position theBall.paint(g); } /* * Demarrer l’activite lorsque le navigateur demarre l’applet */ public void start() { if (!animationThread.isAlive()) { animationThread.start(); } synchronized(this){ stopped=false; notify(); } }// start() /* * Arreter l’activite lorsque le navigateur interromp lŠapplet */ public void stop() { synchronized(this){ stopped=true; } }

Page 67: Corrige tp java

/* * Boucler indefiniment en appelant animer(), puis en se reposant */ public void run() { while (true) { repaint(); try { synchronized(this){ while(stopped){ wait(); } } Thread.sleep(theBall.getDt()); } catch (InterruptedException e) { break; } } }// run() }// class BallField On notera que dans la solution précédente, l’on utilise une variable de condition bolléenne stopped utilisée dans run() et modifiée dans start() et dans stop(). Un wait() dans run() déclenché par la condition stopped == true est associé à un notify() dans start(). Code de BallDoubleBuffering Nous donnons ici une solution au problème de clignotement de l’affichage qui apparaît habituellement. Cette technique, dite du double buffering, consiste à écrire les modifications d’affichage dans un plan mémoire (et non directement à l’écran), puis, une fois que l’ensemble de la fenêtre à afficher est prête, à affectuer l’affichage d’un coup. // This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com) // Copyright (c) 1997 by David Flanagan // This example is provided WITHOUT ANY WARRANTY either expressed or implied. // You may study, use, modify, and distribute it for non-commercial purposes. // For any commercial use, see http://www.davidflanagan.com/javaexamples import java.applet.*; import java.awt.*; /** * An applet that displays a simple animation using double-buffering * and clipping **/ public class BallDoubleBuffering extends Applet implements Runnable { int x = 150, y = 100, r=20; // Position and radius of the circle

Page 68: Corrige tp java

int dx = 8, dy = 5; // Trajectory of circle Dimension size; // The size of the applet Image buffer; // The off-screen image for double-buffering Graphics bufferGraphics; // A Graphics object for the buffer Thread animator; // Thread that performs the animation boolean please_stop; // A flag asking animation thread to stop /** Set up an off-screen Image for double-buffering */ public void init() { size = this.size(); buffer = this.createImage(size.width, size.height); bufferGraphics = buffer.getGraphics(); } /** Draw the circle at its current position, using double-buffering */ public void paint(Graphics g) { // Draw into the off-screen buffer. // Note, we could do even better clipping by setting the clip rectangle // of bufferGraphics to be the same as that of g. // In Java 1.1: bufferGraphics.setClip(g.getClip()); bufferGraphics.setColor(this.getBackground()); bufferGraphics.fillRect(0, 0, size.width, size.height); // clear the buffer bufferGraphics.setColor(Color.red); bufferGraphics.fillOval(x-r, y-r, r*2, r*2); // draw the circle // Then copy the off-screen buffer onto the screen g.drawImage(buffer, 0, 0, this); } /** Don’t clear the screen; just call paint() immediately * It is important to override this method like this for double-buffering */ public void update(Graphics g) { paint(g); } /** The body of the animation thread */ public void run() { while(!please_stop) { // Bounce the circle if we’ve hit an edge. if ((x - r + dx < 0) || (x + r + dx > size.width)) dx = -dx; if ((y - r + dy < 0) || (y + r + dy > size.height)) dy = -dy; // Move the circle. x += dx; y += dy; // Ask the browser to call our paint() method to redraw the circle // at its new position. Tell repaint what portion of the applet needs // be redrawn: the rectangle containing the old circle and the // the rectangle containing the new circle. These two redraw requests // will be merged into a single call to paint() repaint(x-r-dx, y-r-dy, 2*r, 2*r); // repaint old position of circle

Page 69: Corrige tp java

repaint(x-r, y-r, 2*r, 2*r); // repaint new position of circle // Now pause 1/10th of a second before drawing the circle again. try { Thread.sleep(100); } catch (InterruptedException e) { ; } } animator = null; } /** Start the animation thread */ public void start() { if (animator == null) { please_stop = false; animator = new Thread(this); animator.start(); } } /** Stop the animation thread */ public void stop() { please_stop = true; } /** Allow the user to start and stop the animation by clicking */ public boolean mouseDown(Event e, int x, int y) { if (animator != null) please_stop = true; // if running request a stop else start(); // otherwise start it. return true; } } Solution de l’ex. 2 Formes symétriques, balles et pavés (emploi de l’héritage) Code de SymetricSurface // // Archetype d’une surface symetrique simple // import java.awt.*; public abstract class SymetricSurface { protected int x, y; // position de la balle protected int size; // diametre de la balle protected Color color; // couleur // methodes fixant des attributs // public void setXY(int nPosX, int nPosY) { x = nPosX; y = nPosY; } public void setSize (int newSize) { size = newSize; } public void setColor (Color newColor) { color = newColor; } // methodes accedant aux attributs (accesseurs) // public int getX() { return x; } public int getY() { return y; } public int getSize() { return size; } // Afficher la surface // public abstract void paint(Graphics g);

Page 70: Corrige tp java

}// public abstract class SymetricSurface Code de la classe SymSurfDisk import java.awt.*; public class SymSurfDisk extends SymetricSurface{ public SymSurfDisk(int Xpos, int Ypos, int radius) { x = Xpos; y = Ypos; size = radius; color = Color.red; // Initialement rouge } // Afficher le disque // public void paint(Graphics g) { g.setColor(color); g.fillOval(x-(size/2), y-(size/2), size, size); } }// public class SymSurfDisk Code de la classe SymSurfSquare import java.awt.*; public class SymSurfSquare extends SymetricSurface { public SymSurfSquare(int Xpos, int Ypos, int height) { x = Xpos; y = Ypos; size = height; color = Color.red; // Initialement rouge } // Afficher le disque // public void paint(Graphics g) { g.setColor(color); g.fillRect(x-(size/2), y-(size/2), size, size); } }// public class SymSurfSquare Code de la classe SymSurfBall // // SymSurfBall : Disque en mouvement herite de SymSurfDisk // import java.awt.*; public class SymSurfBall extends SymSurfDisk{ protected int dx, dy; // vecteur deplacement protected int dt; // intervalle entre 2 affichages public SymSurfBall (int Xpos, int Ypos, int diameter) { super(Xpos, Ypos, diameter); dx = 0; dy = 0; dt = 0; // Initialemetnt inerte color = Color.red; // Initialement rouge } // methodes fixant des attributs // public void setDxDy (int ndx, int ndy) { dx = ndx; dy = ndy; } public void setDt (int ndt) { dt = ndt; } // methodes accedant aux attributs (accesseurs) // public int getDx() { return dx; } public int getDy() { return dy; }

Page 71: Corrige tp java

public int getDt() { return dt; } // methodes modifiant des attributs // public void move() { x += dx; y += dy; } // Afficher la balle a sa position courante // // public void paint(Graphics g) { // g.setColor(color); // g.fillOval(x-(size/2), y-(size/2), size, size); // } // Traiter le rebond sur les bords // public void xBounce() { dx = -dx; } public void yBounce() { dy = -dy; } }// public class Ball Code de la classe SymSurfPavingStone // // SymSurfBall : Disque en mouvement herite de SymSurfDisk // import java.awt.*; public class SymSurfPavingStone extends SymSurfSquare { protected int dx, dy; // vecteur deplacement protected int dt; // intervalle entre 2 affichages public SymSurfPavingStone(int Xpos, int Ypos, int diameter) { super(Xpos, Ypos, diameter); dx = 0; dy = 0; dt = 0; // Initialemetnt inerte color = Color.red; // Initialement rouge } // methodes fixant des attributs // public void setDxDy (int ndx, int ndy) { dx = ndx; dy = ndy; } public void setDt (int ndt) { dt = ndt; } // methodes accedant aux attributs (accesseurs) // public int getDx() { return dx; } public int getDy() { return dy; } public int getDt() { return dt; } // methodes modifiant des attributs // public void move() { x += dx; y += dy; } // Afficher la balle a sa position courante // // public void paint(Graphics g) { // g.setColor(color); // g.fillOval(x-(size/2), y-(size/2), size, size); // } // Traiter le rebond sur les bords // public void xBounce() { dx = -dx; } public void yBounce() { dy = -dy; } }// public class SymSurfPavingStone

Page 72: Corrige tp java

Code de la classe SymSurfBallPavingStoneField import java.applet.*; import java.awt.*; /* * Terrain a balle : responsable de l’animation de la balle */ public class SymSurfBallPavingStoneField extends Applet implements Runnable { int x = 150, y = 50, size = 50; // position et taille des objets int dx = 11, dy = 7; // trajectoire possible int dt = 60; // nbre de ms entre 2 affichages Thread animationThread = null; // thread pour l’animation SymSurfBall theBall = null; SymSurfPavingStone theSquare = null; /* * Initialisation de l’applet */ public void init() { animationThread = new Thread(this, "Animation de balle et carre"); theBall = new SymSurfBall(x, y, size); theSquare = new SymSurfPavingStone(x, y, size); theBall.setDxDy(dx, dy); theSquare.setDxDy(dx+4, dy-4); theBall.setDt(dt); theSquare.setDt(dt); } /* * Bouger, faire rebondir la balle et demander de redessiner. */ public void paint(Graphics g) { Dimension d = getSize(); int x, y, dx, dy, r; // position, direction et taille // Initialisations pour la balle x = theBall.getX(); y = theBall.getY(); dx = theBall.getDx(); dy = theBall.getDy(); r = theBall.getSize() / 2; // On fait rebondir la balle si l’on a heurte un cote if ((x - r + dx < 0) || (x + r + dx > d.width)) theBall.xBounce(); if ((y - r + dy < 0) || (y + r + dy > d.height)) theBall.yBounce(); // Initialisations pour le carre x = theSquare.getX(); y = theSquare.getY(); dx = theSquare.getDx(); dy = theSquare.getDy(); r = theSquare.getSize() / 2; // On fait rebondir le carre si l’on a heurte un cote if ((x - r + dx < 0) || (x + r + dx > d.width)) theSquare.xBounce(); if ((y - r + dy < 0) || (y + r + dy > d.height)) theSquare.yBounce(); // Bouger la balle et le carre

Page 73: Corrige tp java

theBall.move(); theSquare.move(); // Demander au navigateur d’appeler la methode paint() pour // afficher la balle et le carre a leurs nouvelles position theBall.paint(g); theSquare.paint(g); } /* * Demarrer l’activite lorsque le navigateur demarre l’applet */ public void start() { if (animationThread.isAlive()) { animationThread.resume(); // Deprecie // Non deprecie, mais ne marche pas ... // synchronized (animationThread) { animationThread.notify(); } } else animationThread.start(); }// start() /* * Arreter l’activite lorsque le navigateur interromp l’applet */ public void stop() { animationThread.suspend(); // Deprecie // Non deprecie, mais ne marche pas ... // try { synchronized (animationThread) { animationThread.wait(); } // } catch (InterruptedException e) { ; } }// stop() /* * Boucler indefiniment en appelant animer(), puis en se reposant */ public void run() { while (true) { repaint(); try { Thread.sleep(theBall.getDt()); } catch (InterruptedException e) { break; } } }// run() }// class SymSurfBallPavingStoneField Solution de l’ex. 3 Balles et pavés polychormes (emploi d’interface) Code de PolychromicBall // // PolychromicBall : Disque polychrome en mouvement // import java.awt.*; public class PolychromicBall extends Ball implements Polychrome {

Page 74: Corrige tp java

public PolychromicBall (int Xpos, int Ypos, int diameter) { super(Xpos, Ypos, diameter, Color.red); } // Traiter les changements de couleur // public void changeColor(Color colorToChange) { if (colorToChange.equals(Color.red)) color = Color.blue; else color = Color.red; } }// public class PolychromicBall Code de PolychromicBallField import java.applet.*; import java.awt.*; /* * Terrain a balle polychrome : responsable de l’animation de la balle */ public class PolychromicBallField extends Applet implements Runnable { int x = 150, y = 50, size = 50; // position et rayon de la balle int dx = 11, dy = 7; // trajectoire de la balle int dt = 60; // nbre de ms entre 2 affichages Thread animationThread = null; // thread pour l’animation PolychromicBall theBall = null; /* * Initialisation de l’applet */ public void init() { animationThread = new Thread(this, "Animation de balle"); theBall = new PolychromicBall(x, y, size); theBall.setDxDy(dx, dy); theBall.setDt(dt); } /* * Bouger, faire rebondir la balle et demander de redessiner. */ public void paint(Graphics g) { Dimension d = getSize(); int x, y, dx, dy, r; // position, direction et rayon de la balle // Initialisations x = theBall.getX(); y = theBall.getY(); dx = theBall.getDx(); dy = theBall.getDy(); r = theBall.getSize() / 2; // On rebondit si l’on a heurte un cote if ((x - r + dx < 0) || (x + r + dx > d.width)) { theBall.changeColor(theBall.color); theBall.xBounce(); } if ((y - r + dy < 0) || (y + r + dy > d.height)) {

Page 75: Corrige tp java

theBall.changeColor(theBall.color); theBall.yBounce(); } // Bouger la balle theBall.move(); // Demander au navigateur d’appeler la methode paint() pour // afficher la balle a sa nouvelle position theBall.paint(g); } /* * Demarrer l’activite lorsque le navigateur demarre l’applet */ public void start() { if (animationThread.isAlive()) { animationThread.resume(); // Deprecie // Non deprecie, mais ne marche pas ... // synchronized (animationThread) { animationThread.notify(); } } else animationThread.start(); }// start() /* * Arreter l’activite lorsque le navigateur interromp l’applet */ public void stop() { animationThread.suspend(); // Deprecie // Non deprecie, mais ne marche pas ... // try { synchronized (animationThread) { animationThread.wait(); } // } catch (InterruptedException e) { ; } }// stop() /* * Boucler indefiniment en appelant animer(), puis en se reposant */ public void run() { while (true) { repaint(); try { Thread.sleep(theBall.getDt()); } catch (InterruptedException e) { break; } } }// run() }// class BallField

Exercices Java sur les threads autour de plusieurs balles – Solutions

Solution de l’ex. 1 Remplissage avec 2 types de balles

Page 76: Corrige tp java

(synchronisation d’activités) Solution à la question 2/ import java.awt.*; public class StackableTwoBallsField extends Frame { protected static int frameWidth = 400; protected static int frameHeight = 300; protected Canvas canvas; public static void main (String [] args) { Frame lesBalles = new StackableTwoBallsField(); lesBalles.setSize (frameWidth, frameHeight); lesBalles.setVisible(true); } public StackableTwoBallsField () { setLayout(new BorderLayout()); canvas = new Canvas(); add(canvas, BorderLayout.CENTER); canvas.setSize((int)(0.9*frameWidth), (int)(0.9*frameHeight)); setTitle ("N Balles"); Dimension d = canvas.getSize(); int ballSize = (int) (d.height / 10); SharedBoardTwoBalls tableau = new SharedBoardTwoBalls(canvas, ballSize, ballSize); StackBallTwoBalls redBall = new StackBallTwoBalls(canvas, tableau, Color.red, ballSize, ballSize); StackBallTwoBalls greenBall = new StackBallTwoBalls(canvas, tableau, Color.green, ballSize, ballSize); redBall.start(); greenBall.start(); } }// class StackableTwoBallsField class SharedBoardTwoBalls { private int posLibreX; private int posLibreY; private int tailleBalleX; private int tailleBalleY; private Canvas box; public SharedBoardTwoBalls(Canvas c, int tailleX, int tailleY) { box = c; tailleBalleX = tailleX; tailleBalleY = tailleY; posLibreX = tailleX; posLibreY = tailleY; } public Point nextFreePlace()

Page 77: Corrige tp java

{ Dimension d = box.getSize(); if (posLibreY >= d.height) return(null); posLibreX += tailleBalleX; if (posLibreX >= d.width) { posLibreX = tailleBalleX; posLibreY += tailleBalleY; } Point caseLibre = new Point(posLibreX, posLibreY); return(caseLibre); } // Affiche une balle a l’endroit specifie public void draw(int x, int y, Color theColor) { Graphics g = box.getGraphics(); if (g != null) { g.setColor(theColor); g.fillOval(x, y, tailleBalleX, tailleBalleY); g.dispose(); } } }// class SharedBoard // Classe StackBall qui est une Thread class StackBallTwoBalls extends Thread { protected Canvas box; protected int tailleBalleX; protected int tailleBalleY; protected Color color; protected SharedBoardTwoBalls tableau; public StackBallTwoBalls(Canvas c, SharedBoardTwoBalls tab, Color coul, int tailleX, int tailleY) { box = c; tableau = tab; color = coul; tailleBalleX = tailleX; tailleBalleY = tailleY; } public void run() { while(true) { synchronized (tableau) { Point caseLibre = tableau.nextFreePlace(); if (caseLibre != null) { tableau.draw(caseLibre.x, caseLibre.y, color); } else break; }

Page 78: Corrige tp java

try { Thread.sleep(10); } catch(InterruptedException e) {} } System.out.println("L’activite " + this + " a fini"); } } Solution à la qestion 3/ import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; public class StackableBallField extends Frame implements ActionListener { protected static int frameWidth = 400; protected static int frameHeight = 300; protected int ballSize; protected Canvas canvas; protected Vector vecteurBalles; protected int tailleVecteurBalles = 2; public static void main (String [] args) { Frame lesBalles = new StackableBallField(); lesBalles.setSize (frameWidth, frameHeight); lesBalles.setVisible(true); } public StackableBallField () { setLayout(new BorderLayout()); canvas = new Canvas(); add(canvas, BorderLayout.CENTER); setTitle ("N Balles"); Panel p = new Panel(); Button b1 = new Button("Demarrer"); b1.addActionListener(this); p.add(b1); Button b2 = new Button("Fermer"); b2.addActionListener(this); p.add(b2); add(p, BorderLayout.SOUTH); } private Vector creerVecteurBalles() { Vector vecteur = null; try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); Dimension d = canvas.getSize(); ballSize = (int) (0.9 * d.height / 10); SharedBoard tableau = new SharedBoard(canvas, ballSize, ballSize); System.out.println("Entrez le nombre de balles : "); String ligne = in.readLine(); tailleVecteurBalles = Integer.parseInt(ligne);

Page 79: Corrige tp java

vecteur = new Vector(tailleVecteurBalles); for (int i = 0; i < tailleVecteurBalles; i++) { int priorite = Thread.MIN_PRIORITY - 1; while ((priorite < Thread.MIN_PRIORITY) || (priorite > Thread.MAX_PRIORITY)) { System.out.println("Priorite de la balle " + i); ligne = in.readLine(); priorite = Integer.parseInt(ligne); } int rouge = (int)(255*Math.random()); int vert = (int)(255*Math.random()); int bleu = (int)(255*Math.random()); Color couleur = new Color(rouge, vert, bleu); StackBall nouvelleBalle = new StackBall(canvas, tableau, couleur, ballSize, ballSize); vecteur.addElement((Object)nouvelleBalle); nouvelleBalle.setPriority(priorite); } } catch (IOException e) { ; } return(vecteur); } public void actionPerformed(ActionEvent evt) { if (evt.getActionCommand().equals("Demarrer")) { // Creation vecteurBalles = creerVecteurBalles(); // Lancement for (int i = 0; i < tailleVecteurBalles; i++) { StackBall uneBalle = (StackBall) vecteurBalles.elementAt(i); uneBalle.start(); } // Destruction vecteurBalles.removeAllElements(); vecteurBalles = null; } else if (evt.getActionCommand().equals("Fermer")) System.exit(0); } }// class NBalles class SharedBoard { private int posLibreX; private int posLibreY; private int tailleBalleX; private int tailleBalleY; private Canvas box; public SharedBoard(Canvas c, int tailleX, int tailleY) { box = c;

Page 80: Corrige tp java

tailleBalleX = tailleX; tailleBalleY = tailleY; posLibreX = tailleX; posLibreY = tailleY; } public Point nextFreePlace() { Dimension d = box.getSize(); if (posLibreY >= d.height) return(null); posLibreX += tailleBalleX; if (posLibreX >= d.width) { posLibreX = tailleBalleX; posLibreY += tailleBalleY; } Point caseLibre = new Point(posLibreX, posLibreY); return(caseLibre); } // Affiche une balle a l’endroit specifie public void draw(int x, int y, Color theColor) { Graphics g = box.getGraphics(); g.setColor(theColor); g.fillOval(x, y, tailleBalleX, tailleBalleY); // g.dispose(); } }// class SharedBoard // Classe StackBall qui est une Thread class StackBall extends Thread { protected Canvas box; protected int tailleBalleX; protected int tailleBalleY; protected Color color; protected SharedBoard tableau; public StackBall(Canvas c, SharedBoard tab, Color coul, int tailleX, int tailleY) { box = c; tableau = tab; color = coul; tailleBalleX = tailleX; tailleBalleY = tailleY; } public void run() { while(true) { synchronized (tableau) { Point caseLibre = tableau.nextFreePlace(); if (caseLibre != null) { tableau.draw(caseLibre.x, caseLibre.y, color); }

Page 81: Corrige tp java

else break; } // Ceci n’est pas ideal avec les priorites ... // try { Thread.sleep(10); } catch(InterruptedException e) {} Thread.yield(); } System.out.println("L’activite " + this + " a fini"); } } Solution de l’ex. 2 Plusieurs balles rebondissantes (emploi de plusieurs activités) import java.awt.*; import java.awt.event.*; public class BounceThread extends Frame implements ActionListener { private Canvas canvas; // Le constructeur initialise un Frame avec un Canvas au // centre et 2 boutons demarrer et fermer public BounceThread() { setLayout(new BorderLayout()); setTitle("BounceThread"); canvas = new Canvas(); add(canvas, BorderLayout.CENTER); Panel p = new Panel(); Button b1 = new Button("Demarrer"); b1.addActionListener(this); p.add(b1); Button b2 = new Button("Fermer"); b2.addActionListener(this); p.add(b2); add(p, BorderLayout.SOUTH); } public void actionPerformed(ActionEvent evt) { if (evt.getActionCommand().equals("Demarrer")) { int dxIni = (int) (5 * Math.random()); int dyIni = (int) (5 * Math.random()); Ball b = new Ball(canvas, dxIni, dyIni); b.start(); } else if (evt.getActionCommand().equals("Fermer")) System.exit(0); } public static void main(String[] args) { Frame f = new BounceThread(); f.setSize(400, 300); f.setVisible(true);

Page 82: Corrige tp java

} } // Classe balle qui est une Thread class Ball extends Thread { private Canvas box; private static final int XSIZE = 10; private static final int YSIZE = 10; private int x = 0; private int y = 0; private int dx = 2; private int dy = 2; public Ball(Canvas c) { box = c; } public Ball(Canvas c, int dxIni, int dyIni) { box = c; dx = dxIni; dy = dyIni; } // draws the ball in the current location public void draw() { Graphics g = box.getGraphics(); g.fillOval(x, y, XSIZE, YSIZE); g.dispose(); } public void move() { Graphics g = box.getGraphics(); // On utilise un mode XOR pour reecrire sur la position precedente g.setXORMode(box.getBackground()); g.setColor(Color.red); g.fillOval(x, y, XSIZE, YSIZE); x += dx; y += dy; Dimension d = box.getSize(); if (x < 0) { x = 0; dx = -dx; } if (x + XSIZE >= d.width) { x = d.width - XSIZE; dx = -dx; } if (y < 0) { y = 0; dy = -dy; } if (y + YSIZE >= d.height) { y = d.height - YSIZE; dy = -dy; } g.fillOval(x, y, XSIZE, YSIZE); g.dispose(); } public void run() { draw(); for (int i = 1; i <= 1000; i++) { move(); try { Thread.sleep(5); } catch(InterruptedException e) {} } } }

Page 83: Corrige tp java

Solution de l’ex. 3 Plusieurs balles rebondissantes avec gestion des collisions Une solution astucieuse est laissée à l’imagination de l’étudiant . . .

Programmation réseau

Page 84: Corrige tp java

Exercices de base sur les Sockets en Java – Solutions Solution de l’ex. 1 Service dir distant Code du client import java.io.*; import java.net.*; public class DirClient { public static final int DEFAULT_PORT = 6789; public static void usage() { System.out.println("Utilisation : " + "java DirClient <hostname> [<port>]"); System.exit(0); } public static void main(String[] args) { int port = DEFAULT_PORT; Socket s = null; // Analyser la specification de port if ((args.length != 1) && (args.length != 2)) usage(); if (args.length == 1) port = DEFAULT_PORT; else { try { port = Integer.parseInt(args[1]); } catch (NumberFormatException e) { usage(); } } try { // Creer une socket pour se connecter a la machine et au port s = new Socket(args[0], port); // Creer les flux pour lire et ecrire des lignes de texte // de et vers cette socket. DataInputStream sin = new DataInputStream(s.getInputStream()); PrintStream sout = new PrintStream(s.getOutputStream()); // Creer un flux pour lire des lignes de l’entree standard DataInputStream in = new DataInputStream(System.in); // Signaler que l’on est connecte System.out.println("Connecte a " + s.getInetAddress() + ":"+ s.getPort()); String line; while(true) { // afficher une invite System.out.print("Nom de repertoire (exit pour sortir) : "); System.out.flush(); // lire le nom du repertoire a lister line = in.readLine(); if (line == null) break; // L’envoyer au serveur sout.println(line); // Lire le nombre d’entrees du repertoire line = sin.readLine(); // Verifier si la connexion est fermee (par EOF) if (line == null) { System.out.println("Connection fermee par le serveur."); break;

Page 85: Corrige tp java

} int nbEntrees = Integer.parseInt(line); // Puis lire le nombre d’entrees voulu et les afficher for (int i = 0; i < nbEntrees; i++) { line = sin.readLine(); System.out.println(line); } } } catch (IOException e) { System.err.println(e); } // Etre sur de bien toujours fermer la socket finally { try { if (s != null) s.close(); } catch (IOException e2) { ; } } } } Code du serveur import java.io.*; import java.net.*; public class DirServer extends Thread { public final static int DEFAULT_PORT = 6789; protected int port; protected ServerSocket listen_socket; // Sortir avec un message d’erreur lorsqu’une exception survient public static void fail(Exception e, String msg) { System.err.println(msg + ": " + e); System.exit(1); } // Creer un ServerSocket pour y ecouter les demandes de connexions; // debuter l’execution de l’activite public DirServer(int port) { if (port == 0) port = DEFAULT_PORT; this.port = port; try { listen_socket = new ServerSocket(port); } catch (IOException e) { fail(e, "Exception en creation de socket serveur"); } System.out.println("Serveur : en ecoute sur le port no " + port); this.start(); } // Corps de l’activite serveur. Effectue une boucle infinie, ecoutant // et acceptant les connexions de clients. Pour chaque connexion, // creer un objet Connection pour gerer les communications via la // nouvelle socket. public void run() { try {

Page 86: Corrige tp java

while(true) { Socket client_socket = listen_socket.accept(); DirConnection c = new DirConnection(client_socket); } } catch (IOException e) { fail(e, "Exception en ecoute de connexions"); } } // Lancer le serveur, ecoutant sur un port eventuellement specifie public static void main(String[] args) { int port = 0; if (args.length == 1) { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { port = 0; } } new DirServer(port); } } // Activite gerant toutes les communications avec un client class DirConnection extends Thread { protected Socket client; protected DataInputStream in; protected PrintStream out; // Initialiser les flux et debuter l’activite public DirConnection(Socket client_socket) { client = client_socket; try { in = new DataInputStream(client.getInputStream()); out = new PrintStream(client.getOutputStream()); } catch (IOException e) { try { client.close(); } catch (IOException e2) { ; } System.err.println("Exception en obtention de flux de sockets : " + e); return; } this.start(); } // Fournit effectivement le service // Lire un ligne et la renvoyer inchangee public void run() { String line; int len; try { for(;;) { // lire un nom de repertoire line = in.readLine(); if ((line == null) || (line.equals("exit"))) break; // Obtenir la liste correspondante String theList[] = printDirectoryRecursively(line);

Page 87: Corrige tp java

// Envoyer le nombre d’entrees Integer nbEntries = new Integer(theList.length); out.println(nbEntries.toString()); // Envoyer le nom de chaque entree for(int i = 0; i < theList.length; i++) out.println(theList[i]); } } catch (IOException e) { ; } finally { try {client.close();} catch (IOException e2) {;} } } // run() String[] printDirectoryRecursively(String directory) { String[] files; // Convertir la chaine lue en File et s’assurer que le rep. existe File dir = new File(directory); if (!dir.isDirectory()) throw new IllegalArgumentException("DirServer : pas de rep. " + directory); // Obtenir les entrees files = dir.list(); return(files); } } Solution de l’ex. 2 Service à priorité variable Code du client import java.io.*; import java.net.*; public class PriorityEchoClient { public static final int DEFAULT_PORT = 6789; public static void usage() { System.out.println("Utilisation: java EchoClient <hostname> [<port>]"); System.exit(0); } public static void main(String[] args) { int port = DEFAULT_PORT; Socket s = null; // Analyser la specification de port if ((args.length != 1) && (args.length != 2)) usage(); if (args.length == 1) port = DEFAULT_PORT; else { try { port = Integer.parseInt(args[1]); } catch (NumberFormatException e) { usage(); } } try { // Creer une socket pour se connecter a la machine et au port s = new Socket(args[0], port); // Creer les flux pour lire et ecrire des lignes de texte // de et vers cette socket.

Page 88: Corrige tp java

DataInputStream sin = new DataInputStream(s.getInputStream()); PrintStream sout = new PrintStream(s.getOutputStream()); // Creer un flux pour lire des lignes de l’entree standard DataInputStream in = new DataInputStream(System.in); // Signaler que l’on est connecte System.out.println("Connecte a " + s.getInetAddress() + ":"+ s.getPort()); String line; while(true) { // afficher une invite System.out.print("EchoClient > "); System.out.flush(); // lire une ligne de stdin; verifier l’EOF line = in.readLine(); if (line == null) break; // L’envoyer au serveur sout.println(line); // Lire une ligne du serveur line = sin.readLine(); // Verifier si la connexion est fermee (par EOF) if (line == null) { System.out.println("Connection fermee par le serveur."); break; } // Puis ecrire la ligne sur stdout System.out.println(line); } } catch (IOException e) { System.err.println(e); } // Etre sur de bien toujours fermer la socket finally { try { if (s != null) s.close(); } catch (IOException e2) { ; } } } } Code du serveur import java.io.*; import java.net.*; public class PriorityEchoServer extends Thread { public final static int DEFAULT_PORT = 6789; protected int port; protected ServerSocket listen_socket; // Sortir avec un message d’erreur lorsqu’une exception survient public static void fail(Exception e, String msg) { System.err.println(msg + ": " + e); System.exit(1); } // Creer un ServerSocket pour y ecouter les demandes de connexions; // debuter l’execution de l’activite

Page 89: Corrige tp java

public PriorityEchoServer(int port) { if (port == 0) port = DEFAULT_PORT; this.port = port; try { listen_socket = new ServerSocket(port); } catch (IOException e) { fail(e, "Exception en creation de socket serveur"); } System.out.println("Serveur : en ecoute sur le port no " + port); this.start(); } // Corps de l’activite serveur. Effectue une boucle infinie, ecoutant // et acceptant les connexions de clients. Pour chaque connexion, // creer un objet Connection pour gerer les communications via la // nouvelle socket. public void run() { try { while(true) { Socket client_socket = listen_socket.accept(); PriorityConnection c = new PriorityConnection(client_socket); } } catch (IOException e) { fail(e, "Exception en ecoute de connexions"); } } // Lancer le serveur, ecoutant sur un port eventuellement specifie public static void main(String[] args) { int port = 0; if (args.length == 1) { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { port = 0; } } new PriorityEchoServer(port); } } // Activite gerant toutes les communications avec un client class PriorityConnection extends Thread { protected Socket client; protected DataInputStream in; protected PrintStream out; protected static int nbConnections = 1; protected static int priority = Thread.NORM_PRIORITY; // Initialiser les flux et debuter l’activite public PriorityConnection(Socket client_socket) { client = client_socket; try { in = new DataInputStream(client.getInputStream()); out = new PrintStream(client.getOutputStream()); }

Page 90: Corrige tp java

catch (IOException e) { try { client.close(); } catch (IOException e2) { ; } System.err.println("Exception en obtention de flux de sockets : " + e); return; } // Gestion des priorites if (nbConnections < Thread.MAX_PRIORITY - Thread.NORM_PRIORITY) this.setPriority(priority--); else this.setPriority(Thread.MIN_PRIORITY); nbConnections++; // Lancement du service this.start(); } // Fournit effectivement le service // Lire un ligne et la renvoyer inchangee public void run() { String line; int len; System.out.println("Service a priorite " + getPriority()); try { for(;;) { // lire une ligne line = in.readLine(); if (line == null) break; // ecrire la ligne out.println(line); } } catch (IOException e) { ; } finally { try {client.close();} catch (IOException e2) {;} } } } Solution de l’ex. 3 Serveur multi-services Code du client import java.io.*; import java.net.*; public class MultiServicesClient { public static final int DEFAULT_PORT = 6789; public static void usage() { System.out.println("Utilisation : " + "java EchoClient <hostname> <type_service> [<port>]"); System.exit(0); } public static void main(String[] args) { int port = DEFAULT_PORT; Socket s = null; // Analyser la specification de port if ((args.length != 2) && (args.length != 3)) usage(); if (args.length == 2) port = DEFAULT_PORT;

Page 91: Corrige tp java

else { try { port = Integer.parseInt(args[2]); } catch (NumberFormatException e) { usage(); } } try { // Creer une socket pour se connecter a la machine et au port s = new Socket(args[0], port); // Creer les flux pour lire et ecrire des lignes de texte // de et vers cette socket. DataInputStream sin = new DataInputStream(s.getInputStream()); PrintStream sout = new PrintStream(s.getOutputStream()); // Creer un flux pour lire des lignes de l’entree standard DataInputStream in = new DataInputStream(System.in); // Signaler que l’on est connecte System.out.println("Connecte a " + s.getInetAddress() + ":"+ s.getPort()); String nomService = new String(args[1]); sout.println(nomService); if (nomService.equals("echo")) { EchoClientService service = new EchoClientService(); service.execute(in, sin, sout); } if (nomService.equals("dir")) { DirClientService service = new DirClientService(); service.execute(in, sin, sout); } if (nomService.equals("date")) { DateClientService service = new DateClientService(); service.execute(in, sin, sout); } } catch (IOException e) { System.err.println(e); } // Etre sur de bien toujours fermer la socket finally { try { if (s != null) s.close(); } catch (IOException e2) { ; } } } } class EchoClientService { public void execute(DataInputStream in, DataInputStream sin, PrintStream sout) { try { String line; while(true) { // afficher une invite System.out.print("EchoService > "); System.out.flush(); // lire une ligne de stdin; verifier l’EOF line = in.readLine(); if (line == null) break; // L’envoyer au serveur

Page 92: Corrige tp java

sout.println(line); // Lire une ligne du serveur line = sin.readLine(); // Verifier si la connexion est fermee (par EOF) if (line == null) { System.out.println("Connection fermee par le serveur."); break; } // Puis ecrire la ligne sur stdout System.out.println(line); } } catch (IOException e) { System.err.println(e); } }// execute() }// class EchoClientService class DirClientService { public void execute(DataInputStream in, DataInputStream sin, PrintStream sout) { try { String line; while(true) { // afficher une invite System.out.print("Nom de repertoire (exit pour sortir) : "); System.out.flush(); // lire le nom du repertoire a lister line = in.readLine(); if (line == null) break; // L’envoyer au serveur sout.println(line); // Lire le nombre d’entrees du repertoire line = sin.readLine(); // Verifier si la connexion est fermee (par EOF) if (line == null) { System.out.println("Connection fermee par le serveur."); break; } int nbEntrees = Integer.parseInt(line); // Puis lire le nombre d’entrees voulu et les afficher for (int i = 0; i < nbEntrees; i++) { line = sin.readLine(); System.out.println(line); } } } catch (IOException e) { System.err.println(e); } } // execute }// class DirClientService class DateClientService { public void execute(DataInputStream in, DataInputStream sin, PrintStream sout) { try { String line; // afficher une invite

Page 93: Corrige tp java

System.out.print("DateService > "); System.out.flush(); // Lire la date du serveur line = sin.readLine(); // Verifier si la connexion est fermee (par EOF) if (line == null) { System.out.println("Connection fermee par le serveur."); return; } // Puis ecrire la ligne sur stdout System.out.println(line); } catch (IOException e) { System.err.println(e); } }// execute() }// class DateClientService Code du serveur import java.io.*; import java.net.*; import java.util.*; public class MultiServicesServer extends Thread { public final static int DEFAULT_PORT = 6789; protected int port; protected ServerSocket listen_socket; // Sortir avec un message d’erreur lorsqu’une exception survient public static void fail(Exception e, String msg) { System.err.println(msg + ": " + e); System.exit(1); } // Creer un ServerSocket pour y ecouter les demandes de connexions; // debuter l’execution de l’activite public MultiServicesServer(int port) { if (port == 0) port = DEFAULT_PORT; this.port = port; try { listen_socket = new ServerSocket(port); } catch (IOException e) { fail(e, "Exception en creation de socket serveur"); } System.out.println("Serveur : en ecoute sur le port no " + port); } // Corps de l’activite serveur. Effectue une boucle infinie, ecoutant // et acceptant les connexions de clients. Pour chaque connexion, // creer un objet Connection pour gerer les communications via la // nouvelle socket. public void run() { try { while(true) { Socket client_socket = listen_socket.accept(); Connection c = new Connection(client_socket); }

Page 94: Corrige tp java

} catch (IOException e) { fail(e, "Exception en ecoute de connexions"); } } // Lancer le serveur, ecoutant sur un port eventuellement specifie public static void main(String[] args) { int port = 0; if (args.length == 1) { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { port = 0; } } new MultiServicesServer(port); } } // Activite gerant toutes les communications avec un client class Connection extends Thread { protected Socket client; protected DataInputStream in; protected PrintStream out; // Initialiser les flux et debuter l’activite public Connection(Socket client_socket) { client = client_socket; try { in = new DataInputStream(client.getInputStream()); out = new PrintStream(client.getOutputStream()); } catch (IOException e) { try { client.close(); } catch (IOException e2) { ; } System.err.println("Exception en obtention de flux de sockets : " + e); return; } this.start(); } // Fournit effectivement le service // Lire un ligne et la renvoyer inchangee public void run() { try { // lire le service demande String nomService = in.readLine(); if (nomService == null) return; if (nomService.equals("echo")) { EchoServerService service = new EchoServerService(); service.execute(in, out); } else if (nomService.equals("dir")) { DirServerService service = new DirServerService(); service.execute(in, out); } else if (nomService.equals("date")) { DateServerService service = new DateServerService(); service.execute(in, out); } else

Page 95: Corrige tp java

System.out.println("Service " + nomService + "non disponible pour client " + client); } catch (IOException e) { ; } finally { try {client.close();} catch (IOException e2) {;} } } } class EchoServerService { public void execute(DataInputStream in, PrintStream out) { try { String line; while(true) { // lire une ligne line = in.readLine(); if (line == null) break; // ecrire la ligne out.println(line); } } catch (IOException e) { System.err.println(e); } }// execute() }// class EchoServerService class DirServerService { public void execute(DataInputStream in, PrintStream out) { String line; try { while(true) { // lire un nom de repertoire line = in.readLine(); if ((line == null) || (line.equals("exit"))) break; // Obtenir la liste correspondante String theList[] = printDirectoryRecursively(line); // Envoyer le nombre d’entrees Integer nbEntries = new Integer(theList.length); out.println(nbEntries.toString()); // Envoyer le nom de chaque entree for(int i = 0; i < theList.length; i++) out.println(theList[i]); } } catch (IOException e) { System.err.println(e); } }// execute() String[] printDirectoryRecursively(String directory) { String[] files; // Convertir la chaine lue en File et s’assurer que le rep. existe File dir = new File(directory); if (!dir.isDirectory()) throw new IllegalArgumentException("DirServer : pas de rep. " + directory); // Obtenir les entrees

Page 96: Corrige tp java

files = dir.list(); return(files); } }// class DirServerService class DateServerService { public void execute(DataInputStream in, PrintStream out) { Date theDate = new Date(); out.println(theDate.toString()); }// execute() }// class DateServerService

Exercices sur les sockets : serveur avec gestion de connexions – Solutions

Solution de l’ex. 1 Serveur Multi-activités avec un vautour Code du serveur import java.net.*; import java.io.*; import java.awt.*; import java.util.*; public class VultureServer extends Thread { public final static int DEFAULT_PORT = 6789; protected int port; protected ServerSocket listen_socket; protected ThreadGroup threadgroup; protected java.awt.List connection_list; protected Vector connections; protected Vulture vulture; // Exit with an error message, when an exception occurs. public static void fail(Exception e, String msg) { System.err.println(msg + ": " + e); System.exit(1); } // Create a ServerSocket to listen for connections on; start the thread. public VultureServer(int port) { // Create our server thread with a name. super("Server"); if (port == 0) port = DEFAULT_PORT; this.port = port; try { listen_socket = new ServerSocket(port); } catch (IOException e) { fail(e, "Exception creating server socket"); } // Create a threadgroup for our connections threadgroup = new ThreadGroup("Server Connections"); // Create a window to display our connections in Frame f = new Frame("Server Status"); connection_list = new java.awt.List(); f.add("Center", connection_list); f.resize(400, 200);

Page 97: Corrige tp java

f.setVisible(true); // Initialize a vector to store our connections in connections = new Vector(); // Create a Vulture thread to wait for other threads to die. // It starts itself automatically. vulture = new Vulture(this); // Start the server listening for connections this.start(); } // The body of the server thread. Loop forever, listening for and // accepting connections from clients. For each connection, // create a Connection object to handle communication through the // new Socket. When we create a new connection, add it to the // Vector of connections, and display it in the List. Note that we // use synchronized to lock the Vector of connections. The Vulture // class does the same, so the vulture won’t be removing dead // connections while we’re adding fresh ones. public void run() { try { while(true) { Socket client_socket = listen_socket.accept(); Connection c = new Connection(client_socket, threadgroup, 3, vulture); // prevent simultaneous access. synchronized (connections) { connections.addElement(c); connection_list.addItem(c.toString()); } } } catch (IOException e) { fail(e, "Exception while listening for connections"); } } // Start the server up, listening on an optionally specified port public static void main(String[] args) { int port = 0; if (args.length == 1) { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { port = 0; } } new VultureServer(port); } } // This class is the thread that handles all communication with a client

Page 98: Corrige tp java

// It also notifies the Vulture when the connection is dropped. class Connection extends Thread { static int connection_number = 0; protected Socket client; protected Vulture vulture; protected BufferedReader in; protected PrintStream out; // Initialize the streams and start the thread public Connection(Socket client_socket, ThreadGroup threadgroup, int priority, Vulture vulture) { // Give the thread a group, a name, and a priority. super(threadgroup, "Connection-" + connection_number++); this.setPriority(priority); // Save our other arguments away client = client_socket; this.vulture = vulture; // Create the streams try { // in = new DataInputStream(client.getInputStream()); in = new BufferedReader( new InputStreamReader(client.getInputStream())); out = new PrintStream(client.getOutputStream()); } catch (IOException e) { try { client.close(); } catch (IOException e2) { ; } System.err.println("Exception while getting socket streams: " + e); return; } // And start the thread up this.start(); } // Provide the service. // Read a line, reverse it, send it back. public void run() { String line; StringBuffer revline; int len; // Send a welcome message to the client out.println("Service de renversement de lignes"); try { for(;;) { // read in a line line = in.readLine(); if (line == null) break; // reverse it len = line.length(); revline = new StringBuffer(len); for(int i = len-1; i >= 0; i--) revline.insert(len-1-i, line.charAt(i)); // and write out the reversed line

Page 99: Corrige tp java

out.println(revline); } } catch (IOException e) { ; } // When we’re done, for whatever reason, be sure to close // the socket, and to notify the Vulture object. Note that // we have to use synchronized first to lock the vulture // object before we can call notify() for it. finally { try { client.close(); } catch (IOException e2) { ; } synchronized (vulture) { vulture.notify(); } } } // This method returns the string representation of the Connection. // This is the string that will appear in the GUI List. public String toString() { return this.getName() + " connected to: " + client.getInetAddress().getHostName() + ":" + client.getPort(); } } Code du vautour // This class waits to be notified that a thread is dying (exiting) // and then cleans up the list of threads and the graphical list. class Vulture extends Thread { protected VultureServer server; protected Vulture(VultureServer s) { super(s.threadgroup, "Connection Vulture"); server = s; this.start(); } // This is the method that waits for notification of exiting threads // and cleans up the lists. It is a synchronized method, so it // acquires a lock on the ‘this’ object before running. This is // necessary so that it can call wait() on this. Even if the // the Connection objects never call notify(), this method wakes up // every five seconds and checks all the connections, just in case. // Note also that all access to the Vector of connections and to // the GUI List component are within a synchronized block as well. // This prevents the Server class from adding a new conenction while // we’re removing an old one. public synchronized void run() {

Page 100: Corrige tp java

for(;;) { try { this.wait(5000); } catch (InterruptedException e) { ; } // prevent simultaneous access synchronized(server.connections) { // loop through the connections for(int i = 0; i < server.connections.size(); i++) { Connection c; c = (Connection)server.connections.elementAt(i); // if the connection thread isn’t alive anymore, // remove it from the Vector and List. if (!c.isAlive()) { server.connections.removeElementAt(i); server.connection_list.delItem(i); i--; } } } } } } Code du client import java.io.*; import java.net.*; public class VultureClient { public static final int DEFAULT_PORT = 6789; Socket socket; Thread reader, writer; // Create the client by creating its reader and writer threads // and starting them. public VultureClient(String host, int port) { try { socket = new Socket(host, port); // Create reader and writer sockets reader = new Reader(this); writer = new Writer(this); // Give the reader a higher priority to work around // a problem with shared access to the console. reader.setPriority(6); writer.setPriority(5); // Start the threads reader.start(); writer.start(); } catch (IOException e) { System.err.println(e); } } public static void usage() { System.out.println("Usage: java Client <hostname> [<port>]"); System.exit(0); } public static void main(String[] args) {

Page 101: Corrige tp java

int port = DEFAULT_PORT; Socket s = null; // Parse the port specification if ((args.length != 1) && (args.length != 2)) usage(); if (args.length == 1) port = DEFAULT_PORT; else { try { port = Integer.parseInt(args[1]); } catch (NumberFormatException e) { usage(); } } new VultureClient(args[0], port); } } // This thread reads data from the server and prints it on the console // As usual, the run() method does the interesting stuff. class Reader extends Thread { VultureClient client; public Reader(VultureClient c) { super("Client Reader"); this.client = c; } public void run() { // DataInputStream in = null; BufferedReader in = null; String line; try { // in = new DataInputStream(client.socket.getInputStream()); in = new BufferedReader( new InputStreamReader(client.socket.getInputStream())); while(true) { line = in.readLine(); if (line == null) { System.out.println("Server closed connection."); break; } System.out.println(line); } } catch (IOException e) { System.out.println("Reader: " + e); } finally { try {if (in != null) in.close();} catch (IOException e) {;} } System.exit(0); } } // This thread reads user input from the console and sends it to the server. class Writer extends Thread { VultureClient client; public Writer(VultureClient c) { super("Client Writer"); client = c; } public void run() {

Page 102: Corrige tp java

BufferedReader in = null; PrintStream out = null; try { String line; in = new BufferedReader(new InputStreamReader(System.in)); out = new PrintStream(client.socket.getOutputStream()); while(true) { line = in.readLine(); if (line == null) break; out.println(line); } } catch (IOException e) { System.err.println("Writer: " + e); } finally { if (out != null) out.close(); } System.exit(0); } }