:: Enseignements :: Licence :: L3 :: 2024-2025 :: Programmation Objet avec Java ::
[LOGO]

Premiers pas en Java, chaînes de caractères, tableaux, boucles


Exercice 1 - Hello World

Pour les deux premiers TPs, on va utiliser Java de la même façon que l'on utilise Python, plutôt que de la même façon que l'on utilise C, donc on va exécuter directement les fichiers Java plutôt que les compiler puis les exécuter, on fera cela quand on sera plus grand.
La commande
         java --enable-preview HelloWorld.java
     
permet de compiler le fichier HelloWorld.java en mémoire puis de l'exécuter.
Par convention en Java, les noms des fichiers doivent être constitués de mots accolés (ici, "Hello" et "World") dont la première lettre est une majuscule et finir par l'extension ".java".
Dans un premier temps, nous allons écrire des petits programmes permettant de se familiariser avec la notion de méthodes en Java (plus ou moins l'équivalent des fonctions de C, on verra la différence un peu plus tard).

  1. Un programme très simple en Java est composé d'une méthode main():
          void main() {
            // TODO
          }
         
    avec votre éditeur de texte préféré (pas Visual Studio Code SVP!), créer et sauvegarder celui-ci sous le nom HelloWorld.java
    Note: contrairement au C, main() ne peut pas renvoyer un entier.

  2. Modifier le programme pour qu'il affiche "Hello World !" sachant qu'il existe une méthode println(text) en Java et que les chaines de caractères (String) sont séparés par des double-quotes ("").
    Exécuter le programme et vérifier qu'il affiche la chaine de caractères attendue.

Exercice 2 - Afficher la somme d'entiers stockés dans un tableau

On souhaite maintenant écrire un programme un peu plus compliqué qui calcul la somme d'un tableau d'entiers et affiche cette somme. Pour tester, vous utiliserez deux tableaux, le premier ayant les valeurs 1, 2, 4 et le second les valeurs 2, 6, 8, 10, 23, -2, 14, 21, 17.
Bien sûr, on va faire les choses proprement et pas mettre tout le code dans le main() mais découper en méthodes.

  1. Quelles sont les méthodes dont on a besoin, et quelles doit être leur signature (type de retour et type des arguments) ?

  2. Comment faire pour créer un tableau de 3 entiers en Java.
    Pourquoi doit-on utiliser new ?
    Quelle est la syntaxe pour créer ET initialiser un tableau en Java ?
    Note: comme on écrit du Java "moderne" (noter les air-quotes), on va utiliser var pour déclarer le type des variables et laisser le compilateur trouver le type des variables tout seul.

  3. Écrire la méthode qui calcul la somme des éléments d'un tableau d'entiers, sachant qu'en Java, les tableaux possèdent un champ (un attribut) length qui correspond à la taille du tableau.
    Note: en Java, on indente avec 2 espaces (pas de TAB) et par convention en met les accolades ('{' et '}') même si on a une seule instruction derrière un if ou un for.

  4. Changer votre méthode pour utiliser la syntaxe dite du 'for deux points', c'est à dire for(Type value: array)

  5. Enfin, completer votre programme pour qu'il affiche la somme de chaque tableau.

Exercice 3 - Calculette simple

Écrire un programme qui demande deux nombres à l'utilisateur et affiche la somme des deux nombres.
En Java, il existe une méthode readln(text) qui affiche le texte pris en paramètre, attend que l'utilisateur saisisse une chaine de caractères au clavier et renvoie cette chaine de caractères en valeur de retour (comme input() en Python).

  1. Écrire un programme Calc.java qui demande à l'utilisateur une chaine de caractère et affiche celle-ci.

  2. En Java, toutes les méthodes sont rangées dans ce que l'on appele des classes, par exemple, les méthodes println et readln sont en fait des méthodes de la classe java.io.IO,
    Chercher dans la javadoc (la doc de Java), la classe java.io.IO et ses méthodes IO.println et IO.readln.
    Et pour vérifier que l'on ne dit pas de bétise, remplacer les appels à println et readln par IO.println et IO.readln dans votre code.

  3. On veut maintenant convertir la chaine de caractères indiquée par l'utilisateur en entier, pour cela, nous allons utiliser la méthode Integer.parseInt (la méthode parseInt(text) rangée dans la classe java.lang.Integer).
    Modifier votre programme pour utiliser Integer.parseInt.
    Que ce passe t'il si l'utilisateur rentre une chaine de caractères qui n'est pâs un entier ?
    Note: il est fortement conseillé de mettre le lien vers la javadoc en bookmark (signet, favoris, etc.), on va beaucoup utiliser cette doc dans la suite des TPs.

  4. Modifier le programme pour qu'il demande deux entiers et affiche la somme de ceux-ci.
    Note: Java permet de faire des '+' sur les chaines de caractères pour avoir un bel affichage.

  5. Afficher en plus de la somme, la différence, le produit, le quotient et le reste.

Exercice 4 - Record et paramètre de programme

On souhaite écrire un programme calculant la distance entre deux points.
Voici un exemple d'exécution que l'on souhaite obtenir :
      $ java Distance 3 4
      x=3, y=4
      distance Point[x=0, y=0] Point[x=3, y=4] = 5.0
    
On récupère deux entiers en paramètre du programme, on crée deux points (0, 0) et (3, 4) et on affiche la distance entre ses deux points.
  1. En Java, la méthode main() peut prendre en paramètre un tableau de chaine de caractère (String[]). Ce tableau contient les chaines de caractères passées en paramètre du programme. Contrairement au C, le premier paramètre est bien le premier paramètre et pas le nom de l'exécutable.
    Dans le fichier Distance.java, écrire une méthode main qui regarde que le programme ait bien deux paramètres (sinon il faut afficher un message d'erreur) et vérifie que ces deux paramètres sont bien des entiers.
    Note: on ne sait pas encore afficher sur la sortie d'erreur (l'équivalent de STDERR en C), donc on va écrire sur la sortie standard avec println pour l'instant.

  2. Ajouter à votre programme un record qui représente un Point avec une coordonné x et une coordonné y (de type entier).
    Où doit-on déclarer le record ?
    Modifier votre programme pour créer un Point avec les deux valeurs envoyées en paramètre du programme.

  3. Écrire une méthode distance qui renvoie un flottant (c'est pas float par défaut en Java !) correspondant à la distance entre deux points (p1 et p2).
    Modifier votre main pour afficher la distance entre le point créer précédemment et le Point en (0,0).
    Note: les méthodes mathématiques sont rangées dans la classe java.lang.Math

  4. Cela marche, mais le code n'est pas terrible, en effet, en Java, on préfère ranger chaque méthode dans le record (ou la classe) qui lui correspond, c'est plus facile pour la retrouver (et les environments de developement (IDE) que l'on utilisera un peu plus tard, vont même faire de la complétion automatique), or dans notre exemple, distance n'est pas rangée dans le record Point.
    Il y a deux façons de "ranger" une méthode dans un record en Java, soit-on crée une méthode d'instance, soit-on crée une méthode statique. Une méthode statique est une méthode où l'on ajoute le mot clé static devant et que l'on accède par le nom de la classe, comme IO.println ou Integer.parseInt, dans notre cas, Point.distance(p1, p2). Une méthode d'instance est une méthode dont le premier paramètre est forcément nommé this (l'équivalent du self de Python) et que l'on accède sur un objet, dans notre cas, p1.distance(p2).
    Déplacer la méthode distance dans le record Point sous forme de méthode static et modifier votre main pour que le programme fonctionne.

  5. En fait, si la méthode a pour premier paramètre, un type qui est le même que le record (ici, que Point), alors on va préférer en Java déclarer la méthode distance comme une méthode d'instance plutôt qu'une méthode statique (moins de caractère à taper, meilleure découverte par les IDEs, et le polymorphisme quand on sera plus grand).
    Pour voir la différence entre une méthode statique et une méthode d'instance, on va déclarer distance2 comme une méthode d'instance et recopier le contenu de la méthode distance dans cette nouvelle méthode d'instance distance2. Une méthode d'instance n'a pas le mot clé static devant, son premier paramètre doit s'appeler this (et pas autre chose !).
    Créer la méthode d'instance distance2 et modifier votre main pour utiliser distance2.

  6. On peut améliorer un peu le code de deux façons :
    • Il n'est pas nécessaire de déclarer le premier paramètre this, le compilateur sait que c'est une méthode d'instance donc il peut l'ajouter tout seul.
    • On peut remplacer "this.x" par "x" (et pareil pour "y"), car lorsque le compilateur voit un nom de variable qu'il ne connait pas, il regarde si la variable est déclarée comme champ/attribut au-dessus.

    Simplifier votre code.
    Note: Et oui, cela fait bizarre d'avoir une méthode (d'instance) où l'on écrit un paramètre, mais en fait, il y en a deux, mais on s'y habitue très bien :)

Exercice 5 - De C vers Java

Cet exemple a pour but de montrer les différences de performances entre un programme en C et le même en Java.
Comme on va faire des tests de vitesse par rapport à du code C, pour cet exemple, on va compiler le code Java (avec javac) avant de l'exécuter, de la même façon qu'en C.

  1. Compiler (avec gcc pascal.c) et exécuter le programme a.out en demandant au système le temps d'exécution du programme (time ./a.out).

  2. Écrire le programme (Pascal.java) équivalent en Java. Pour une fois, vous pouvez commencer par un copier/coller.
    Puis compiler le programme avec le compilateur Java, javac
          javac --release 23 --enable-preview Pascal.java
        
    et exécuter le
            java --enable-preview Pascal
        
    en mesurant le temps (toujours avec time).
    Note: quand on exécute un code déjà compilé avec la commande java, on indique juste le nom de la classe (Pascal pas Pascal.class ni Pascal.java).
Comment peut-on expliquer la différence de vitesse ?