web-dev-qa-db-fra.com

Les tableaux sont-ils passés par valeur ou par référence en Java?

Duplicate possible:
Est-ce que Java est-il "référencé"?

Les tableaux ne sont pas un type primitif en Java, mais ils ne sont pas non plus des objets , sont-ils donc passés par valeur ou par référence? Cela dépend-il du contenu du tableau, par exemple des références ou un type primitif?

152
Froskoy

Votre question est basée sur une fausse prémisse.

Les tableaux ne sont pas un type primitif en Java, mais ce ne sont pas non plus des objets ... "

En fait, tous les tableaux de Java sont des objets 1. Chaque type de tableau Java a Java.lang.Object comme super-type et hérite de la mise en œuvre de toutes les méthodes de l'API Object.

... alors sont-ils passés par valeur ou par référence? Cela dépend-il du contenu du tableau, par exemple des références ou un type primitif?

Réponses courtes: 1) passer par valeur, et 2) cela ne fait aucune différence.

Réponse plus longue:

Comme tous les objets Java, les tableaux sont passés par valeur ... mais la valeur est la référence au tableau. Ainsi, lorsque vous affectez quelque chose à une cellule du tableau dans la méthode appelée, vous affectez le même objet de tableau que celui que voit l'appelant.

Ce n'est PAS passé par référence. Réel passé par référence implique de transmettre l'adresse d'une variable . Avec real passé par référence, la méthode appelée peut affecter à sa variable locale, ce qui entraîne la mise à jour de la variable dans l'appelant.

Mais pas en Java. En Java, la méthode appelée peut mettre à jour le contenu du tableau et peut mettre à jour sa copie de la référence du tableau, mais elle ne peut pas mettre à jour la variable dans l'appelant qui contient la référence du tableau de l'appelant. Par conséquent ... ce que Java fournit n'est PAS passe-à-référence.

Voici quelques liens qui expliquent la différence entre passer-par-référence et passer-par-valeur. Si vous ne comprenez pas mes explications ci-dessus, ou si vous vous sentez enclin à être en désaccord avec la terminologie, vous devriez les lire.

Question connexe SO:

Contexte historique:

L'expression "passer par référence" était à l'origine "appel par référence" et elle a été utilisée pour distinguer la sémantique de FORTRAN (appel de référence) qui transmettait les arguments de celles d'ALGOL-60 (appel par valeur). et appel par nom).

  • Dans call-by-value, l'expression d'argument est évaluée en tant que valeur et cette valeur est copiée dans la méthode appelée.

  • Dans l'appel par référence, l'expression d'argument est partiellement évaluée en tant que "lvalue" (c'est-à-dire l'adresse d'une variable ou d'un élément de tableau) qui est transmise à la méthode d'appel. La méthode appelante peut alors directement lire et mettre à jour la variable/l’élément.

  • Dans call-by-name, l'expression d'argument réelle est transmise à la méthode d'appel (!!) qui peut l'évaluer plusieurs fois (!!!). Cela était compliqué à mettre en œuvre et pouvait être utilisé (abusé) pour écrire du code très difficile à comprendre. Appel par nom n'a été utilisé que dans ALGOL-60 (heureusement!).

UPDATE

En fait, l'appel par nom d'ALGOL-60 est similaire au passage d'expressions lambda en tant que paramètres. Le problème réside dans le fait que ces expressions non-exactement-lambda (appelées "thunks" au niveau de la mise en œuvre) peuvent indirectement modifier l’état des variables qui se trouvent dans la portée. la procédure/fonction appelante. Cela fait partie de ce qui les rendait si difficile à comprendre. (Voir la page Wikipedia sur Dispositif de Jensen par exemple.)


1. Rien dans le Q & A lié ( Tableaux dans Java et comment ils sont stockés dans la mémoire ) n'indique ou n'implique que les tableaux ne sont pas des objets.

99
Stephen C

