Maison >Java >javaDidacticiel >Pourquoi la valeur est-elle uniquement transmise en Java ?

Pourquoi la valeur est-elle uniquement transmise en Java ?

王林
王林avant
2023-04-18 11:28:02929parcourir

Question classique

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

Paramètres formels et paramètres réels

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

  • Passage par référence : La méthode reçoit l'adresse référencée par le paramètre réel et ne créera pas de copie. Les modifications apportées aux paramètres formels affecteront les paramètres réels, c'est-à-dire que si

    ne crée pas de copie, cela affectera l'objet natif

Nous devons également savoir : Il existe 2 types de données en Java, les principaux sont les

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, doublebyte,short,int,long,char,boolean,float,double

Java是值传递还是引用传递

对于这个问题,我们先来看几个例子慢慢道来:

传参的类型:基本数据类型

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传参的类型如果是基本数据类型,是值传递

Pourquoi la valeur est-elle uniquement transmise en 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():

Pourquoi la valeur est-elle uniquement transmise en Java ?

after change():

Pourquoi la valeur est-elle uniquement transmise en Java ?

在Java中,除了基本数据类型以外,其他的都是引用类型,引用类型在内存中有两块存储空间(一块在栈stack中,一块在堆heap中)。

如果参数是引用类型,传递的就是实参所引用的对象在栈中地址值的拷贝,这里创建的副本是 地址的拷贝。那就有人说了,可是它值变了呀,这明明就是"引用传递"嘛?

我们可以换个角度理解,如果我们把栈地址当成值,会创建栈地址副本(复制栈帧),栈地址最终并没有改变,改变的是堆内存中的值。这就好比栈地址是钥匙,我们copy了一把,它能打开保险箱。我们关心的是钥匙有没有花纹这种变化,至于打开保险箱后的钱多钱少,我们并不需要关心。

虽然调用完函数后,str2变量值(堆中的数据)改变了,但是参数是引用类型,传递的实参是 栈中地址值,这是我们关心的,拷贝的是栈中地址值,最终栈中地址值并没有改变。所以是符合值传递的定义创建副本,不会影响原生对象。

可能又有人问了,那str变量值为啥没有改变呢?其实这完全是由于String类Java est-il passé par valeur ou par référence ?

🎜Pour ce problème, commençons par regardez quelques exemples et expliquez-le lentement :🎜

Passer les paramètres Type : Type de données de base

rrreee🎜Résultat :🎜
🎜param1 = 10
param2 = 20
après changement ....
param1 = 333
param2 = 444

==============

num1 = 10
num2 = 20🎜
🎜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🎜. 🎜🎜Pourquoi la valeur est-elle uniquement transmise en Java ?🎜

Type de paramètre : type de données de référence

rrreee 🎜Résultat : 🎜
🎜param1 = Xiao Ming
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🎜
🎜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():🎜🎜Pourquoi la valeur est-elle uniquement transmise en Java ?🎜🎜après changement():🎜🎜Pourquoi la valeur est-elle uniquement transmise en Java ?🎜🎜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 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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer