:: Enseignements :: ESIPE :: E3INFO :: 2020-2021 :: Programmation Objet avec Java ::
[LOGO]

String, StringBuilder, égalité, et expressions régulières


Exercice 1 - Assignation, égalité, référence

Dans cet exercice, on travaillera avec un record Point et une classe Pixel qui sont donnés ci-dessous:
public record Point(int x,int y){
  
}
Copiez ces codes (ci-dessus et ci-dessous) dans votre projet Java sous eclipse, pour que ce dernier les compile.
public class Pixel {
  public final static int ORIGIN = 0;
  private int x;
  private int y;
  public Pixel(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public void reset() {
    x = ORIGIN;
    y = ORIGIN;
  }

  public void printOnScreen() {
    System.out.println("("+x+","+y+")");
  }
}

  1. Dans le main de la classe Pixel, copiez le code ci-dessous:
          var p = new Pixel(2,5);
          p.printOnScreen();
          p.reset();
          p.printOnScren();
         
    Quel est le type de 'p' ? Comment le compilateur fait il pour savoir qu'il existe une méthode reset() sur 'p' ?
  2. Qu'affiche le code suivant ?
           var p1 = new Pixel(3,2);
           var p2 = p1;
           var p3 = new Pixel(3,4);
           var p4 = new Pixel(3,2);
    
           System.out.println(p1 == p2);
           System.out.println(p1 == p3);
           System.out.println(p1 == p4);
         
    Expliquez ces affichages. Même question en remplaçant la classe Pixel par la classe Point.
  3. Quelle est la méthode à utiliser si l'on veut tester si le contenu des chaînes de caractères est le même ?
           var s4 = "toto";
           var s5 = new String(s4);
    
           System.out.println(/* comparer contenue de s4 et s5 */);
         
  4. Qu'affiche le code ci-dessous:
        var p4 = new Point(1,2);
        var p5 = new Point(1,2);
        System.out.println(p4.equals(p5));
        var q1 = new Pixel(1,2);
        var q2 = new Pixel(1,2);
        System.out.println(q1.equals(q2));
      
    Expliquez l'affichage.
    Comment peut-on appeler la méthode equals alors qu'elle n'est pas définie dans la classe Point ou Pixel ?
    On verra comment redéfinir equals dans la classe Pixel pour qu'il ait le comportement attendu dans la suite du cours.
A retenir:
  • Pour les objets, l'affectation ne copie que la référence pas l'objet. == teste l'égalité des références, pas du contenu des objets. La méthode equals teste le contenu des objets mais si on écrit sa propre classe il faut la coder soit même sauf pour les records où c'est fait automatiquement.
  • Pour les types primitifs qui ne sont pas des objets (i.e., int, long, float, double, boolean). L'affectation copie la valeur et == teste l'égalité des valeurs.

Exercice 2 - String et StringBuilder

La classe String qui représente les chaînes de caractères est immutable: c'est à dire qu'après la création de l'objet String son contenu ne peut pas être modifié.

  1. Qu'affiche le code suivant ?
          var s8 = "hello";
          s8.toUpperCase();
          System.out.println(s8);
         
    Expliquez et corrigez le code.
  2. Dans une classe Stars, écrivez une méthode statique stars qui prend en paramètre un entier positif n et qui renvoie une chaîne de caractères contenant n fois le caractère *. Dans le main de cette classe, vous lirez un entier au clavier et vous afficherez autant d'étoiles grâce à la fonction stars.
    Utiliser dans un premier temps l'opérateur + qui permet la concaténation de chaînes de caractères.
  3. Si l'on fait un graphe du temps moyen pris par votre implémentation de stars en fonction de la valeur du paramètre n, on obtient:
    Clairement, le temps d'exécution n'est pas proportionnel à la valeur de n et est très élevé. Expliquez ces observations.
  4. Pour écrire une version plus performante de la fonction stars, on va utiliser un StringBuilder qui se comporte comme une chaîne de caractères mutable.
    Regardez le javadoc de StringBuilder (en particulier les méthodes append et toString).
    Réécrivez votre fonction statique stars en utilisant un StringBuilder. Normalement le temps d'exécution de cette nouvelle fonction ressemble à cela:
  5. Expliquez le miracle technologique qui permet de remplacer le code:
      var sb = new StringBuilder();
      sb.append("Bonjour");
      sb.append(" et aurevoir!");
      var res = sb.toString();
    
    par
       var sb = new StringBuilder();
       var res = sb.append("Bonjour").append(" et aurevoir!").toString();
    
  6. On pourrait penser qu'il faut utiliser systématiquement un StringBuilder quand on veut concatener plus de deux chaînes. Nous allons voir que ce n'est pas toujours nécessaire.
    Recopier le code suivant dans une classe de Test :
           public static void main(String[] args) {
             var first = args[0];
             var second = args[1];
             var last = args[2];
             System.out.println(first + ' ' + second + ' ' + last);
           }
          
