web-dev-qa-db-fra.com

Java passe-t-il vraiment les objets par valeur?

Duplicata possible: Est Java passe par référence?

public class myClass{
    public static void main(String[] args){
        myObject obj = new myObject("myName");
        changeName(obj);
        System.out.print(obj.getName()); // This prints "anotherName"
    }
    public static void changeName(myObject obj){
        obj.setName("anotherName");
    }
}

Je sais que Java passe par valeur, mais pourquoi passe-t-il obj par référence dans l'exemple précédent et le change-t-il?

30
MBZ

Java passe toujours les arguments par valeur, PAS par référence. Dans votre exemple, vous passez toujours obj par sa valeur, pas la référence elle-même. Dans votre méthode changeName, vous assignez une autre référence (locale), obj, au même objet que vous l'avez passé en argument. Une fois que vous avez modifié cette référence, vous modifiez la référence d'origine, obj, qui est passée en argument.


MODIFIER:

Permettez-moi d'expliquer cela à travers un exemple:

public class Main
{
     public static void main(String[] args)
     {
          Foo f = new Foo("f");
          changeReference(f); // It won't change the reference!
          modifyReference(f); // It will change the object that the reference refers to!
     }
     public static void changeReference(Foo a)
     {
          Foo b = new Foo("b");
          a = b;
     }
     public static void modifyReference(Foo c)
     {
          c.setAttribute("c");
     }
}

Je vais l'expliquer par étapes:

1- Déclarer une référence nommée f de type Foo et l'affecter à un nouvel objet de type Foo avec un attribut "f".

Foo f = new Foo("f");

Enter image description here

2- Du côté méthode, une référence de type Foo avec un nom a est déclarée et elle est initialement affectée à null.

public static void changeReference(Foo a)

Enter image description here

3- Lorsque vous appelez la méthode changeReference, la référence a sera affectée à l'objet qui est passé en argument.

changeReference(f);

Enter image description here

4- Déclarer une référence nommée b de type Foo et l'affecter à un nouvel objet de type Foo avec un attribut "b".

Foo b = new Foo("b");

Enter image description here

5- a = b Réattribue la référence a PAS f à l'objet dont son attribut est "b".

Enter image description here


6- Lorsque vous appelez la méthode modifyReference(Foo c), une référence c est créée et affectée à l'objet avec l'attribut "f".

Enter image description here

7- c.setAttribute("c"); changera l'attribut de l'objet qui référence c pointe vers lui, et c'est le même objet qui référence f pointe vers lui.

Enter image description here

J'espère que vous comprenez maintenant comment fonctionne le passage d'objets comme arguments dans Java :)

101
Eng.Fouad

En Java, un descripteur d'objet ou l'identité d'un objet est considéré comme une valeur. Passer par la valeur signifie passer cette poignée, pas une copie complète de l'objet.

Une "référence" dans le terme "passer par référence" ne signifie pas non plus "référence à un objet". Cela signifie "référence à une variable" - un "compartiment" nommé dans une définition de fonction (ou, plutôt, un cadre d'appel) qui peut stocker une valeur.

Passer par référence signifierait que la méthode appelée pourrait changer valeurs variables dans la méthode appelante. (Par exemple, dans la bibliothèque standard C, la fonction scanf fonctionne de cette façon.) Ce n'est pas possible en Java. Vous pouvez toujours changer les propriétés d'un objet - ils ne sont pas considérés comme faisant partie de sa "valeur". Ce sont des objets indépendants complètement différents.

9
millimoose

Vous modifiez une propriété de obj, et non pas obj (le paramètre) lui-même.

Le fait est que si vous avez pointé obj vers autre chose dans changeName que ce changement ne serait pas reflété dans main.

Voir cet article pour plus de précisions.

2
Dave Newton

Il n'a pas changé d'obj (votre code ne le change pas de toute façon). S'il avait été adopté par référence, vous auriez pu écrire:

public static void changeName(myObject obj){
    obj = new myObject("anotherName");
}

Et faites imprimer "anotherName" par la méthode principale.

2
Maurice Perry

Java transmet une copie de ce que vous transmettez à votre fonction. Lorsqu'il s'agit d'un type primitif - ce sera la copie d'une valeur. Quand c'est un objet - vous passez la copie de référence. Dans votre exemple de code, vous modifiez l'une des propriétés des objets, mais pas la référence elle-même, donc le nom sera changé. Cependant, lorsque vous souhaitez affecter un nouvel objet à la variable obj dans la fonction changeName, vous modifiez la référence, donc obj extérieur aura une ancienne valeur.

1
mmatloka

C'est passer la référence à obj comme valeur (un peu déroutant je sais :)).

Disons donc qu'il fait une copie du pointeur sur la valeur d'obj et transmettons cela.

Cela signifie que vous pouvez faire des choses comme:

  public static void changeName(myObject obj){    
        obj.setName("anotherName");
        obj = new myObject();
    }

et la déclaration

System.out.print(obj.getName());

va toujours faire référence à l'ancien objet (celui que vous avez défini setName).

0
Mikel