Avant de lire cet article, en fonction de votre propre expérience et de votre compréhension, vous pouvez d'abord réfléchir et choisir la méthode de transmission des paramètres des fonctions Java :
A. Est-ce transmis par valeur ?
B. Passé par référence ?
C. En partie par valeur et en partie par référence ?
La bonne réponse ne sera pas encore annoncée ici. Nous vous laissons trouver la réponse par vous-même à travers un exemple simple :
1. Définissez d’abord un type Value
public static class Value { valeur de chaîne privée = "valeur"; public String getValue() { valeur de retour } public void setValue (valeur de chaîne) { this.value = valeur } }
2. Écrivez deux fonctions newValue et modifierValue : newValue pointera le paramètre d'entrée vers un nouvel objet, et modifierValue appellera la méthode setValue du paramètre d'entrée pour modifier la valeur de l'objet.
public static void newValue(Value value) { value = new Value(); value.setValue("nouvelle valeur"); System.out.println("Dans newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); } public static void modifierValue(Valeur valeur) { value.setValue("nouvelle valeur"); System.out.println("Dans modifierValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); }
3. Code de test simple
public static void main(String[] args) { Value value1 = new Value(); System.out.println("Avant de modifier, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() ); // Pointez value1 vers le nouvel objet Value newValue(value1); System.out.println("Après modification, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "/n"); Value value2 = new Value(); Avant de modifier, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); // Utiliser la méthode set de l'objet pour modifier la valeur interne de l'objet submitValue(value2); System.out.println("Après modification, HashCode = " + value2.hashCode() + ", valeur = " + value2.getValue() );
4. Journal des résultats d'exécution :
Avant modification, HashCode = 12677476, valeur = valeur Dans newValue, HashCode = 33263331, valeur = nouvelle valeur Après modification, HashCode = 12677476, valeur = valeur Avant modification, HashCode = 6413875, valeur = valeur Dans editValue, HashCode = 6413875, valeur = nouvelle valeur Après modification, HashCode = 6413875, valeur = nouvelle valeur
5. Analyse des résultats :
Le code ci-dessus est un modèle de programmation très courant : définir | save | obtenir une valeur ou un objet en périphérie, transmettre l'objet en tant que paramètre à une méthode et modifier les propriétés et le comportement de l'objet dans la méthode. Cependant, les méthodes de modification des deux méthodes newValue et modifierValue sont différentes. Une fois la méthode appelée, l'objet est très différent de l'extérieur ! Comment comprendre cette différence ? Passons d’abord en revue les concepts de passage par valeur et de passage par référence :
* Le passage par valeur signifie que lorsque vous transmettez un argument à une fonction, la fonction reçoit une copie de la valeur d'origine. Ainsi, si la fonction modifie le paramètre, seule la copie est modifiée, tandis que la valeur d'origine reste inchangée.
* Le passage par référence signifie que lorsqu'un argument est passé à une fonction, la fonction reçoit l'adresse mémoire de la valeur d'origine plutôt qu'une copie de la valeur. Par conséquent, si la fonction modifie le paramètre, la valeur originale du paramètre (dans le code appelant en dehors du bloc fonction) change également.
Bonne réponse : A - Les fonctions Java transmettent les paramètres par valeur !
Analysez le journal :
* Dans la première section de la sortie du journal, le paramètre value1 est modifié pour pointer vers un nouvel objet à l'intérieur de la méthode newValue, et le hashCode et la valeur du nouvel objet sont affichés. Cependant, après avoir quitté le domaine de la méthode newValue, aucun changement. se produit à value1 dans la méthode principale. Ceci est conforme à la définition et aux caractéristiques du passage par valeur ; s'il est passé par référence, value1 devrait changer après l'appel de la méthode newValue(Value value).
* La deuxième sortie du journal montre que value2 effectue une opération setValue dans la méthode modifierValue. Le hashCode reste inchangé mais la valeur est modifiée après avoir quitté le domaine de la méthode modifierValue, value2 change dans la méthode principale. Les personnes qui ont utilisé C++ peuvent facilement comprendre ce phénomène comme suit : passer des paramètres de fonction par référence ! Parce que c'est très similaire au passage par référence en C++ ! Mais c’est justement là que l’on risque le plus de tomber dans des malentendus !
Le principe caché derrière les différents phénomènes des deux logs est que le langage Java transmet les paramètres par valeur et les objets par référence ; les objets exploités en Java sont en réalité des références aux objets opérationnels, et les objets eux-mêmes sont stockés dans le « tas », et la « référence » de l'objet est stockée dans un registre ou « pile ».
Le pseudocode décrit la différence entre la méthode newValue et la méthode modifierValue :
newValue{ Value_ref2 = value_ref1; // Passe la référence value_ref1 par valeur et obtient une copie de value_ref1 value_obj2 = new Value(); // value_obj2 est créé et initialisé dans le "tas" value_ref2 -> value_obj2; value_obj2 value_ref2 - >value_obj2.setValue("xxx"); // value_obj2; La valeur est modifiée printValueObj2(); // Ce qui est imprimé ici est la valeur de obj2} modifierValue{ Value_ref2 = value_ref1; // Passer la référence value_ref1 par valeur et obtenir une copie de value_ref1 value_ref2 ->value_obj1.setValue("xxx "); // La valeur de value_obj1 est modifiée printValueObj1(); // Ce qui est imprimé ici est la valeur de obj1}
C'est assez clair ! Lorsque value1_ref1 est transmis à la fonction en tant que paramètre, une copie de value1_ref2 est d'abord copiée pour être utilisée dans le domaine de fonction. À ce stade, les deux références pointent vers le même code value_obj dans la fonction newObject [value = new Value(); ] En fait, value1_ref1 pointe vers un nouvel objet value_obj2 ; les opérations set après cela sont toutes des opérations sur le nouvel objet ; la fonction editValue exploite directement value_obj1 via la méthode set, qui est différente de la fonction newValue.
Passer les paramètres par valeur
Lorsque vous appelez une méthode, vous devez fournir des paramètres et vous devez les fournir dans l'ordre spécifié dans la liste des paramètres.
Par exemple, la méthode suivante imprime un message n fois de suite :
public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) System.out.println(message);}
Exemple L'exemple suivant illustre l'effet du passage par valeur.
Ce programme crée une méthode qui échange deux variables.
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; System.out.println("Avant la méthode d'échange, num1 est " + num1 + " et num2 est " + num2) ; // Appel de la méthode swap swap(num1, num2); System.out.println("Après la méthode swap, num1 est " + num1 + " et num2 est " + num2); } /** Méthode pour échanger deux variables*/ public static void swap(int n1, int n2) { System.out.println("/tDans la méthode d'échange"); .out.println("/t/tAvant d'échanger n1 est " + n1 + " n2 est " + n2); // Échangez les valeurs de n1 et n2 int temp = n1 = n2; n2 = temp; System.out.println("/t/tAprès l'échange de n1 est " + n1 + " n2 est " + n2);
Les résultats de compilation et d'exécution de l'exemple ci-dessus sont les suivants :
Avant la méthode d'échange, num1 est 1 et num2 est 2 Dans la méthode d'échange Avant l'échange, n1 est 1, n2 est 2 Après l'échange, n1 est 2, n2 est 1. Après la méthode d'échange, num1 est 1 et num2 est 2.
Appelez la méthode swap en passant deux paramètres. Fait intéressant, les valeurs des paramètres réels ne changent pas après l'appel de la méthode.