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

Premiers pas en Java, premiers objets


Pour les premiers TPs, nous allons tout faire à la main sans utiliser d'environnement de programmation, donc pas de Visual Code, d'Eclipse ou d'IntelliJ, pour bien comprendre comment cela marche.
Nous vous conseillons d'utiliser l'éditeur de texte atom ou SublimeText qui savent mettre le code en couleur (et faire une complétion simple).
De plus, comme chaque exercice n'utilisera qu'une classe, nous n'utiliserons pas les notions de privé/publique qui interviennent que quand on a plusieurs classes qui se parlent.

Exercice 1 - Hello World

Dans un premier temps nous allons écrire des petits programmes permettant de se familiariser avec le compilateur, la machine virtuelle et la syntaxe du langage.
En Java, les classes sont typiquement définies dans un fichier qui lui est propre. Le nom du fichier doit être le nom de la classe qu'il contient, auquel on ajoute le suffixe .java. Les noms des classes doivent être constitués de mots accolés dont la première lettre est une majuscule (c'est ce qu'on appelle le camelCase).

Écrire le programme suivant :
      class HelloWorld {
        static void main() {
          IO.println("Hello World");
        }
      }
     
dans votre éditeur de texte et sauvegarder celui-ci sous le nom HelloWorld.java
On peut remarquer qu'en Java, les méthodes (sortes de fonctions) sont rangées dans des classes, on écrit pas println() mais IO.println(), car println() est rangé dans la classe java.lang.IO.
En on verra ce que le "static" devant le main veut dire plus tard.

Compiler le programme en utilisant le commande javac puis vérifier que le fichier .class correspondant existe bien.
      javac HelloWorld.java
    

Exécuter le programme avec la commande java
      java HelloWorld
     
On ne met pas .class parce que la machine virtuelle le rajoute toute seule.

Déclaration d'une classe compacte.
Dans le cas où l'on a une seule classe toute seule, on peut simplifier le code en ne déclarant pas la classe dans le fichier .java.
Simplifier le code pour voir que cela marche.
A votre avis, comment le compilateur fait pour savoir quel est le nom de la classe ?

En fait, l'intérêt des classes compactes ne résident pas dans le fait que l'on écrit moins de lignes mais dans le fait que les imports sont fait automatiquement.
On verra dans la suite du cours comment faire les imports à la main.

En fait, on peut exécuter avec java HelloWorld.java, sans créer le fichier HelloWorld.class, dans ce cas, l'équivalent du fichier .class en créé en mémoire et donc n'apparait pas sur le disque.
Supprimer le fichier "HelloWorld.clas" et vérifier que vous pouvez exécuter directement le fichier "HelloWorld.java" avec la commande java.

Note: dans la suite des TPs, on vous demandera compiler pour créer les fichiers ".class" car on ira occasionnellement regarder le contenu de ces fichiers.

Exercice 2 - Arguments de la ligne de commande, boucles

Le but de cet exercice est d'écrire le main d'une classe compacte PrintArgs qui affiche les arguments de la ligne de commande.

La classe PrintArgs s'utilisera comme suit:

      $ java PrintArgs Voici des arguments
      Voici
      des
      arguments
    
Les arguments de la ligne de commande sont stockés dans le tableau de chaînes de caractères passé en argument à la méthode static void main(String[] args).

Dans un premier temps, afficher le premier argument de la ligne de commande (dans notre exemple Voici).

Que se passe-t-il si l'on ne passe pas d'argument lors de l'exécution du programme ?

Écrire une boucle affichant le contenu du tableau, sachant qu'en Java, les tableaux possèdent un champ (un attribut) length qui correspond à la taille du tableau.

Changer votre programme pour utiliser la syntaxe dite du 'for deux points', c'est à dire for(var value: array).

Exercice 3 - Calculette simple

Le but de cet exercice est d'écrire une petite calculatrice.

Écrire une classe compacte prenant un nombre sur l'entrée standard et affichant celui-ci.
Pour cela, on utilisera un objet java.util.Scanner (c'est son nom complet) qui est initialisé sur System.in (l'entrée standard) et la méthode nextInt() qui renvoie l'entier correspondant à ce que tape l'utilisateur.
    	static void main(String[] args) {
    		Scanner scanner;
    		scanner = new Scanner(System.in);
    		int value;
    		value = scanner.nextInt();
    		// compléter ici
    	}
    }
    
Pour comprendre le programme, il est utile de regarder la documentation disponible ici. Il est fortement conseillé de mettre ce lien en bookmark.