    Pourquoi peut-on utiliser ' ' à la place de " " ?
    Compiler le code puis utiliser la commande javap pour afficher le bytecode Java (qui n'est pas un assembleur) généré.
           javap -c Test
          
    Que pouvez-vous en déduire ?
  7. Et pourquoi est-ce que le chargé de TD va me faire les gros yeux si j'écris un + dans un appel à la méthode append?
  8. Quand faut-il utiliser un StringBuilder et quand est-ce que l'on peut utiliser + ?

Exercice 3 - Pixels et Points

Le but de cet exercice est de manipuler très simplement des tableaux de Pixel et des tableaux de Point. Ici, on écrira les méthodes demandées mais on en ajoutera pas d'autres (en particulier, on utilisera pas de getter pour récupérer les coordonnées).

  1. Dans la classe Pixel, on veut ajouter une méthode String displayPixels(Pixel[] pixels) qui retourne la représentation sous la forme d'une String des pixels contenus dans le tableau sous la forme d'une ligne donnant la taille du tableau, une accolade ouvrante puis les coordonnées de chaque pixel, chacun sur une ligne, entre parenthèses, et séparé du suivant par un point-virgule, comme ceci par exemple:
    5 point(s): { 
    (1,1) ;
    (2,2) ;
    (3,3) ;
    (4,4) ;
    (5,5) }
    
    Quel doit être le modificateur de cette méthode pour que le code suivant, dans la méthode main, fonctionne correctement?
    var empty = new Pixel[] {};
    var singlePixel = new Pixel[] { new Pixel(1,1) };
    var fivePixels = new Pixel[] { new Pixel(1,1), new Pixel(2,2), new Pixel(3,3), new Pixel(4,4), new Pixel(5,5) };
    System.out.println(Pixel.displayPixels(empty));
    System.out.println(Pixel.displayPixels(singlePixel));
    System.out.println(Pixel.displayPixels(fivePixels));
    
  2. Dans le record Point, ajoutez une méthode String displayPoints(Point[] points) qui fait exactement la même chose; testez dans la main du record Point:
    var empty = new Point[] {};
    var singlePoints = new Point[] { new Point(1,1) };
    var fivePoints = new Point[] { new Point(1,1), new Point(2,2), new Point(3,3), new Point(4,4), new Point(5,5) };
    System.out.println(Point.displayPoints(empty));
    System.out.println(Point.displayPoints(singlePoints));
    System.out.println(Point.displayPoints(fivePoints));
    
  3. Dans la classe Pixel, on veut maintenant ajouter la méthode void resetAtOriginAllPixelsWithXAt(int targetX, Pixel[] pixels) qui remet à l'origine (0,0) tous les pixels du tableau dont la corrdonnée en X vaut targetX. Par exemple, à la suite du main précédent, on pourra tester avec
    Pixel.resetAtOriginAllPixelsWithXAt(3, fivePixels);
    System.out.println(Pixel.displayPixels(fivePixels));
    
    qui devra alors afficher :
    5 pixel(s): { 
    (1,1) ;
    (2,2) ;
    (0,0) ;
    (4,4) ;
    (5,5) }
    
  4. Dans le record Point, ajoutez une méthode void resetAtOriginAllPointsWithXAt(int targetX, Point[] points) qui fait exactement la même chose; quel est le problème? Comment pourriez vous faire pour que le main du record Point auquel vous auriez ajouté:
    Point.resetAtOriginAllPointsWithXAt(3, fivePoints);
    System.out.println(Point.displayPoints(fivePoints));
    
    affiche
    5 point(s): { 
    (1,1) ;
    (2,2) ;
    (0,0) ;
    (4,4) ;
    (5,5) }
    

Exercice 4 - Reconnaissance de motifs

Le but de cet exercice est la manipulation d'expressions régulières en java. Nous utiliserons pour cela les classes du paquetage java.util.regex.

  1. A quoi servent la classe java.util.regex.Pattern et sa méthode compile ?
    A quoi sert la classe java.util.regex.Matcher ?
  2. Écrire un programme qui lit des chaînes de caractères sur la ligne de commande et affiche les chaînes qui correspondent à des nombres, c'est-à-dire les chaînes dont tous les caractères sont compris entre '0' et '9'.
  3. Modifier le programme pour que, si une chaîne de caractères commence par des caractères qui ne sont pas des chiffres, ces chiffres soient également affichés (par exemple, avec les chaînes "abc", "ab3", "4de", "f6h" et "789", on affiche : "3 789").
  4. Écrire une méthode qui prend en paramètre une chaîne de caractères contenant une adresse IPv4 et renvoie un tableau de 4 bytes. Il faut tester qu'il s'agit bien d'une adresse valide.
    Vous utiliserez pour cela la notion de groupe.