Skip to content

TD / TP Java : De la procédure à l'Objet

Objectifs et Prérequis

Prérequis : Maîtrise des bases du langage C (variables, fonctions, struct, pointeurs).

Objectif : Découvrir la syntaxe Java, comprendre le fonctionnement de la Machine Virtuelle, et assimiler les concepts fondamentaux de la Programmation Orientée Objet (POO) à l'aide de l'environnement visuel BlueJ.


Étape 1 : "Hello World" et la JVM

📖 Notion de cours : Compilation C vs Compilation Java

En C, vous utilisez un compilateur (comme gcc) qui traduit votre code directement en langage machine compréhensible par votre processeur. Ce fichier ne fonctionne que sur le système pour lequel il a été compilé.

En Java, le processus se fait en deux étapes :

  1. Le compilateur Java (javac) traduit votre code source (fichier .java) en Bytecode (fichier .class). Ce n'est pas du langage machine, c'est un code intermédiaire.
  2. La Machine Virtuelle Java (JVM) lit ce Bytecode et l'exécute sur votre machine.

L'avantage ? "Write Once, Run Anywhere". Le même fichier .class fonctionnera sur Windows, Mac ou Linux, tant qu'une JVM y est installée.

💻 Exercice 1 : À la main (sans IDE)

  1. Ouvrez un éditeur de texte simple (Notepad, Gedit, Nano...).
  2. Écrivez le code suivant, qui est l'équivalent de votre int main() en C :
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Bonjour depuis Java !");
    }
}
  1. Sauvegardez ce fichier exactement sous le nom HelloWorld.java (le nom du fichier doit correspondre au nom de la classe publique).
  2. Ouvrez un terminal / invite de commande et naviguez jusqu'au dossier contenant votre fichier.
  3. Compilez le code avec la commande :
    javac HelloWorld.java
    
  4. Vérifiez qu'un fichier HelloWorld.class a bien été créé.
  5. Exécutez le programme via la JVM avec la commande (attention, on ne met pas l'extension .class ici) :
    java HelloWorld
    

Interlude Théorique : Les Types et les Conventions en Java

📖 Notion de cours : Types Primitifs vs Types Objets

En Java, il existe deux grandes familles de types :

  1. Les Types Primitifs (commencent par une minuscule) : int, double, boolean, char...
    • Comme en C, la variable contient directement la valeur en mémoire.
    • Ils n'ont pas de méthodes associées.
  2. Les Types Objets ou Références (commencent par une Majuscule) : String, CompteBancaire, Scanner...
    • C'est l'équivalent d'un pointeur en C. La variable contient l'adresse mémoire où se trouve l'objet (créé avec new).
    • Ils donnent accès à des méthodes (ex: titulaire.length()).

📖 Notion de cours : Les Conventions de nommage

En Java, le respect de ces conventions est primordial pour la lisibilité :

  • Les Classes commencent toujours par une majuscule : CompteBancaire, String, System.
  • Les variables et attributs commencent par une minuscule : titulaire, solde.
  • Les méthodes commencent par une minuscule et contiennent un verbe : getSolde(), deposer().

Étape 2 : De la struct à la Classe (avec BlueJ)

📖 Notion de cours : Classes, Objets et Attributs

En C, vous utilisiez des struct pour regrouper des variables. En Java, on utilise des Classes. Une Classe est le "plan de construction" ou le "moule". À partir de ce plan, on crée des Objets (ou instances). L'action de créer un objet s'appelle l'instanciation (en C : malloc, en Java : mot-clé new).

💡 Zoom sur les Attributs : Un attribut est une variable définie directement à l'intérieur d'une classe (l'équivalent d'un champ dans votre struct). La syntaxe de déclaration s'écrit comme une variable globale en C : Type nomVariable [= valeur_initiale];

💻 Exercice 2 : Création et Manipulation

Partie A : Définir le plan et tester visuellement (Interface BlueJ)

  1. Dans un nouveau projet BlueJ nommé Banque, créez une Nouvelle Classe nommée CompteBancaire. Double-cliquez dessus et effacez le code par défaut.
  2. À l'intérieur, déclarez deux attributs :
    • titulaire de type String.
    • solde de type double.
  3. Cliquez sur Compiler.
  4. Test visuel : Sur l'écran principal, faites un clic droit sur la boîte orange CompteBancaire et sélectionnez new CompteBancaire(). Un rectangle rouge apparaît : c'est votre Objet ! Double-cliquez dessus pour "l'inspecter".

Partie B : La réalité du code (Le Code Pad)

Plutôt que d'écrire une méthode main complète, nous allons utiliser le Panneau d'évaluation (Code Pad) de BlueJ pour taper du code Java exécutable instantanément.

  1. Allez dans Affichage > Afficher le panneau d'évaluation.
  2. Supprimez l'objet rouge créé précédemment (clic droit -> supprimer).
  3. Dans le Code Pad, tapez cette ligne pour instancier votre objet :
    CompteBancaire monCompte = new CompteBancaire();
    
  4. Accédez aux attributs avec la notation "pointée" pour leur donner des valeurs :
    monCompte.titulaire = "Ada Lovelace";
    monCompte.solde = 500.0;
    
  5. Affichez le résultat :
    System.out.println(monCompte.titulaire + " a " + monCompte.solde + " euros.");
    

Étape 3 : Protéger ses données - L'Encapsulation

📖 Notion de cours : Encapsulation et Accesseurs

En C, n'importe quelle partie du programme peut faire mon_compte.solde = -5000;. La POO introduit l'Encapsulation : on interdit l'accès direct aux attributs en les déclarant privés (private).

Pour interagir avec eux de façon sécurisée, on utilise des fonctions appelées Accesseurs :

  • Les Getters pour lire la donnée (ex: getSolde).
  • Les Setters pour modifier la donnée.

💻 Exercice 3 : Verrouiller et contrôler

Partie A : Le verrouillage

  1. Dans CompteBancaire, ajoutez le mot-clé private devant titulaire et solde. Compilez.
  2. Essayez de taper monCompte.solde = 1000; dans le Code Pad. L'accès est désormais refusé !

Partie B : Création des Accesseurs

  1. Ajoutez ce code dans votre classe pour créer vos méthodes d'accès :
    public String getTitulaire() { return titulaire; }
    public double getSolde() { return solde; }
    public void setTitulaire(String nouveauNom) { titulaire = nouveauNom; }
    
    (Pourquoi ne pas créer de setSolde() ? Discutez-en avec votre voisin).

Partie C : Test visuel et code

  1. Interface BlueJ : Créez un objet. Faites un clic droit sur l'objet rouge : utilisez setTitulaire depuis le menu, puis inspectez l'objet pour vérifier.
  2. Code Pad : Modifiez le nom et affichez le solde en écrivant le code :
    monCompte.setTitulaire("Alan Turing");
    System.out.println(monCompte.getSolde());
    

Étape 4 : Donner un comportement - Les Méthodes

📖 Notion de cours : Les Méthodes

Une Méthode est une fonction définie à l'intérieur de la classe.

  • En C : Vous passiez un pointeur vers la structure : deposer(&mon_compte, 50);.
  • En Java : La méthode appartient à l'objet. On l'appelle avec un point : monCompte.deposer(50);.

💻 Exercice 4 : Agir sur le compte

  1. Dans CompteBancaire, créez une méthode public void deposer(double montant). Utilisez un if pour vérifier que le montant est strictement positif avant de l'ajouter au solde.
  2. Créez une méthode public void retirer(double montant). Vérifiez que le montant est positif ET que le solde est suffisant.
  3. Test Code Pad : Écrivez les lignes pour créer un compte, déposer 100€, tenter de retirer 200€ (ce qui doit échouer), et vérifier le solde.

Étape 5 : Le niveau "Classe" - Les Méthodes Statiques

📖 Notion de cours : Le mot-clé static

Une méthode statique (static) appartient à la Classe (le plan), pas aux objets.

  • Elle n'a pas besoin d'objet pour être appelée.
  • Elle ne peut pas utiliser les attributs de l'objet (elle ne connaît ni titulaire ni solde).
  • C'est l'équivalent d'une fonction classique et indépendante en C.

💻 Exercice 5 : Outil utilitaire

  1. Dans CompteBancaire, ajoutez la méthode :
    public static double convertirEnDollars(double montantEuros)
    
    (Considérez que 1 Euro = 1.10 Dollars. Retournez le résultat).
  2. Test Interface : Ne créez PAS d'objet. Faites directement un clic droit sur la boîte orange CompteBancaire. Appelez convertirEnDollars.
  3. Test Code Pad : Puisqu'il n'y a pas d'objet, on utilise le nom de la classe. Testez :
    double enDollars = CompteBancaire.convertirEnDollars(100.0);
    System.out.println(enDollars);
    

📝 Auto-évaluation Interactive

Cochez la bonne réponse pour vérifier vos acquis de cette première séance.

1. Quelle est la différence fondamentale entre une "Classe" et un "Objet" ?



2. Quel mot-clé permet de créer (instancier) un objet en mémoire en Java ?




3. Qu'est-ce que l'encapsulation ?



4. Quel est le but principal de l'Encapsulation en pratique ?



5. Parmi ces types, lequel est un type Primitif (et non une référence vers un Objet) ?




6. Quelle est la différence en mémoire entre un type primitif (ex: int) et un type Objet (ex: String) ?



7. Que signifie le mot-clé static lorsqu'il est placé devant un attribut ?



8. Comment appelle-t-on une méthode définie avec le mot-clé static ?




Exercice Bonus : Manipulation avancée et compilation manuelle

Cet exercice final a pour but de synthétiser vos connaissances en Java tout en vous forçant à manipuler les outils en ligne de commande.

Contrainte stricte

L'utilisation des gestionnaires graphiques de fichiers (explorateur) est interdite. L'un des objectifs de ce TP est de vous familiariser avec le terminal Linux.


1. Création de l'environnement de travail

Nous allons mettre en place une arborescence propre pour séparer le code source des fichiers compilés.

  1. Créez un répertoire de travail et placez-vous dedans, par exemple :
    mkdir -p $HOME/java/TD1/exoBonus
    cd $HOME/java/TD1/exoBonus
    
  2. À l'aide de la commande wget, récupérez l'archive de l'exercice :
    wget https://PLACEHOLDER/script.sh
    
    en cas de problème de certificat, vous pouvez ajouter l'option --no-check-certificate
  1. Testez l'exécution directe de l'archive :
    java -jar circles.jar
    
  2. Décompressez l'archive pour en extraire le contenu :
    jar xf circles.jar
    
  3. Analyse : Listez le contenu du répertoire courant. Que contient l'archive ?
  4. Pour y voir plus clair, nous allons séparer les sources des classes compilées. Les sources sont déjà dans un répertoire src/. Créez un répertoire pour les binaires et déplacez-les :
    mkdir classes
    mv *.class classes/
    
  5. Comparez le contenu des répertoires classes/ et src/. Comment expliquez-vous la différence de contenu ?

Commandes de compilation manuelles

À partir de maintenant, vous allez compléter les fichiers src/Circle.java et src/Main.java. En admettant que la variable exoBonus contienne le chemin vers votre répertoire de travail (exoBonus=$HOME/java/TD1/exoBonus), voici les commandes à utiliser depuis la racine de ce répertoire :

Pour compiler :

javac -classpath $exoBonus/classes/ -sourcepath $exoBonus/src/ -d $exoBonus/classes/ $exoBonus/src/Main.java

Pour exécuter :

java -classpath $exoBonus/classes/ Main


2. Observer le code existant

Ouvrez le fichier src/Circle.java avec votre éditeur de texte (nano, vim, gedit ou autre).

  • Quels sont les membres publics de la classe Circle ?
  • Quels sont ses membres privés ?
  • Observez les méthodes makeVisible(), makeInvisible(), changeSize() et changeColor(). À quoi sert le mot-clé this ? Quand est-il strictement nécessaire, et quand est-il facultatif ?

3. Génération de la Javadoc

Les commentaires au-dessus des méthodes de Circle respectent un format précis (les tags @param, @return, etc.). Ils permettent de générer automatiquement la documentation de la classe sous forme de site web.

  1. Générez la documentation avec la commande suivante :
    javadoc -d doc src/*.java
    
  2. Ouvrez le fichier généré dans un navigateur web depuis le terminal :
    firefox doc/index.html
    
  3. Vous trouverez la documentation officielle du JDK (Java 21) sous ce même format à l'adresse suivante : https://docs.oracle.com/en/java/javase/21/docs/api/. Prenez l'habitude de la consulter !

4. Manipulation de la classe Main

Modifiez la classe Main pour tester les méthodes makeVisible() et makeInvisible() de vos cercles.

Problème : Que se passe-t-il si vous créez une nouvelle instance de Circle et que vous invoquez directement sa méthode makeVisible() ? Indice : Invoquez d'abord la méthode changeColor() et/ou changeSize() pour comprendre ce qui se passe à l'écran.

Pour pallier ce problème d'affichage initial, nous allons créer des méthodes pour déplacer explicitement un cercle.


5. Enrichissement de la classe Circle

Pour chaque méthode modifiée ou ajoutée dans Circle, testez-la en ajoutant son appel dans la classe Main.

  1. Mouvements basiques :
    • Ajoutez une méthode moveUp() qui déplace un cercle vers le haut de 10 pixels (diminue la valeur de son champ y).
    • Ajoutez une méthode moveDown() qui déplace un cercle vers le bas de 10 pixels.
  2. Surcharge (Overloading) :
    • Surchargez ces deux méthodes (ajoutez deux méthodes de même nom mais avec une signature différente) pour qu'elles prennent un paramètre entier indiquant le nombre de pixels du déplacement (au lieu de la valeur par défaut de 10).
    • Attention : Écoutez bien le chargé de TD lors de la correction, il y a un piège classique de conception ici !
  3. Refactoring (DRY - Don't Repeat Yourself) :
    • Ces quatre méthodes se ressemblent beaucoup. Ajoutez une méthode moveVertical(int distance) qui traite le déplacement sur l'axe Y.
    • Modifiez vos méthodes précédentes pour qu'elles fassent appel à moveVertical(). Aucun code de calcul ne doit être dupliqué.
    • Écrivez sur le même modèle une méthode moveHorizontal(int distance).
  4. Animation :
    • Ajoutez des méthodes slowMoveHorizontal(int distance) et slowMoveVertical(int distance) pour provoquer un déplacement animé.
    • Pour cela, appelez vos méthodes de mouvement classique en demandant un déplacement de 1 unique pixel, et recommencez autant de fois que nécessaire.
    • Contrainte d'implémentation : Programmez slowMoveHorizontal() de manière récursive, et slowMoveVertical() de manière itérative (avec une boucle).

6. Menu interactif avec Scanner

À l'aide de la classe java.util.Scanner (cherchez-la dans la Javadoc !) et d'une structure switch, ajoutez un menu interactif dans la console au sein de votre Main.

L'utilisateur devra saisir un numéro associé à l'action qu'il souhaite exécuter sur le cercle (monter, descendre, changer de couleur...), suivi des paramètres nécessaires si la méthode l'exige. La saisie du chiffre "0" devra terminer proprement le programme.


7. Refaire le .jar exécutable

Pour terminer, nous allons repaqueter votre travail dans une archive Java exécutable propre.

  1. Placez-vous dans le répertoire des classes compilées :
    cd classes
    
  2. Créez une variable avec votre nom et générez l'archive en spécifiant la classe principale (Main) :
    JARNAME="nom1_prenom1.jar"
    jar cfe "$JARNAME" Main *.class
    
  3. Déplacez le fichier créé dans le répertoire parent :
    mv "$JARNAME" ../
    cd ..
    
  4. Ajoutez vos sources à l'archive :
    jar uf "$JARNAME" src
    
  5. Testez :
    jar -jar "$JARNAME"
    

🛠️ ANNEXE : Aide-mémoire C vers Java

Concept En langage C En langage Java Remarques
Point d'entrée int main(int argc, char *argv[]) { ... } public static void main(String[] args) { ... } En Java, le main doit obligatoirement être dans une class.
Affichage printf("Solde : %f\n", solde); System.out.println("Solde : " + solde); On utilise le + pour concaténer.
Structures / Classes struct Compte { double solde; }; class Compte { double solde; } En Java, la classe contient aussi les méthodes.
Allocation Mémoire Compte* c = malloc(sizeof(Compte)); Compte c = new Compte(); Le mot-clé new alloue la mémoire.
Pointeurs c->solde = 50; c.solde = 50; Java utilise toujours un point ..
Pointeur nul NULL null Indique qu'une référence ne pointe vers rien.
Libération free(c); (Automatique) Le "Garbage Collector" libère la mémoire tout seul.
Tableaux int tab[5]; int[] tab = new int[5]; Un tableau est un Objet en Java.
Taille d'un tableau sizeof(tab) / sizeof(int) passage d'une deuxième variable entière tab.length La taille est un attribut intégré.
Chaînes (String) strcmp(nom1, nom2) == 0 nom1.equals(nom2) On ne compare JAMAIS deux String avec == en Java.

Sujet rédigé à l'aide de Gemini (pas par Gemini)