Everything in Java are passed-by value.. Dans le cas d'un tableau (qui n'est rien d'autre qu'un objet), la référence du tableau est passée par valeur. (Tout comme une référence d'objet est passée par valeur).

Lorsque vous passez un tableau à une autre méthode, la référence à ce tableau est en fait copiée.

  • Toute modification du contenu du tableau par le biais de cette référence affectera le tableau d'origine.
  • Mais changer la référence pour pointer vers un nouveau tableau ne changera pas la référence existante dans la méthode originale.

Voir ce post ..

Java est-il "passe-à-référence" ou "passe-à-valeur"?

Voir cet exemple de travail: -

public static void changeContent(int[] arr) {

   // If we change the content of arr.
   arr[0] = 10;  // Will change the content of array in main()
}

public static void changeRef(int[] arr) {
   // If we change the reference
   arr = new int[2];  // Will not change the array in main()
   arr[0] = 15;
}

public static void main(String[] args) {
    int [] arr = new int[2];
    arr[0] = 4;
    arr[1] = 5;

    changeContent(arr);

    System.out.println(arr[0]);  // Will print 10.. 

    changeRef(arr);

    System.out.println(arr[0]);  // Will still print 10.. 
                                 // Change the reference doesn't reflect change here..
}
205
Rohit Jain

Les tableaux sont en fait des objets, donc une référence est passée (la référence elle-même est passée par valeur, encore confuse?). Exemple rapide:

// assuming you allocated the list
public void addItem(Integer[] list, int item) {
    list[1] = item;
}

Vous verrez les modifications apportées à la liste à partir du code appelant. Cependant, vous ne pouvez pas changer la référence elle-même, car elle est passée par valeur:

// assuming you allocated the list
public void changeArray(Integer[] list) {
    list = null;
}

Si vous transmettez une liste non nulle, elle ne sera pas nulle au moment du retour de la méthode.

59
Tudor

Non c'est faux. Les tableaux sont des objets spéciaux en Java. C'est donc comme si vous passiez par d'autres objets pour lesquels vous transmettez la valeur de la référence, mais pas la référence elle-même. Cela signifie que changer la référence d'un tableau dans la routine appelée ne sera pas reflété dans la routine appelante.

13
sakthisundar

Tout ce qui se trouve dans Java est passé par valeur.

Dans le cas du tableau, la référence est copiée dans une nouvelle référence, mais souvenez-vous que tout dans Java est passé par valeur.

Jetez un oeil à cet article intéressant pour plus d'informations ...

4
aleroot

La discussion définitive sur les tableaux se trouve à http://docs.Oracle.com/javase/specs/jls/se5.0/html/arrays.html#278 . Cela montre clairement que les tableaux Java sont des objets. La classe de ces objets est définie au 10.8.

La section 8.4.1 de la spécification de langue, http://docs.Oracle.com/javase/specs/jls/se5.0/html/classes.html#4042 , décrit comment les arguments sont passés à méthodes. Puisque la syntaxe Java est dérivée de C et C++, le comportement est similaire. Les types primitifs sont passés par valeur, comme pour C. Lorsqu'un objet est passé, une référence d'objet (pointeur) est passée par valeur, reflétant la syntaxe C consistant à transmettre un pointeur par valeur. Voir 4.3.1, http://docs.Oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4. ,

Concrètement, cela signifie que la modification du contenu d'un tableau dans une méthode est reflétée dans l'objet tableau dans l'étendue appelante, mais que la réaffectation d'une nouvelle valeur à la référence dans la méthode n'a aucun effet sur la référence dans l'étendue appelante. est exactement le comportement attendu d'un pointeur sur une structure en C ou un objet en C++.

Une partie au moins de la confusion dans la terminologie provient de l'histoire des langages de haut niveau avant l'utilisation commune de C. Dans les langages précédents, les langages de haut niveau populaires, référencer directement la mémoire par adresse était quelque chose à éviter autant que possible. était considéré comme le travail du langage de fournir une couche d’abstraction. Il était donc nécessaire que le langage prenne explicitement en charge un mécanisme permettant de renvoyer des valeurs à partir de sous-routines (pas nécessairement des fonctions). Ce mécanisme correspond à ce que l’on entend officiellement par "passer par référence".

Lorsque C a été introduit, il comportait une notion simplifiée d’appel de procédure, dans laquelle tous les arguments étaient en entrée uniquement, et la seule valeur renvoyée à l’appelant était un résultat de fonction. Cependant, l’objectif de passer des références pourrait être atteint grâce à l’utilisation explicite et étendue de pointeurs. Comme cela sert le même objectif, la pratique consistant à passer un pointeur en tant que référence à une valeur est souvent appelée familièrement un passage par référence. Si la sémantique d'un appel de routine pour qu'un paramètre soit passé par référence, la syntaxe de C nécessite que le programmeur passe explicitement un pointeur. Passer un pointeur par valeur est le modèle de conception pour la mise en oeuvre de la sémantique de passage par référence en C.

Comme il peut souvent sembler que le seul but des pointeurs bruts en C est de créer des bogues bloquants, les développements ultérieurs, en particulier Java, ont cherché à revenir à des moyens plus sûrs de transmettre des paramètres. Cependant, la prédominance de C obligeait les développeurs à imiter le style familier du codage en C. Le résultat est des références qui sont transmises de la même manière que les pointeurs, mais qui sont implémentées avec davantage de protections pour les rendre plus sûres. Une alternative aurait été la syntaxe riche d'un langage comme Ada, mais cela aurait présenté l'apparence d'une courbe d'apprentissage non souhaitée et réduit l'adoption probable de Java.

En bref, la conception du passage de paramètres pour les objets, y compris les tableaux, en Java, consiste essentiellement à servir l’intention sémantique du passage par référence, mais elle est modifiée. avec la syntaxe de passer une référence par valeur.

2
Steven McGrath

En réalité, même les références sont passées par valeur en Java, d’où une modification de la référence elle-même portée au niveau de la fonction appelée. Le compilateur et/ou la machine virtuelle Java transforment souvent un type de valeur en référence.

0
Jeff Watkins