L2



1.1. L2 MI/ME - Programmation Objet - Java

1.1.1. Introduction

Ce cours conerne l'apprentissage des concepts liés à la Programmation Orientée Objet (POO) (ou OOP en anglais pour Object Oriented Programming), notamment au travers du langage Java.

Java est un langage objet créé par Sun Microsystems et utilisé à partir de 1995. Sun fut rachetée en 2009 par Oracle et le langage Java appartient désormais à cette société américaine.

Le grand intérêt de Java est qu'il est portable grâce au fait que le code source est traduit en code exécutable dans un langage particulier (bytecode). On peut donc exécuter le bytecode Java sur toute machine qui dispose d'une JVM (Java Virtual Machine) qui est un programme capable d'exécuter ce code.

Le langage Java est également doté de nombreuses bibliothèques et permet de faire du développement Web (J2E), du réseau, du parallélisme, accéder aux bases de données (JDBC) ou créer des interfaces graphiques (Swing, JavaFX).

Il ne faut pas confondre Java et JavaScript qui sont deux langages ayant des syntaxes proches mais qui sont différents.

1.1.2. Complément concernant les threads

1.1.2.a  Exercices

Exercice 1.1

  • Résoudre le problème suivant : complement_td6.pdf
  • Améliorer ensuite le code, on peut notamment utiliser :
  1. // ------------------------------------------------------------------
  2. // Le parcours de la liste suivant l'indice de l'élément
  3. for (int i = 0; i < listeCaisses.size(); +=i) {
  4.   Caisse c = listeCaisses.get( i )
  5. }
  6.  
  7. // peut être remplacé par un foreach + itérateur
  8. for (Caisse c : listeCaisses) {
  9. }
  10.  
  11. // ------------------------------------------------------------------
  12. // Trouver l'indice de la caisse la moins chargée
  13. // Cette solution nécessite de définir l'interface
  14. // Comparable pour la classe Caisse
  15. int caisseLaMoinsChargee = listeCaisses.indexOf(
  16.     Collections.min( listeCaisses )
  17.   );
  18.  

Voir :

Exercice 1.2

Existe t-il une différence entre les deux codes suivants qui permettent tous deux d'accéder de manière synchrone à deux compteurs.

Pour rappel, on peut synchroniser :

  • l'accès à une méthode de la classe
  • l'accès à un morceau de code d'une méthode en se synchronisant sur un objet
  1. /**
  2.  * Première version
  3.  */
  4. class CompteursVersion1 {
  5.  
  6.   protected int compteur_1 = 0;
  7.   protected int compteur_2 = 0;
  8.  
  9.   public synchronized void incrementeCompteur_1() {
  10.     ++compteur_1;
  11.   }
  12.  
  13.   public synchronized void incrementeCompteur_2() {
  14.     ++compteur_2;
  15.   }
  16.  
  17. }
  18.  
  19. /**
  20.  * Seconde version
  21.  */
  22. class CompteursVersion2 {
  23.  
  24.   protected int compteur_1 = 0;
  25.   protected int compteur_2 = 0;
  26.   protected Object accessCompteur_1 = new Object();
  27.   protected Object accessCompteur_2 = new Object();
  28.  
  29.   public void incrementeCompteur_1() {
  30.  
  31.     synchronized( accessCompteur_1 ) {
  32.       ++compteur_1;
  33.     }
  34.    
  35.   }
  36.  
  37.   public void incrementeCompteur_2() {
  38.  
  39.     synchronized( accessCompteur_2 ) {
  40.       ++compteur_2;
  41.     }
  42.    
  43.   }
  44.  
  45. }
  46.  
  47.  
  48.  

Dans le premier cas, les méthodes étant synchronized, on ne peut être que dans une seule méthode à la fois

Par contre dans le second cas, on synchronise sur des objets, on peut donc avoir deux threads différents qui exécutent chacun l'une des méthodes en même temps.

1.1.2.b  Le mot clé volatile en Java

Le mot clé volatile indique qu'une variable sera modifiée par plusieurs Threads. La variable sera stockée dans la mémoire partagée entre les Threads ce qui la rend synchronisée de manière implicite.

La différence avec synchronized et que volatile peut s'appliquer à des types simples (i.e. basique, scalaire comme int) alors que synchronized s'applique sur des objets.

1.1.3. Complément concernant les types génériques

Exercice 1.3

Implantez une liste doublement chaînée circulaire.

  1. /**
  2.  * CLASS
  3.  *
  4.  * Implementation of a circular doubly linked list.
  5.  *
  6.  */
  7. public class LinkedList<E> {
  8.  
  9.         /**
  10.          * Inner class that represents a link of the list
  11.          */
  12.         class Link<E> {
  13.  
  14.                 /**
  15.                  * pointer to previous and next elements
  16.                  */
  17.                 protected Link<E> prev, next;
  18.                 protected E value;
  19.  
  20.     ....
  21.     }
  22.    
  23.        /**
  24.          * pointer to first element of the list
  25.          */
  26.         protected Link<E> first;
  27.  
  28.         /**
  29.          * size of list in number of elements
  30.          */
  31.         protected int size;
  32.  
  33.         /**
  34.          * Default constructor
  35.          */
  36.         public LinkedList() {
  37.       ...
  38.     }
  39.    
  40.     ...
  41.    
  42. }
  43.  

On implantera notamment les méthodes suivantes en plus du constructeur :

  • public int getSize( E value ) qui donne la taille de la liste
  • public void putLast( E value ) qui ajoute un nouvel élément à la fin de la liste
  • public String toString() qui donne le contenu de la liste sous forme de chaîne de caractères
  • public static LinkedList iota( int n, int m ) qui retourne une liste d'entiers de n à m

Exercice 1.4

Créer un programme de Test qui permet de

  • créer une liste l1 de 10 entiers en ajoutant chaque entier à la fin de la liste
  • créer une liste l2 de 10 entiers en utilisant le fonction iota
  • on affichera le contenu des deux listes

Exercice 1.5

Ecrire une fonction sort qui permet de trier la liste.