Sur la base des sources fournies, voici les concepts fondamentaux de Java identifiés, accompagnés d'exercices théoriques et pratiques pour tester votre compréhension.
Une classe est une structure formelle regroupant des objets ayant les mêmes caractéristiques, tandis qu'un objet est une instance de cette classe avec un état et un comportement. Un membre statique appartient à la classe elle-même et est partagé par toutes ses instances.
- Question théorique : Quelle est la principale différence entre un attribut d'instance (comme
nom) et un attribut statique (commenbEmployes) au sein d'une classe ? - Défi de codage (Gestion d'Inventaire) : Créez une classe
Produitavec un attributnomet un attribut statiquecompteurProduits. Chaque fois qu'un objetProduitest créé via le constructeur,compteurProduitsdoit être incrémenté. - Trouvez le bug :
Correction attendue : L'accès à un membre statique doit se faire via le nom de la classe ou une instance, mais ici l'attribut
class Boutique { static int totalClients = 0; } // Dans une autre classe Boutique b1 = new Boutique(); System.out.println(Boutique.totalClients); // OK Boutique.totalClients = 10; // OK System.out.println(b1.nomBoutique); // ERREUR : nomBoutique n'est pas défini.
nomBoutiquen'existe pas dans la définition de la classe fournie.
L'héritage permet de concevoir de nouvelles classes à partir de classes existantes en utilisant le mot-clé extends. La surcharge consiste à créer plusieurs méthodes avec le même nom mais des signatures (paramètres) différentes.
- Question théorique : Lorsqu'une classe hérite d'une autre, quels membres de la classe parente ne sont pas hérités par la classe fille ?
- Défi de codage (Système Bancaire) : Créez une classe
Compteavec une méthodedeposer(double montant). Créez une sous-classeCompteEpargnequi hérite deCompteet redéfinissez une méthodecalculerInteret(). - Trouvez le bug :
Correction attendue : La classe fille doit appeler le constructeur de la classe parente avec
class Animal { Animal(int age) { } } class Chat extends Animal { Chat() { // Bug ici } }
super(age)car le constructeur deAnimalnécessite un argument.
L'encapsulation utilise des modificateurs d'accès (private, public, protected) pour contrôler comment les données d'une classe sont lues ou modifiées, souvent via des accesseurs (getters) et des mutateurs (setters).
- Question théorique : Pourquoi est-il conseillé de déclarer les attributs d'une classe en
private? - Défi de codage (Profil Utilisateur) : Créez une classe
Utilisateuravec un attributmotDePasseprivé. Implémentez un mutateursetMotDePassequi vérifie que la longueur du mot de passe est supérieure à 6 caractères avant de l'assigner. - Trouvez le bug :
Correction attendue : L'attribut
class Voiture { private int carburant; } Voiture v = new Voiture(); v.carburant = 50;
carburantestprivate, il ne peut pas être modifié directement depuis l'extérieur de la classe. Il faut utiliser un mutateursetCarburant(int c).
Le polymorphisme permet à un objet d'appartenir à plusieurs catégories (types) à la fois, facilitant la manipulation d'objets de types différents via une classe parente ou une interface commune.
- Question théorique : Qu'est-ce que le "late binding" (liaison tardive) en Java ?
- Défi de codage (Système de Paiement) : Définissez une interface
Paiementavec une méthodepayer(). Créez deux classes,CarteCreditetPayPal, qui implémentent cette interface. Utilisez le polymorphisme pour appelerpayer()sur un objet de typePaiement. - Trouvez le bug :
Correction attendue : Un "sous-casting" (down-casting) explicite est nécessaire, et ici, un
Fruit f = new Orange(100); Pomme p = f;
Fruitqui est uneOrangene peut pas être casté enPommesans erreur.
Les exceptions sont des objets représentant des erreurs. Java distingue les exceptions surveillées (doivent être traitées) et non surveillées.
- Question théorique : Quel bloc de code est utilisé pour capturer et traiter une exception afin d'éviter l'arrêt du programme ?
- Défi de codage (Calculatrice) : Écrivez un programme qui demande deux nombres et effectue une division. Utilisez un bloc
try-catchpour gérer l'exceptionArithmeticExceptionen cas de division par zéro. - Trouvez le bug :
Correction attendue :
void lireFichier() { FileReader fr = new FileReader("test.txt"); }
FileReaderpeut lancer uneIOException(surveillée). Elle doit être soit capturée par untry-catch, soit déclarée avecthrows IOExceptiondans la signature de la méthode.
Les flux permettent la communication de données entre le programme et des destinations comme des fichiers. La sérialisation est le processus de sauvegarde d'un objet dans un fichier.
- Question théorique : Quelle interface une classe doit-elle implémenter pour que ses instances puissent être sérialisées ?
- Défi de codage (Sauvegarde de données) : Créez une classe
Etudiantsérialisable. Écrivez un programme qui utiliseObjectOutputStreampour sauvegarder un objetEtudiantdans un fichier nommé "etudiant.ser". - Trouvez le bug :
Correction attendue : Il est impératif de fermer le flux avec
FileWriter fw = new FileWriter("doc.txt"); fw.write("Bonjour"); // Fin du programme sans rien d'autre
fw.close()pour s'assurer que les données sont bien écrites et les ressources libérées.
Les collections sont des structures dynamiques pour stocker des objets. Les principales interfaces sont List (ordonnée), Set (pas de doublons) et Map (clés-valeurs).
- Question théorique : Dans quel cas devriez-vous choisir une
LinkedListplutôt qu'uneArrayList? - Défi de codage (Annuaire) : Utilisez une
Hashtable(ouHashMap) pour stocker des noms d'amis comme clés et leurs numéros de téléphone comme valeurs. Affichez tous les éléments de la collection. - Trouvez le bug :
Correction attendue : Un
HashSet set = new HashSet(); set.add("Java"); set.add("Java"); System.out.println(set.size()); // Affiche 2
HashSetn'accepte pas les doublons. La taille (size()) sera de 1, car le deuxième ajout de "Java" sera ignoré.
Analogie pour comprendre l'Héritage : Imaginez une classe parente comme un plan de construction pour un "Véhicule" (possédant un moteur et une couleur). Une classe dérivée (comme "Voiture") est comme un plan plus spécifique qui réutilise les instructions du premier plan tout en ajoutant ses propres détails (comme le nombre de portes), évitant ainsi de tout redessiner de zéro.