:: Enseignements :: ESIPE :: E3INFO :: 2012-2013 :: Programmation Objet avec Java ::
[LOGO]

Objets, références, égalités, strings


Exercice 1 - Point

On cherche à écrire une classe Point stockant un point graphique en coordonnées cartésiennes (appelons les x et y).
  1. Déclarer une classe Point contenant les deux champs privés x et y.
    Puis essayer le code suivant dans la méthode main de la classe Point.
    Point p=new Point();
    System.out.println(p.x+" "+p.y);
          
    Expliquer pourquoi l'accès aux champs privés est autorisé ici.
  2. Créer une classe TestPoint (dans un fichier TestPoint.java) et recopiez le main de Point dans la classe TestPoint.
    Quel est le problème à l'exécution de la classe TestPoint? Comment peut-on le corriger ?
  3. Pourquoi doit-on toujours déclarer les champs privés ?
  4. Qu'est ce qu'un accesseur ?
    Quels sont les acceseurs que l'on doit mettre ici ?
  5. Ajouter un constructeur initialisant les coordonnés du point avec deux paramètres (appelons les px et py).
    Quel est le problème ?
    Quel est la solution ?
  6. Modifier le constructeur précédent pour que les deux paramètres s'appellent x et y.
    Quel est le problème ?
    Quel est la solution ?
  7. Comment faire en sorte de connaître, à tout moment, le nombre total de points qui ont été créés par la classe depuis le lancement de l'application?
    Créer une méthode totalCreated() de sorte à obtenir le comportement suivant:
      public static void main(String[] args) {
        Point p = new Point();
        System.out.println(p.x+" "+p.y);                // 0 0 
        System.out.println("Total: " + totalCreated()); // Total: 1 
        Point p1 = new Point(1,1);
        System.out.println("Total: " + totalCreated()); // Total: 2
        Point p2 = new Point(2,2);
        System.out.println("Total: " + totalCreated()); // Total: 3
        Point p0 = new Point();
        System.out.println("Total: " + totalCreated()); // Total: 4
      }
    
  8. Écrire un autre constructeur qui prend un point en paramètre et et utilise les coordonnées de celui-ci pour initialiser le point courant.
    Comment le compilateur fait-il pour savoir quel constructeur appeler ?

Exercice 2 - Test d'égalité

En utilisant la classe Point de l'exercice précédent.
      Point p1=new Point(1,2);
      Point p2=p1;
      Point p3=new Point(1,2);

      System.out.println(p1==p2);
      System.out.println(p1==p3);
     

  1. Qu'affiche le code ci-dessus ? Expliquez.
  2. Écrire dans la classe Point une méthode isSameAs() (à vous de trouver la signature exacte de la méthode) qui renvoie true si deux points ont les mêmes coordonnées.
  3. La classe java.util.ArrayList fournit une implementation correspondant à un tableau qui s'agrandi dynamiquement, au besoin.
    À quoi selon vous peut servir la méthode indexOf de cette classe?
  4. Executez le code suivant :
         public static void main(String[] args){
           Point p1=new Point(1,2);
           Point p2=p1;
           Point p3=new Point(1,2);
    
           ArrayList list = new ArrayList();
           list.add(p1);
           System.out.println(list.indexOf(p2));
           System.out.println(list.indexOf(p3));
         }
         
    Quel est le problème avec les résultats affiché sur la console.
    Note : ici, le compilateur génère des warnings à la création et à l'utilisation de l'ArrayList. Nous verrons dans les prochains TD comment les éviter.
  5. Quelle méthode de Point est appelée par ArrayList.indexOf ?
    Lire la doc !!!
  6. Modifier la classe Point pour que indexOf() teste suivant les coordonées des Points et pas suivant les références.
  7. Utiliser l'annotation @Override pour vérifier que vous avez bien écrit la signature de la méthode ajoutée à Point.
  8. A quoi sert l'annotation @Override ?

Exercice 3 - Comment afficher un Point ?

On aimerait pouvoir afficher les caractéristiques d'un point, par le code Java suivant :
      Point point=...
      System.out.println(point);
    
Java sait faire cela, à condition de mettre dans la classe Point une méthode public String toString() (la définition de cette méthode est dans la classe java.lang.Object) retournant une chaîne de caractères, qu'on construit typiquement à partir des attributs de l'objet.
Rappel: en Java on peut faire un '+' entre une String et n'importe quoi, le résultat est la concatenation entre la String et le n'importe quoi vu comme une suite de caractère.

  1. Ecrire cette méthode, pour obtenir par exemple l'affichage suivant :
          (x,y)
          
  2. Peut-on utiliser l'annotation @Override, ici ?

Exercice 4 - Chaînes de caractères constantes...

Sachant que les String sont constantes en Java, que pensez vous de la manière dont vous avez écrit la dernière méthode?
Afin de mieux comprendre ce que fait le compilateur avec le code source, utilisez la commande javap -c pour décompiler la classe Point dans laquelle la méthode main() ne contiendra plus que le code suivant:
    Point p0 = new Point(1,2);
    System.out.println(p0);
    
    String s = null;
    s = "(" + p0.getX() + "," + p0.getY() + ")";
    System.out.println(s);
    
    Point[] array = new Point[4];
    array[0] = p0;
    array[1] = new Point(p0);
    array[3] = p0;
    
    s = "";
    for(int i=0; i<array.length; i++) {
      s = s + array[i] + " * ";
    }
    System.out.println(s);
Commencez par faire un dessin (sur une feuille de papier) représentant les états successifs des variables sur la pile et l'état du tas. Essayez ensuite de retrouver à quoi correspondent les instructions de bytecode indiquées par le bytecode.

Comment pourriez vous écrire la boucle pour qu'aucune String (constante) inutile ne soit créée?
Pourriez vous éviter d'écrire l'étoile après le dernier élément du tableau, et ce quelque soit la taille du tableau?