Pass-By-Value en tant que mécanisme de passage de paramètres en Java

Pass-By-Value en tant que mécanisme de passage de paramètres en Java

 

1. introduction

Les deux modes les plus courants de passage d'arguments à des méthodes sont «passage par valeur» et «passage par référence». Différents langages de programmation utilisent ces concepts de différentes manières. As far as Java is concerned, everything is strictly Pass-by-Value.

Dans ce didacticiel, nous allons illustrer la manière dont Java transmet les arguments pour différents types.

2. Pass-by-Value vs Pass-by-Reference

Commençons par certains des différents mécanismes permettant de passer des paramètres aux fonctions:

  • valeur

  • référence

  • résultat

  • valeur-résultat

  • name

Les deux mécanismes les plus courants dans les langages de programmation modernes sont “Pass-by-Value” et “Pass-by-Reference”. Avant de continuer, abordons d'abord les points suivants:

2.1. Valeur Pass-by-Value

Lorsqu'un paramètre est transmis valeur par valeur, l'appelant et la méthode appelée opèrent sur deux variables différentes qui sont des copies l'une de l'autre. Les modifications apportées à une variable ne modifient pas l’autre.

Cela signifie que lors de l'appel d'une méthode,parameters passed to the callee method will be clones of original parameters. Toute modification effectuée dans la méthode appelée n'aura aucun effet sur les paramètres d'origine de la méthode appelante.

2.2. Pass-by-Reference

Lorsqu'un paramètre est passé par référence, l'appelant et l'appelé agissent sur le même objet.

Cela signifie que lorsqu'une variable est pass-by-reference,the unique identifier of the object is sent to the method. Toute modification apportée aux membres de l'instance du paramètre entraînera la modification de la valeur d'origine.

3. Passage de paramètres en Java

Les concepts fondamentaux de tout langage de programmation sont les «valeurs» et les «références». En Java,Primitive variables store the actual values, whereas Non-Primitives store the reference variables which point to the addresses of the objects they’re referring to. Les valeurs et les références sont stockées dans la mémoire de la pile.

Les arguments en Java sont toujours passés par valeur. Lors de l'appel de la méthode, une copie de chaque argument, qu'il s'agisse d'une valeur ou d'une référence, est créée dans la mémoire de pile, qui est ensuite transmise à la méthode.

Dans le cas de primitives, la valeur est simplement copiée dans la mémoire de pile, qui est ensuite transmise à la méthode appelée. dans le cas de non primitives, une référence dans la mémoire de pile pointe vers les données réelles qui résident dans le tas. Lorsque nous transmettons un objet, la référence en mémoire de pile est copiée et la nouvelle référence est transmise à la méthode.

Voyons maintenant cela en action à l'aide de quelques exemples de code.

3.1. Passer des types primitifs

Le langage de programmation Java proposeeight primitive data types. Primitive variables are directly stored in stack memory. Whenever any variable of primitive data type is passed as an argument, the actual parameters are copied to formal arguments and these formal arguments accumulate their own space in stack memory.

La durée de vie de ces paramètres formels ne dure que tant que cette méthode est utilisée et, au retour, ces arguments formels sont effacés de la pile et sont ignorés.

Essayons de le comprendre à l'aide d'un exemple de code:

public class PrimitivesUnitTest {

    @Test
    public void whenModifyingPrimitives_thenOriginalValuesNotModified() {

        int x = 1;
        int y = 2;

        // Before Modification
        assertEquals(x, 1);
        assertEquals(y, 2);

        modify(x, y);

        // After Modification
        assertEquals(x, 1);
        assertEquals(y, 2);
    }

    public static void modify(int x1, int y1) {
        x1 = 5;
        y1 = 10;
    }
}

Essayons de comprendre les assertions du programme ci-dessus en analysant comment ces valeurs sont stockées en mémoire:

  1. Les variables «x” et«y” dans la méthode principale sont des types primitifs et leurs valeurs sont directement stockées dans la mémoire de la pile

  2. Lorsque nous appelons la méthodemodify(), une copie exacte de chacune de ces variables est créée et stockée à un emplacement différent dans la mémoire de la pile

  3. Toute modification apportée à ces copies ne les concerne que et laisse les variables originales inchangées.

image

3.2. Passer des références d'objets

En Java, tous les objets sont stockés dynamiquement dans l’espace Heap sous le capot. Ces objets sont référencés à partir de références appelées variables de référence.

Un objet Java, contrairement aux Primitives, est stocké en deux étapes. Les variables de référence sont stockées dans la mémoire de la pile et l’objet auquel elles font référence est stocké dans une mémoire de tas.

Chaque fois qu'un objet est passé en tant qu'argument, une copie exacte de la variable de référence est créée qui pointe vers le même emplacement de l'objet dans la mémoire du tas que la variable de référence d'origine.

As a result of this, whenever we make any change in the same object in the method, that change is reflected in the original object. Cependant, si nous allouons un nouvel objet à la variable de référence transmise, il ne sera pas reflété dans l’objet original.

Essayons de comprendre cela à l'aide d'un exemple de code:

public class NonPrimitivesUnitTest {

    @Test
    public void whenModifyingObjects_thenOriginalObjectChanged() {
        Foo a = new Foo(1);
        Foo b = new Foo(1);

        // Before Modification
        assertEquals(a.num, 1);
        assertEquals(b.num, 1);

        modify(a, b);

        // After Modification
        assertEquals(a.num, 2);
        assertEquals(b.num, 1);
    }

    public static void modify(Foo a1, Foo b1) {
        a1.num++;

        b1 = new Foo(1);
        b1.num++;
    }
}

class Foo {
    public int num;

    public Foo(int num) {
        this.num = num;
    }
}

Analysons les assertions du programme ci-dessus. Nous avons passé les objetsandb dansmodify() method qui a la même valeur1. Au départ, ces références d'objet pointent vers deux emplacements d'objets distincts dans un espace de tas:image

Lorsque ces référencesand sont passées dans la méthodemodify(), il crée des copies miroir de ces référencesa1 andb1 qui pointent vers les mêmes anciens objets:

image

Dans la méthodemodify() , lorsque nous modifions la référencea1, cela change l'objet d'origine. Cependant, pour une référenceb1, we ont assigné un nouvel objet. Il pointe donc maintenant vers un nouvel objet dans la mémoire du tas.

Toute modification apportée àb1 ne reflètera rien dans l'objet d'origine:

image

4. Conclusion

Dans cet article, nous avons examiné la manière dont le passage de paramètre est géré dans le cas de primitives et de non-primitives.

Nous avons appris que le passage de paramètres en Java est toujours Pass-by-Value. Cependant, le contexte change selon qu’il s’agit de primitifs ou d’objets:

  1. Pour les types primitifs, les paramètres sont passés valeur par valeur

  2. Pour les types d'objet, la référence de l'objet est passage par valeur.

Les extraits de code utilisés dans cet article peuvent être trouvésover on GitHub.