Dans un premier temps, utiliser la doc de Java ; il y a une barre de recherche en haut à droite ; pour trouver la classe java.util.Scanner, vous pouvez aussi aller chercher java.lang.IO que l'on a vu à l'exercice précédent.

Indiquer dans le programme où sont les variables et quel est leur type.
Modifier le programme pour déclarer et initialiser les variables en une seule ligne.

Dogme : À partir de maintenant, on déclarera les variables en les initialisant et en utilisant le mot-clé var quand c'est possible.

Modifier le programme pour qu'il demande de saisir deux entiers au clavier et qu'il affiche leur somme.

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

Exercice 4 - Record et conversion de String en entier

On souhaite écrire un programme calculant la distance entre deux points, ou plus exactement la distance entre un point et l'origine, i.e. le point de coordonnées (0,0).
Pour cela, on va introduire un record Point qui va nous servir à représenter un point avec ses deux coordonnées.

Voici un exemple d'exécution que l'on souhaite obtenir :
      $ java Point 3 4
      x=3, y=4
      Point[x=3, y=4]
      dist = 5.0
    

Dans un premier temps, créer un record Point (dans un fichier Point.java) avec deux composants x et y, tous les deux de type int.
Quelle doit être la ligne de commande pour compiler le fichier Point.java ?

Écrire une méthode main qui déclare deux variables entières x et y, qui leur assigne les valeurs 0, 5, puis qui crée un point p avec ces deux coordonnées. Enfin, faire afficher le point p.

Modifier le main pour prendre en paramètre le tableau des arguments, et utiliser les arguments pour initialiser les coordonnées x et y.
Comme les arguments de la ligne de commande sont des Strings et que l'on veut des entiers, on va utiliser la méthode Integer.parseInt() (n'hésitez pas à aller voir la doc).

Que se passe-t-il lorsque l'un des arguments n'est pas un nombre ?

On souhaite ajouter au record Point une méthode d'instance nommée distance qui va prendre un autre point en paramètre et qui va calculer la distance entre ces deux points sous forme d'un nombre à virgule flottante.
Quels sont les paramètres et le type de retour de la méthode distance ?
Écrire la méthode distance et afficher dans le main la distance entre le point saisi par l'utilisateur et l'origine (0, 0).

Calculer la distance entre deux points est équivalent à utiliser Pythagore sur la distance en ordonnée et la distance en abcisse entre les deux points et qu'il existe une méthode statique Math.sqrt (aller voir la doc !) qui renvoie la racine carrée d'un nombre.

Exercice 5 - Pour aller plus loin : C vs Java

Le but de cet exercice est de montrer que Java n'est pas forcément plus lent que C. Cela peut paraître contre-intuitif. En effet, l'exécution d'un programme Java passe par lancement d'une machine virtuelle qui va exécuter le bytecode produit par le compilateur Java. De l'autre côté, le code C est transformé directement en code exécutable sur votre machine (pas besoin de démarrer une machine virtuelle).
Le mystère est donc de savoir comment le code Java s'exécute aussi vite.

Considérons le programme suivant en C :

#include <stdio.h> 
#include <stdlib.h>

	int pascal (int nBut, int pBut){
       int * tab;
       unsigned int n, i;

       tab = (int *)malloc ((nBut+1)*sizeof(int));
       if(tab==NULL){
         fprintf(stderr,"Pas assez de place\n");
         exit(0);
       }

       tab[0] = 1;

       for(n=1; n<=nBut; n++){
         tab[n] = 1;

         for(i=n-1; i>0; i--)
           tab[i] = tab[i-1] + tab[i];
       }

       int result=tab[pBut];
       free(tab);
       return result;
    }

    int main(int argc, char * argv[]) {
       printf(" Cn, p = %d\n", pascal (30000, 250));
       return 0;
    }
Compiler (gcc pascal.c) et exécuter le programme a.out en demandant au système le temps d'exécution du programme avec la commande time a.out.

Écrire le programme (Pascal.java) équivalent en Java. Pour une fois, servez-vous du copier/coller. Compiler le programme puis l'exécuter en mesurant le temps (toujours avec time).

Normalement, vous devriez obtenir des temps d'exécution comparables.
Comment peut-on expliquer que le code Java soit aussi performant que le code C ?

Hint 1: Si vous voulez percer le mystère, regardez ce qu'est le JIT.

Hint 2: Si vous voulez voir qu'on vous ment un peu, essayez de compiler le code C avec l'option -O3 qui produit un code plus optimisé mais spécifique à la machine courante.