Java : passage par référence ou par valeur ? Analyse complète

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : le combat éternel "par référence" vs "par valeur"



Si vous avez déjà programmé en Java et passé un tableau ou un objet à une méthode, puis vous êtes étonné que les données d'origine aient changé — vous n'êtes pas seul. Cette question tourmente les débutants (et pas seulement) depuis l'apparition du langage. Sur Stack Overflow, elle a accumulé des millions de vues, et les débats dans les commentaires ne s'éteignent pas depuis des années.



Aujourd'hui, nous allons une fois pour toutes clarifier : Java est-il "pass-by-reference" ou "pass-by-value" ? Spoiler : la réponse est sans équivoque, mais le diable, comme toujours, se cache dans les détails. Nous ne donnerons pas simplement une définition sèche, mais nous montrerons avec des exemples concrets comment fonctionne le passage d'arguments en Java, et pourquoi beaucoup s'y trompent.



Que disent les créateurs de Java ?



La documentation officielle et James Gosling lui-même (le créateur de Java) ne laissent aucune place au débat : Java transmet toujours les arguments par valeur (pass-by-value). Aucune exception. Ni pour les primitifs, ni pour les objets.



Mais alors pourquoi le code modifie-t-il les objets ? Pourquoi un List ou un tableau passé à une méthode est-il modifié ? Analysons cela.



Pass-by-value : qu'est-ce que cela signifie exactement ?



Pour commencer — une définition claire. Pass-by-value signifie que lors de l'appel d'une méthode, une copie de la valeur de la variable est créée, et c'est cette copie qui est transmise à la méthode. La variable d'origine (dans le code appelant) reste intacte.



Pass-by-reference — c'est lorsque la méthode reçoit une référence à la variable d'origine, et la méthode peut directement modifier sa valeur (par exemple, remplacer l'objet). Cela n'existe pas en Java.



Passons maintenant aux exemples.



Exemple 1 : types primitifs (int, double, boolean)



Avec les primitifs, tout est évident. Écrivons un code simple :



public class Main {    public static void main(String[] args) {        int x = 10;        changePrimitive(x);        System.out.println("Après la méthode x = " + x); // 10    }

public static void changePrimitive(int value) { value = 20; // on modifie la copie }}


Sortie :

Après la méthode x = 10


Tout est logique : nous avons transmis une copie du nombre 10, à l'intérieur de la méthode nous avons modifié la copie en 20, mais l'original est resté tel quel. C'est du pur pass-by-value.



Exemple 2 : objets (chaînes, listes, vos propres classes)



Et maintenant, le plus intéressant. Regardez :



public class Main {    public static void main(String[] args) {        StringBuilder sb = new StringBuilder("Hello");        changeStringBuilder(sb);        System.out.println("Après la méthode : " + sb); // Hello World!    }

public static void changeStringBuilder(StringBuilder builder) { builder.append(" World!"); // on modifie le contenu de l'objet }}


Sortie :

Après la méthode : Hello World!


« Ah ! — direz-vous. — L'objet a changé ! Donc, c'est du pass-by-reference ! »



Non. C'est le piège dans lequel tombent 90% des débutants. Analysons ce qui s'est réellement passé.



Qu'est-ce qui est stocké dans la variable sb ?



En Java, une variable de type objet (par exemple, StringBuilder, List, String) ne stocke pas l'objet lui-même. Elle stocke une référence (adresse) vers l'objet en mémoire. L'objet lui-même se trouve quelque part dans le tas (heap).



Lorsque vous transmettez sb à une méthode, vous transmettez une copie de cette référence. C'est-à-dire une copie de l'adresse. L'original et la copie pointent vers le même objet. Par conséquent, lorsque vous modifiez le contenu de l'objet via la copie de la référence, ces modifications sont visibles également via la référence d'origine.



Mais ! Si vous essayez d'assigner un nouvel objet au paramètre à l'intérieur de la méthode, la référence d'origine ne changera pas. Prouvons-le :



public class Main {    public static void main(String[] args) {        StringBuilder sb = new StringBuilder("Hello");        changeReference(sb);        S                

Blogs

Book Recommendations