Maison >Java >javaDidacticiel >Pourquoi la valeur est-elle uniquement transmise en Java ?
Le passage des paramètres en Java est-il passé par valeur ou par référence ? Cette question est très basique, mais beaucoup de gens sont un peu confus
Nous devons d'abord comprendre plusieurs concepts sur les paramètres
Paramètres formels : Paramètres utilisés lors de la définition d'une fonction pour recevoir des fonctions entrantes Paramètres, par exemple, si nous écrivons une fonction, les paramètres de la fonction sont des paramètres formels
public void test(String str) { //str为形式参数 System.out.println(str); }
Paramètres réels :Lorsque nous appelons une fonction, les paramètres entre parenthèses après le nom de la fonction sont appelés paramètres réels et doivent avoir une certaine valeur, comme le montre l'exemple ci-dessous Comme le montre
public static void main(String[] args) { A a = new A(); a.test("小 明"); //"小 明"则为实际参数 }
, nous pouvons constater que lors de l'appel d'une fonction paramétrée, les paramètres réels seront transmis aux paramètres formels.
Il existe généralement deux situations pour les paramètres dans ce processus de passageTransmission de valeur et transmission de référence.
Transmission de valeurs : lors de l'appel d'une fonction, copiez les paramètres réels et transmettez-les à la fonction. La modification des paramètres à l'intérieur de la fonction n'affectera pas les paramètres réels, c'est-à-dire que crée une copie et n'affectera pas le. objet natif
ne crée pas de copie, cela affectera l'objet natif
types de données de base et les types de données de référence À l'exception des 8 types de données de base. , ce sont tous des types de données de référence, à savoir byte, short , int, long, char, boolean, float, double
byte,short,int,long,char,boolean,float,double
对于这个问题,我们先来看几个例子慢慢道来:
public class TestBasic { public static void main(String[] args) { int num1 = 10; int num2 = 20; change(num1, num2); System.out.println("=============="); System.out.println("num1 = " + num1); System.out.println("num2 = " + num2); } public static void change(int param1, int param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1 = 333; param2 = 444; System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
结果:
param1 = 10
param2 = 20
after change....
param1 = 333
param2 = 444
==============
num1 = 10
num2 = 20
我们可以发现,change()方法内对变量重新赋值,并未改变变量num1和num2的值,改变的只是change()方法内的num1和num2的副本。我们需要知道,基本数据类型在内存中只有一块存储空间,分配在栈stack中。
Java传参的类型如果是基本数据类型,是值传递。
public class TestQuote { public static void main(String[] args) { String str = "小明"; StringBuilder str2 = new StringBuilder("今天天气好"); change(str,str2); System.out.println("=============="); System.out.println("str = " + str); System.out.println("str2 = " + str2); } public static void change(String param1,StringBuilder param2) { System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); param1= "小张"; param2.append(",我们去钓鱼"); System.out.println("after change...."); System.out.println("param1 = " + param1); System.out.println("param2 = " + param2); } }
结果:
param1 = 小明
param2 = 今天天气好
after change....
param1 = 小张
param2 = 今天天气好,我们去钓鱼
str = 小明
str2 = 今天天气好,我们去钓鱼
我们发现str变量没有改变,但是str2变量却改变了,大家是不是迷惑了:Java传参的类型如果是引用数据类型,是值传递还是引用传递?
其实大家被一堆术语给忽悠了,笔者画了2张图,帮助大家理解:
before change():
after change():
在Java中,除了基本数据类型以外,其他的都是引用类型,引用类型在内存中有两块存储空间(一块在栈stack中,一块在堆heap中)。
如果参数是引用类型,传递的就是实参所引用的对象在栈中地址值的拷贝,这里创建的副本是 地址的拷贝。那就有人说了,可是它值变了呀,这明明就是"引用传递"嘛?
我们可以换个角度理解,如果我们把栈地址当成值,会创建栈地址副本(复制栈帧),栈地址最终并没有改变,改变的是堆内存中的值。这就好比栈地址是钥匙,我们copy了一把,它能打开保险箱。我们关心的是钥匙有没有花纹这种变化,至于打开保险箱后的钱多钱少,我们并不需要关心。
虽然调用完函数后,str2变量值(堆中的数据)改变了,但是参数是引用类型,传递的实参是 栈中地址值,这是我们关心的,拷贝的是栈中地址值,最终栈中地址值并没有改变。所以是符合值传递的定义创建副本,不会影响原生对象。
可能又有人问了,那str变量值为啥没有改变呢?其实这完全是由于String类
Java est-il passé par valeur ou par référence ?
🎜param1 = 10🎜Nous pouvons constater que la réaffectation des variables dans la méthode change() ne modifie pas les valeurs des variables num1 et num2 🎜Ce qui change, ce sont uniquement les copies. de num1 et num2 dans la méthode change(). 🎜Nous devons savoir que les types de données de base n'ont qu'un seul espace de stockage en mémoire, qui est alloué dans la 🎜stack🎜. 🎜🎜Si le type de paramètre passé en Java est un type de données de base, il est 🎜passé par valeur🎜. 🎜🎜🎜
param2 = 20
après changement ....
param1 = 333
param2 = 444
==============
num1 = 10
num2 = 20🎜
🎜param1 = Xiao Ming🎜Nous avons constaté que la variable str n'a pas changé, mais la La variable str2 a changé, tout le monde Êtes-vous confus : si le type de paramètre passé en Java est un type de données de référence, est-ce 🎜passé par valeur🎜 ou 🎜passé par référence🎜 ? 🎜🎜En fait, tout le monde a été trompé par un tas de termes. L'auteur a dessiné 2 images pour aider tout le monde à comprendre : 🎜🎜avant changement():🎜🎜🎜🎜après changement():🎜🎜🎜🎜En Java, à l'exception des types de données de base, tous les autres sont des types référence. Les types référence ont deux espaces de stockage en mémoire (un dans la pile et un dans le tas). 🎜🎜Si le paramètre est un type référence, ce qui est transmis est une copie de la valeur d'adresse de l'objet référencé par le paramètre réel sur la pile. La copie créée ici est une copie de l'adresse. Puis quelqu'un l'a dit, mais sa valeur a changé. Est-ce évidemment un « passage par référence » ? 🎜🎜Nous pouvons le comprendre sous un autre angle. Si nous traitons l'adresse de la pile comme une valeur, une copie de l'adresse de la pile sera créée (copiez le cadre de la pile au final, mais la valeur dans). la mémoire tas change. C'est comme si l'adresse de la pile était une clé. Si nous la copions, elle peut ouvrir le coffre-fort. Ce qui nous importe, c'est de savoir s'il y a un changement dans le motif de la clé. Quant au montant d'argent après l'ouverture du coffre-fort, nous n'avons pas besoin de nous en soucier. 🎜🎜Bien que la valeur de la variable str2 (données dans le tas) ait changé après l'appel de la fonction, le paramètre est un type de référence et le paramètre réel transmis est la valeur de l'adresse dans la pile. C'est ce qui nous préoccupe. copiée est la valeur de l'adresse dans la pile. La valeur de l'adresse finale sur la pile n'a pas changé. Par conséquent, la création d’une copie est conforme à la définition du 🎜transfert de valeur🎜 et n’affectera pas l’objet original. 🎜🎜Quelqu'un peut se demander à nouveau : pourquoi la valeur de la variable str ne change-t-elle pas ? En fait, cela est entièrement dû à la nature particulière de la
param2 = La météo d'aujourd'hui est bonne
après changement....
param1 = Xiao Zhang
param2 = Météo d'aujourd'hui D'accord, allons à la pêche
str = Xiao Ming
str2 = Il fait beau aujourd'hui, allons à la pêche🎜
String class
. Nous savons qu'elle est immuable et définitive. À ce stade, param1= "Xiao Zhang" dans la fonction créera en fait une nouvelle String. objet implicitement, et en même temps Un nouvel espace mémoire sera ouvert dans la mémoire tas, et param1 pointe vers cet espace mémoire nouvellement ouvert. Il n'y a aucun changement dans les données dans l'espace mémoire du tas pointé par l'adresse d'origine str. 🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!