Les bases de Java
Types, méthodes, classes et objets, héritage, collections, exceptions. Les fondations solides du langage, avant d'attaquer un framework comme Spring Boot.
À la fin du cours, tu sais
- Comprendre comment Java compile et s'exécute (JDK, JVM, bytecode)
- Manipuler les types, les variables et les opérateurs de base
- Écrire des méthodes claires (paramètres, retour, surcharge)
- Créer des classes et des objets (attributs, constructeurs, encapsulation)
- Utiliser l'héritage, les interfaces et le polymorphisme
- Manipuler les collections (List, Map, Set) et les génériques
- Gérer les erreurs proprement avec les exceptions
Prérequis
- Avoir déjà programmé un peu (variables, boucles) aide, mais n'est pas obligatoire
- Un JDK 21 et un IDE (IntelliJ IDEA ou VS Code) installés
Étape 1 sur 11 : Pourquoi Java et comment ça tourne
Chapitre 1
Pourquoi Java et comment ça tourne
Avant d'écrire une ligne, comprendre ce qui rend Java particulier : la promesse « écris une fois, exécute partout » et la machine virtuelle qui la tient.
Java est l'un des langages les plus utilisés au monde, surtout en entreprise : banque, assurance, industrie, applications Android, gros systèmes qui doivent tourner de façon fiable pendant des années. Il a la réputation d'être un peu verbeux, il faut écrire plus de code que dans un langage comme Python, mais cette verbosité a une contrepartie précieuse : le code est explicite, structuré, et l'outillage (compilateur, IDE) attrape énormément d'erreurs avant même que le programme s'exécute.
La grande idée de Java tient en une phrase : « write once, run anywhere », écris une fois, exécute partout. Pour comprendre comment cette promesse est tenue, il faut distinguer trois sigles. Le JDK (Java Development Kit) est la trousse à outils du développeur : il contient le compilateur et tout le nécessaire pour créer des programmes. Le JRE est le sous-ensemble qui permet seulement d'exécuter un programme Java. Et la JVM (Java Virtual Machine) est la machine virtuelle qui fait réellement tourner ton code.
Le cheminement d'un programme Java
Contrairement à un langage interprété, Java passe par une étape de compilation, mais pas vers du code machine spécifique à ton ordinateur. Le compilateur (javac) transforme ton fichier source .java en bytecode (.class), un format intermédiaire universel. C'est ensuite la JVM, installée sur chaque machine, qui lit ce bytecode et le traduit à la volée pour le système sur lequel elle tourne. Résultat : le même fichier compilé s'exécute sur Windows, macOS ou Linux, à condition qu'une JVM y soit installée. La JVM est la couche qui absorbe les différences entre systèmes.
public class Main {
public static void main(String[] args) {
System.out.println("Bonjour, Java !");
}
}Ce petit programme montre déjà deux règles structurantes de Java. D'abord, tout vit dans une classe : il n'existe pas de code « en vrac » hors d'une classe, contrairement à un script Python. Ensuite, l'exécution commence toujours par une méthode très particulière, public static void main(String[] args) : c'est le point d'entrée que la JVM cherche pour démarrer. Tu n'as pas besoin de tout comprendre de cette ligne maintenant, chaque mot (public, static, void) prendra son sens au fil du cours.
javac Main.java # produit Main.class (le bytecode)
java Main # la JVM exécute le bytecodeEn pratique, ton IDE fait tout
javac à la main : IntelliJ IDEA ou VS Code compilent et lancent ton programme d'un clic (ou avec un raccourci). Mais comprendre ce qui se passe dessous, source → bytecode → JVM, t'évitera d'être perdu·e le jour où une erreur de compilation surgit.Vrai ou faux ?
Le compilateur Java transforme ton code source directement en code machine spécifique à ton système d'exploitation.
Chapitre 2
Types, variables et opérateurs
Java est un langage typé statiquement : chaque variable a un type déclaré, connu à la compilation. C'est plus strict, mais ça attrape des erreurs très tôt.
Une variable, c'est une boîte nommée qui contient une valeur. En Java, tu dois annoncer le type de cette boîte au moment de la déclarer, et ce type ne changera plus : c'est le typage statique. Là où Python te laisse mettre n'importe quoi dans une variable, Java refuse de compiler si tu tentes de ranger un texte dans une boîte à nombres. C'est plus contraignant au premier abord, mais ça transforme des bugs qui n'apparaîtraient qu'à l'exécution en erreurs signalées immédiatement dans ton éditeur.
Types primitifs vs objets
Java distingue deux grandes familles. Les types primitifs représentent des valeurs simples et s'écrivent en minuscules : int (entier), long (grand entier), double (nombre à virgule), boolean (vrai/faux), char (un caractère). Les objets, eux, commencent par une majuscule et sont bien plus riches : String (une chaîne de texte) est le plus courant. Cette distinction primitif/objet a des conséquences concrètes, notamment sur la façon de comparer des valeurs, comme on le verra plus bas.
int age = 30; // entier
double prix = 19.99; // nombre à virgule
boolean estActif = true; // vrai / faux
char initiale = 'A'; // un seul caractère, entre apostrophes
String nom = "Alice"; // texte, entre guillemets
// 'var' laisse Java deviner le type (inférence), depuis Java 10
var ville = "Lyon"; // Java sait que c'est un StringDepuis Java 10, le mot-clé var permet de laisser le compilateur deviner le type à partir de la valeur affectée : c'est l'inférence de type. var ville = "Lyon" crée bien une variable de type String, var ne rend pas Java « non typé », il t'évite juste de répéter un type évident. À réserver aux cas où le type est clair au premier coup d'œil.
Opérateurs et conversions
- Arithmétique :
+,-,*,/,%(reste de division) - Comparaison :
==,!=,<,>,<=,>= - Logique :
&&(et),||(ou),!(non) - Concaténation :
+fonctionne aussi pour coller des chaînes
Le piège de la division entière
5 / 2 donne 2 en Java, pas 2.5 ! Quand les deux nombres sont des entiers, la division est entière. Pour obtenir 2.5, il faut qu'au moins un des deux soit un double : 5.0 / 2 ou (double) 5 / 2. C'est une erreur classique de débutant·e qui fausse des calculs sans lever d'erreur.Vrai ou faux ?
Pour comparer le contenu de deux chaînes de caractères en Java, on utilise ==.
Chapitre 3
Conditions et boucles
Un programme qui ne fait que des calculs en ligne droite est vite limité. Les structures de contrôle lui donnent la capacité de décider et de répéter.
Toute la logique d'un programme repose sur deux idées simples : prendre une décision selon une condition, et répéter une action. Java offre pour cela une syntaxe très proche de celle de la plupart des langages en accolades (C, JavaScript, C#), ce qui la rend familière si tu viens de l'un d'eux. La règle de base : une condition est toujours une expression boolean (qui vaut true ou false), et les blocs de code sont délimités par des accolades { }.
Les conditions : if / else et switch
int note = 14;
if (note >= 16) {
System.out.println("Très bien");
} else if (note >= 10) {
System.out.println("Reçu");
} else {
System.out.println("À retravailler");
}
// switch moderne (depuis Java 14) : plus concis, sans 'break'
String mention = switch (note / 2) {
case 10, 9 -> "Excellent";
case 8, 7 -> "Bien";
default -> "Peut mieux faire";
};Le switch permet de comparer une valeur à plusieurs cas sans empiler les else if. Sa forme moderne avec des flèches (->) est bien plus sûre que l'ancienne : elle n'a pas besoin du mot-clé break et peut directement renvoyer une valeur, comme dans l'exemple ci-dessus où mention reçoit le résultat du switch.
Les boucles : for, while, for-each
// for classique : quand tu contrôles un compteur
for (int i = 0; i < 5; i++) {
System.out.println("Tour numéro " + i);
}
// while : tant qu'une condition reste vraie
int reste = 100;
while (reste > 0) {
reste -= 25;
}
// for-each : parcourir une collection, sans se soucier de l'index
String[] fruits = {"pomme", "banane", "cerise"};
for (String fruit : fruits) {
System.out.println(fruit);
}Trois formes de boucles, trois usages. Le for classique sert quand tu as besoin d'un compteur explicite (« répète 5 fois »). Le while répète tant qu'une condition tient, sans savoir à l'avance combien de fois. Le for-each (littéralement « pour chaque ») parcourt tous les éléments d'un tableau ou d'une collection sans que tu aies à gérer un index, c'est le plus lisible et celui que tu utiliseras le plus souvent, notamment avec les collections du chapitre 7.
Préfère le for-each quand tu peux
for-each est plus clair et évite les erreurs d'index (i <= taille au lieu de <, un grand classique). Garde le for classique pour les cas où tu as vraiment besoin du numéro de position.Chapitre 4
Les méthodes
Une méthode, c'est un bloc de code nommé et réutilisable. Bien découper son programme en méthodes, c'est la première étape vers un code lisible et testable.
Copier-coller le même bout de code à dix endroits est le meilleur moyen de créer des bugs : le jour où il faut le corriger, on en oublie forcément un. Une méthode résout ça en donnant un nom à un bloc de code que l'on peut appeler autant de fois qu'on veut. C'est aussi l'unité de base du raisonnement : un programme bien écrit se lit comme une suite de méthodes aux noms parlants, chacune faisant une seule chose.
Anatomie d'une méthode
// visibilité type de retour nom (paramètres typés)
public int addition (int a, int b) {
return a + b; // 'return' renvoie la valeur au code appelant
}
// 'void' signifie : ne renvoie rien, fait juste une action
public void direBonjour(String nom) {
System.out.println("Bonjour " + nom);
}
// Appels
int total = addition(3, 4); // total vaut 7
direBonjour("Alice");Une méthode se lit de gauche à droite : sa visibilité (public, on y reviendra avec l'encapsulation), son type de retour (ce qu'elle renvoie, ici un int), son nom, et entre parenthèses ses paramètres, chacun avec son type. Le mot-clé return renvoie une valeur au code qui a appelé la méthode. Quand une méthode ne renvoie rien, elle se contente d'agir, comme afficher un message, son type de retour est void (« vide »).
La surcharge (overloading)
Java autorise plusieurs méthodes à porter le même nom tant que leurs paramètres diffèrent : c'est la surcharge. Le compilateur choisit la bonne version selon les arguments que tu passes. C'est très pratique pour proposer plusieurs façons d'appeler la même opération.
public int addition(int a, int b) {
return a + b;
}
// Même nom, mais trois paramètres : c'est une autre méthode
public int addition(int a, int b, int c) {
return a + b + c;
}
addition(2, 3); // appelle la première
addition(2, 3, 4); // appelle la secondestatic ou pas ?
static appartient à la classe et s'appelle sans créer d'objet (Math.max(3, 7)). Une méthode non static appartient à une instance précise et a besoin d'un objet pour être appelée. On garde static pour les utilitaires purs (des calculs qui ne dépendent d'aucun état) ; le reste, le cœur de la programmation objet, sera d'instance, c'est l'objet du chapitre suivant.Chapitre 5
Classes et objets : la POO
Le cœur de Java. Une classe est un plan ; un objet est une réalisation concrète de ce plan. C'est le concept qui structure tout le reste.
Java est un langage orienté objet (POO), et ce chapitre est le plus important du cours : tout ce qui suit en découle. L'idée centrale est de regrouper, dans une même entité, des données et les comportements qui agissent dessus. Une classe décrit ce regroupement, c'est un moule, un plan. Un objet (ou instance) est un exemplaire concret fabriqué à partir de ce plan. La classe Voiture définit ce qu'est une voiture en général ; ta voiture rouge immatriculée AB-123-CD est un objet de cette classe.
Attributs, constructeur, méthodes
public class Compte {
// Attributs : les données que porte chaque objet
private String titulaire;
private double solde;
// Constructeur : appelé pour créer un objet, initialise les attributs
public Compte(String titulaire, double soldeInitial) {
this.titulaire = titulaire; // 'this' = l'objet courant
this.solde = soldeInitial;
}
// Méthode d'instance : un comportement de l'objet
public void deposer(double montant) {
this.solde += montant;
}
}Trois éléments composent cette classe. Les attributs (titulaire, solde) sont les données que chaque objet portera, avec ses propres valeurs. Le constructeur, une méthode spéciale qui porte le nom de la classe, s'exécute au moment où l'on crée un objet et sert à initialiser ces attributs. Le mot-clé this désigne « l'objet courant » et sert à lever l'ambiguïté entre un attribut et un paramètre de même nom. Enfin, les méthodes d'instance (deposer) définissent ce que l'objet sait faire.
Créer et utiliser un objet
// 'new' fabrique un objet à partir de la classe
Compte compte = new Compte("Alice", 100.0);
compte.deposer(50.0);
// Le solde de CET objet vaut maintenant 150.0Le mot-clé new déclenche la fabrication d'un objet : il appelle le constructeur et te rend une référence vers le nouvel objet, que tu ranges dans une variable. Tu peux créer autant de comptes que tu veux à partir de la même classe, chacun avec son propre titulaire et son propre solde, c'est toute la puissance du modèle : un plan, une infinité d'objets indépendants.
L'encapsulation
Tu as remarqué le mot-clé private devant les attributs ? C'est l'encapsulation, un principe fondamental : on cache les données internes d'un objet pour ne les rendre accessibles qu'à travers des méthodes contrôlées. Ainsi, personne ne peut mettre le solde à une valeur absurde en écrivant directement compte.solde = -9999 ; il faut passer par deposer() ou retirer(), qui peuvent vérifier que l'opération est valide. Les méthodes d'accès s'appellent traditionnellement des getters (pour lire) et des setters (pour modifier).
public class Compte {
private double solde;
// getter : lecture contrôlée
public double getSolde() {
return this.solde;
}
// setter avec validation : on refuse un dépôt négatif
public void deposer(double montant) {
if (montant <= 0) {
throw new IllegalArgumentException("Le montant doit être positif");
}
this.solde += montant;
}
}Pourquoi c'est le socle de Spring Boot
Task, un service qui l'orchestre, l'injection d'objets par le constructeur. Maîtriser ce chapitre, c'est déjà avoir un pied dans le framework.Chapitre 6
Héritage, interfaces, polymorphisme
Trois mécanismes pour réutiliser du code et modéliser des relations entre classes. Ils font peur au début, mais reposent sur des idées simples.
Une fois qu'on sait créer des classes, une question se pose : comment éviter de réécrire les mêmes attributs et méthodes dans des classes qui se ressemblent ? Java répond avec trois outils complémentaires, l'héritage, les interfaces et le polymorphisme. Ils permettent de factoriser du code commun et de modéliser proprement des relations entre concepts. On les découvre ici sans chercher l'exhaustivité : l'objectif est de comprendre l'idée de chacun.
L'héritage : la relation « est un »
L'héritage permet à une classe d'hériter des attributs et méthodes d'une autre. On l'utilise pour exprimer une relation « est un » : un Chien est un Animal. La classe fille (Chien) récupère tout ce que la classe parente (Animal) possède, et peut y ajouter ou redéfinir des comportements avec l'annotation @Override.
public class Animal {
protected String nom; // 'protected' : visible par les classes filles
public Animal(String nom) {
this.nom = nom;
}
public String crier() {
return "...";
}
}
public class Chien extends Animal { // Chien hérite d'Animal
public Chien(String nom) {
super(nom); // appelle le constructeur du parent
}
@Override
public String crier() { // redéfinit le comportement
return "Wouf !";
}
}Le mot-clé extends établit l'héritage, et super(nom) appelle le constructeur de la classe parente. L'annotation @Override signale que crier() redéfinit la méthode héritée, elle n'est pas obligatoire, mais fortement recommandée : elle permet au compilateur de vérifier que tu redéfinis bien une méthode existante, et non que tu en crées une nouvelle par erreur de frappe.
Les interfaces : un contrat
Une interface est un contrat : elle déclare des méthodes sans les implémenter, et toute classe qui « signe » ce contrat (avec implements) s'engage à fournir ces méthodes. C'est plus souple que l'héritage : une classe ne peut hériter que d'une seule classe parente, mais elle peut implémenter plusieurs interfaces. Les interfaces décrivent des capacités (« est capable de… ») plutôt qu'une identité.
public interface Volant {
void voler(); // méthode sans corps : juste le contrat
}
public class Oiseau implements Volant {
@Override
public void voler() {
System.out.println("L'oiseau bat des ailes");
}
}Le polymorphisme
Le polymorphisme (« plusieurs formes ») est la conséquence élégante des deux mécanismes précédents : on peut manipuler des objets de types différents à travers un type commun, et Java appelle automatiquement la bonne version de la méthode. Ranger un Chien et un Chat dans une variable de type Animal et appeler crier() sur chacun produira « Wouf ! » puis « Miaou ! », sans que le code appelant ait à connaître le type précis. C'est ce qui rend un programme extensible : on peut ajouter un nouvel animal sans toucher au code qui les fait crier.
Vrai ou faux ?
En Java, une classe peut hériter de plusieurs classes parentes à la fois.
Chapitre 7
Les collections
Un tableau a une taille figée. Les collections offrent des structures dynamiques et puissantes pour stocker et manipuler des groupes d'objets.
Dès qu'on manipule plusieurs éléments, une liste de tâches, un annuaire, un panier, on a besoin de structures adaptées. Le tableau (String[]) existe en Java mais reste rigide : sa taille est fixée à la création. Les collections du framework standard (java.util) sont bien plus souples et couvrent trois grands besoins, qu'il faut savoir distinguer pour choisir la bonne.
List, Set, Map : trois besoins
- List (
ArrayList) : une séquence ordonnée qui accepte les doublons. « Ma liste de courses, dans l'ordre. » - Set (
HashSet) : un ensemble sans doublon, sans ordre garanti. « L'ensemble des tags uniques. » - Map (
HashMap) : des paires clé → valeur. « Un annuaire : à chaque nom, un numéro. »
import java.util.*;
// List : ordonnée, doublons autorisés
List<String> courses = new ArrayList<>();
courses.add("pain");
courses.add("lait");
courses.add("pain"); // le doublon est accepté
System.out.println(courses.get(0)); // "pain"
// Set : pas de doublon
Set<String> tags = new HashSet<>();
tags.add("java");
tags.add("java"); // ignoré : déjà présent
System.out.println(tags.size()); // 1
// Map : clé -> valeur
Map<String, Integer> ages = new HashMap<>();
ages.put("Alice", 30);
ages.put("Bob", 25);
System.out.println(ages.get("Alice")); // 30Les génériques : le <String>
Tu as remarqué les chevrons <String> ? Ce sont les génériques. Ils précisent le type des éléments que la collection va contenir. List<String> se lit « une liste de String ». Leur intérêt est double : le compilateur t'empêche d'y mettre un autre type par erreur, et tu récupères tes éléments directement dans le bon type, sans conversion. Une collection sans génériques accepterait n'importe quoi et te forcerait à des conversions manuelles risquées, à éviter absolument.
Parcourir une collection
// Le for-each, idéal pour parcourir
for (String article : courses) {
System.out.println(article);
}
// Aperçu des streams (Java 8+) : filtrer et transformer de façon déclarative
long nbLongs = courses.stream()
.filter(a -> a.length() > 3)
.count();Le for-each vu au chapitre 3 est la façon la plus simple de parcourir une collection. Java propose aussi les streams, une manière plus déclarative de filtrer, transformer et agréger des données (« garde les articles de plus de 3 lettres, puis compte-les »). C'est un sujet plus avancé, retiens simplement que ça existe et que tu le croiseras vite ; l'essentiel pour débuter est de savoir choisir entre List, Set et Map, et de parcourir avec un for-each.
Vrai ou faux ?
Pour stocker une association « identifiant → objet » (par exemple un numéro de compte vers un compte), la structure la plus adaptée est une List.
Chapitre 8
Les exceptions et les bonnes pratiques
Un programme robuste ne se contente pas de marcher quand tout va bien : il gère proprement les cas où quelque chose tourne mal. C'est le rôle des exceptions.
Que se passe-t-il quand un utilisateur saisit du texte là où on attendait un nombre, ou qu'un fichier attendu n'existe pas ? En Java, ces situations anormales déclenchent une exception : un objet spécial qui « remonte » dans le programme jusqu'à ce que quelqu'un s'en occupe. Si personne ne la gère, le programme s'arrête net en affichant une trace d'erreur. Gérer les exceptions, c'est décider quoi faire face à l'imprévu au lieu de laisser le programme planter.
try / catch / finally
try {
int resultat = 10 / diviseur; // peut échouer si diviseur == 0
System.out.println(resultat);
} catch (ArithmeticException e) {
// On attrape l'erreur et on réagit proprement
System.out.println("Division par zéro impossible");
} finally {
// 'finally' s'exécute TOUJOURS, erreur ou non (nettoyage)
System.out.println("Calcul terminé");
}Le bloc try entoure le code susceptible d'échouer. Si une exception survient, l'exécution saute immédiatement dans le bloc catch correspondant, où tu décides de la réaction (afficher un message clair, réessayer, journaliser). Le bloc finally, optionnel, s'exécute dans tous les cas, qu'il y ait eu une erreur ou non, et sert typiquement au nettoyage (fermer un fichier, libérer une ressource).
Checked vs unchecked
Java distingue deux familles d'exceptions. Les checked (comme IOException) doivent obligatoirement être gérées ou déclarées : le compilateur t'y force, car elles représentent des problèmes prévisibles et extérieurs (un fichier absent, une panne réseau). Les unchecked (comme NullPointerException ou ArithmeticException) ne sont pas imposées par le compilateur : elles signalent le plus souvent un bug de programmation qu'il vaut mieux corriger que rattraper.
La NullPointerException, terreur du débutant
NullPointerException (NPE) survient quand tu appelles une méthode sur une variable qui vaut null (« rien »). C'est l'erreur la plus fréquente en Java. Deux réflexes : vérifier qu'une variable n'est pas null avant de l'utiliser, et découvrir Optional, un type introduit pour exprimer explicitement « il peut ne rien y avoir » et forcer à traiter ce cas.Quelques conventions à adopter dès maintenant
- Classes en
PascalCase:CompteBancaire - Méthodes et variables en
camelCase:calculerSolde,montantTotal - Constantes en
MAJUSCULES_AVEC_UNDERSCORES:TAUX_TVA - Des noms explicites :
nombreEssaisplutôt quen - Une méthode = une seule responsabilité, un nom qui dit ce qu'elle fait
🧭 Ton programme plante avec une NullPointerException
Tu récupères un compte dans une Map par son identifiant, puis tu appelles une méthode dessus, et le programme s'arrête sur une <code>NullPointerException</code>. Que fais-tu ?
La ligne fautive est compte.deposer(50), où compte vient de comptes.get(id). Quelle est ta première hypothèse ?
Pour aller plus loin
- La documentation officielle de Java (Oracle) · Oracle (en anglais) (nouvel onglet)
- Apprendre Java, tutoriel de référence (Baeldung) · Baeldung (en anglais) (nouvel onglet)
- Le framework des collections Java expliqué · dev.java (en anglais) (nouvel onglet)
- Enchaîne avec : Java et Spring Boot · Ce site (nouvel onglet)
🛠️ Exercice optionnel
Un mini gestionnaire de tâches en Java
Tu vas assembler presque tout le cours dans un petit programme console : une classe Tache, une List pour les stocker, des méthodes pour les manipuler, et une boucle pour afficher le résultat. Bonus : c'est exactement le domaine (Task) que tu retrouveras dans le cours Spring Boot.
Ta mission
- Classe
Tache: deux attributsprivate,titre(String) etfaite(boolean), un constructeur qui initialisetitreet metfaiteàfalse, et des getters. - Une méthode
marquerFaite()qui passefaiteàtrue(encapsulation : on ne modifie pas l'attribut de l'extérieur). - Programme principal : crée une
List<Tache>, ajoute 3 tâches. - Marque la deuxième tâche comme faite via sa méthode.
- Parcours la liste avec un
for-eachet affiche chaque tâche avec une coche[x]si elle est faite,[ ]sinon. - Bonus : ajoute une méthode qui compte les tâches restantes (non faites).
Tu bloques ? Des indices, à dévoiler quand tu en as besoin.
Indice 1
Indice masqué.
Indice 2
Indice masqué.
Indice 3
Indice masqué.
✅ QCM de fin de cours
Teste tes acquis
10 questions, plusieurs réponses parfois possibles. Coche tout ce qui te semble juste, puis valide pour voir ton score et les explications.
- 1
Que produit le compilateur
javacà partir d'un fichier.java? - 2
Comment comparer correctement le contenu de deux
String? - 3
Que vaut
5 / 2en Java ? - 4
À quoi sert le mot-clé
new? - 5
Que garantit l'encapsulation (attributs
private+ getters/setters) ? - 6
À quoi sert l'annotation
@Override? - 7
Combien de classes une classe Java peut-elle avoir comme parent direct ?
- 8
Quelle collection choisir pour un annuaire « nom → numéro » ?
- 9
Que signifient les chevrons dans
List<String>? - 10
Une
NullPointerExceptionsurvient quand…
Tu peux laisser des questions sans réponse, elles compteront comme fausses.
🎓 Attestation
Ton attestation de réussite
Termine le QCM avec au moins 80% de bonnes réponses pour débloquer ton attestation de réussite.
Tu veux ce cours pour ton équipe ?
Je peux adapter et animer ce cours pour tes formateur·ices ou tes apprenant·es, en présentiel ou en distanciel. Parlons-en pendant l'audit gratuit.
Réserver un audit gratuit →