Examen de programmation Java
Partie 1 : Choix multiples (QCM) Question 1 - Instanciation et héritage des constructeurs Le résultat de ce code lorsqu'il est exécuté est la Réponse C : 123 . Explication détaillée : En Java, lorsqu'une classe enfant est instanciée, son constructeur appelle systématiquement le constructeur de sa classe parente avant d'exécuter ses propres instructions.
D'après le document Examen de programmation Java
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source
Programmation, Mathématiques · PDF · 8 pages · 2015
Afficher l'aperçu du document
Partie 1 : Choix multiples (QCM)
Question 1 - Instanciation et héritage des constructeurs
Le résultat de ce code lorsqu'il est exécuté est la Réponse C : 123.
Explication détaillée :
En Java, lorsqu'une classe enfant est instanciée, son constructeur appelle systématiquement le constructeur de sa classe parente avant d'exécuter ses propres instructions. Si aucun appel explicite (comme super(arguments)) n'est écrit par le programmeur, le compilateur insère un appel implicite au constructeur par défaut (sans arguments) de la classe parente super().
Ainsi, lors de l'appel de new Three() :
- Le constructeur
Three()est appelé. Il déclenche d'abordsuper()versTwo(). - Le constructeur
Two()est appelé. Il déclenche d'abordsuper()versOne(). - Le constructeur
One()s'exécute et affiche1. - Le contrôle revient à
Two(), qui exécute son code et affiche2. - Le contrôle revient à
Three(), qui exécute son code et affiche3.
Question 2 - Héritage et constructeur par défaut manquant
Le résultat est la Réponse D : Compilation échoue en raison d'une erreur dans la ligne 7.
Explication détaillée :
Comme expliqué dans la question précédente, le constructeur de la classe fille Employee (à la ligne 7) tente d'appeler implicitement le constructeur par défaut (sans argument) de sa classe parente Person via un super() invisible.
Cependant, en Java, si vous définissez explicitement un constructeur avec paramètres dans une classe (ici public Person(String nm) à la ligne 3), le compilateur ne génère plus automatiquement le constructeur par défaut sans argument. La classe Person n'a donc aucun constructeur vide. L'appel implicite à la ligne 7 échoue, provoquant une erreur de compilation.
Remarque sur le code source : Une faute de frappe est également présente dans le code de l'énoncé (la variable est déclarée emplD à la ligne 6 mais le constructeur utilise empID à la ligne 7). Toutefois, l'erreur liée à l'absence de constructeur parent empêche la compilation de toute façon, et c'est cette règle fondamentale d'héritage objet que la question évalue, comme le confirme la justification de la correction officielle.
Question 3 - Pointeurs de tableaux en mémoire
La bonne réponse est la Réponse B : Ligne 3 affiche la valeur 3.
Explication détaillée :
La déclaration int y[] = x; à la ligne 2 ne crée pas un nouveau tableau indépendant. Elle copie uniquement la référence mémoire du tableau x dans la variable y. Les deux variables pointent donc vers exactement le même objet tableau en mémoire.
En Java, l'indexation d'un tableau commence toujours à l'indice 0. Par conséquent, y[2] cible la troisième case du tableau {1, 2, 3, 4, 5}, ce qui correspond bien à la valeur numérique 3.
Partie 2 : Conception et implémentation orientée objet Java
Section I - Implémentation de la classe Membre
Pour se conformer strictement à la contrainte ("Les Getters et les setters ne sont à implémenter que si leur demande est explicite"), les attributs autres que id (comme nom) ne posséderont pas de getters. Ils recevront la visibilité par défaut (visibilité de paquetage, ou package-private) afin d'être consultables par les autres classes du même exercice sans nécessiter de méthodes d'accès.
À noter également : la signature exigée par l'énoncé pour la comparaison est boolean equals(Membre m). Bien que la norme Java classique redéfinisse boolean equals(Object obj), nous respectons ici scrupuleusement la signature imposée par le sujet.
public class Membre {
private int id;
String nom; // Visibilité 'package' par défaut car aucun getter n'est autorisé
// Uniquement un constructeur paramétré
public Membre(int id, String nom) {
this.id = id;
this.nom = nom;
}
// Getters et Setters seulement pour l'attribut identifiant
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// La méthode toString
@Override
public String toString() {
return "Membre [id=" + id + ", nom=" + nom + "]";
}
// La méthode equals avec la signature spécifique imposée par l'énoncé
public boolean equals(Membre m) {
if (m == null) {
return false;
}
// Deux membres sont égaux s'ils ont le même id et le même nom
return this.id == m.getId() && this.nom.equals(m.nom);
}
}
Section II - Implémentation des classes Joueur et Entraineur
Ces deux classes héritent de Membre et font appel à super() dans leurs constructeurs.
public class Joueur extends Membre {
int numero; // Visibilité 'package' pour y accéder plus tard sans getter
public Joueur(int id, String nom, int numero) {
super(id, nom);
this.numero = numero;
}
@Override
public String toString() {
return "Joueur [id=" + getId() + ", nom=" + nom + ", numero=" + numero + "]";
}
}
public class Entraineur extends Membre {
int anneesExperience;
public Entraineur(int id, String nom, int anneesExperience) {
super(id, nom);
this.anneesExperience = anneesExperience;
}
@Override
public String toString() {
return "Entraineur [id=" + getId() + ", nom=" + nom + ", anneesExperience=" + anneesExperience + "]";
}
}
Section III - Implémentation de la classe Equipe
Afin de rendre le code compilable et de respecter les exigences de l'énoncé quant à la gestion des erreurs, nous devons d'abord déclarer les exceptions personnalisées.
// Déclaration des exceptions personnalisées requises
public class EquipeNonValideException extends Exception {
public EquipeNonValideException(String message) {
super(message);
}
}
public class TransfertException extends Exception {
public TransfertException(String message) {
super(message);
}
}
Voici l'implémentation complète de la classe Equipe. Nous utilisons un tableau natif et un compteur interne pour respecter techniquement la notion de "capacité maximale de 30" classique de ce niveau de programmation.
public class Equipe {
private int id;
private String nom;
private Membre[] membres;
private int nombreActuelMembres;
public Equipe(int id, String nom) {
this.id = id;
this.nom = nom;
this.membres = new Membre[30]; // Capacité maximale de 30 membres
this.nombreActuelMembres = 0;
}
// 1. Rechercher un membre (retourne l'indice ou -1)
public int rechercher(Membre membre) {
if (membre == null) return -1;
for (int i = 0; i < nombreActuelMembres; i++) {
if (membres[i].equals(membre)) {
return i;
}
}
return -1;
}
// 2. Ajouter un membre (vérification capacité et unicité)
public void ajouter(Membre membre) {
if (nombreActuelMembres >= 30) {
System.out.println("Ajout impossible : la capacité maximale de 30 est atteinte.");
return;
}
if (rechercher(membre) != -1) {
System.out.println("Ajout impossible : ce membre est déjà dans l'équipe.");
return;
}
membres[nombreActuelMembres] = membre;
nombreActuelMembres++;
}
// 3. Supprimer un membre
public void supprimer(Membre membre) {
int indice = rechercher(membre);
if (indice != -1) {
// On décale les membres restants vers la gauche pour éviter les espaces null
for (int i = indice; i < nombreActuelMembres - 1; i++) {
membres[i] = membres[i + 1];
}
membres[nombreActuelMembres - 1] = null;
nombreActuelMembres--;
}
}
// 4. toString pour l'équipe (id, nom, et uniquement les joueurs)
@Override
public String toString() {
String chaine = "Equipe [id=" + id + ", nom=" + nom + "]\nListe des joueurs :\n";
for (int i = 0; i < nombreActuelMembres; i++) {
// L'opérateur instanceof permet de filtrer uniquement les objets de type Joueur
if (membres[i] instanceof Joueur) {
chaine += membres[i].toString() + "\n";
}
}
return chaine;
}
// 5. Valider la composition de l'équipe
public void valider() throws EquipeNonValideException {
int compteurEntraineur = 0;
for (int i = 0; i < nombreActuelMembres; i++) {
if (membres[i] instanceof Entraineur) {
compteurEntraineur++;
}
}
if (compteurEntraineur == 1) {
System.out.println("Equipe valide");
} else {
throw new EquipeNonValideException("Erreur de validation : l'équipe doit posséder un et un seul entraineur.");
}
}
// 6. Afficher les numéros des joueurs
public void afficherNumeros() {
for (int i = 0; i < nombreActuelMembres; i++) {
if (membres[i] instanceof Joueur) {
// Conversion (cast) explicite pour accéder à l'attribut du Joueur
Joueur j = (Joueur) membres[i];
System.out.println("Numéro: " + j.numero);
}
}
}
// 7. Transférer un joueur entre deux équipes
// L'énoncé demande "void transfererJoueur". Nous la déclarons statique car la méthode
// orchestre des transferts entre deux instances externes distinctes (e1 et e2).
public static void transfererJoueur(Joueur joueur, Equipe e1, Equipe e2) throws TransfertException {
if (e1.rechercher(joueur) == -1) {
throw new TransfertException("Transfert impossible");
}
e1.supprimer(joueur);
e2.ajouter(joueur);
}
}
Méthode
Face à une épreuve de programmation orientée objet sur papier, l'approche optimale se structure en trois étapes clés :
- Extraction du modèle de domaine : Avant de coder, dressez la liste des entités (
Membre,Joueur,Equipe). Établissez leurs liens : qui hérite de qui ? (relation "est un" : unJoueurest unMembre), qui contient qui ? (relation "possède" : uneEquipepossède desMembre). - Identification des contraintes strictes : Repérez et soulignez les règles impératives. Dans cet examen, l'absence imposée de getters non sollicités est un piège classique ; il dicte immédiatement le choix de la visibilité des variables (passer de
privateau mode "package-private" par défaut). - Sécurité des traitements en boucle : L'utilisation de tableaux à taille fixe (comme
new Membre[30]) implique que toutes les cases ne sont pas nécessairement remplies à un instant T. Il est crucial d'utiliser une variable de contrôle (nombreActuelMembres) pour limiter les itérations plutôt quemembres.length, ce qui évite l'apparition fatale d'exceptions de typeNullPointerExceptionen plein milieu de vos algorithmes de recherche ou d'affichage.
Commentaires
Aucun commentaire pour le moment. Posez la première question.