Maison  >  Article  >  Java  >  Quelle est la différence entre passer par valeur et passer par référence en Java

Quelle est la différence entre passer par valeur et passer par référence en Java

青灯夜游
青灯夜游original
2023-01-04 11:50:005900parcourir

Différence : 1. Le transfert de valeur créera une copie, tandis que le transfert de référence ne crée pas de copie ; 2. Dans le transfert de valeur, l'objet d'origine ne peut pas être modifié dans la fonction, mais dans le transfert de référence, l'objet d'origine peut être modifié dans la fonction. Le passage par valeur signifie que lors de l'appel d'une fonction, une copie des paramètres réels est transmise à la fonction, de sorte que si les paramètres sont modifiés dans la fonction, les paramètres réels ne seront pas affectés, tandis que le passage par référence signifie que lors de l'appel de la fonction ; fonction, une copie des paramètres réels sera transmise à la fonction. L'adresse est transmise directement à la fonction, donc les modifications apportées aux paramètres de la fonction affecteront les paramètres réels.

Quelle est la différence entre passer par valeur et passer par référence en Java

L'environnement d'exploitation de ce tutoriel : système windows7, version java8, ordinateur DELL G3.

Paramètres réels et formels

Nous savons tous que les paramètres peuvent être définis lors de la définition d'une méthode en Java. Par exemple, la méthode main en Java, public static void main(String[ ] args), les arguments ici sont des paramètres. Les paramètres sont divisés en paramètres formels et paramètres réels dans les langages de programmation.

  • Paramètres formels : sont les paramètres utilisés lors de la définition du nom de la fonction et du corps de la fonction. Le but est de recevoir les paramètres transmis lors de l'appel de la fonction.

  • Paramètres réels : Lors de l'appel d'une fonction paramétrée, il existe une relation de transfert de données entre la fonction appelante et la fonction appelée. Lors de l'appel d'une fonction dans la fonction appelante, les paramètres entre parenthèses après le nom de la fonction sont appelés "paramètres réels"

Un exemple simple :

public static void main( String[ ] args) {
ParamTest pt = new ParamTest();
pt.sout( "Hollis");//实际参数为Hollis
}
public void sout( String name) {/!形式参数为name
system.out.println(name);
}

Les paramètres réels sont ceux qui sont réellement passés lors de l'appel d'une méthode paramétrée, et Formel les paramètres sont des paramètres utilisés pour recevoir le contenu des paramètres réels.

Passage par valeur et passage par référence

Comme mentionné ci-dessus, lorsque nous appelons une fonction paramétrée, les paramètres réels seront transmis aux paramètres formels. Cependant, dans les langages de programmation, il existe deux cas de transfert dans ce processus de transfert, à savoir le transfert par valeur et le transfert par référence. Voyons comment le passage par valeur et le passage par référence sont définis et distingués dans les langages de programmation.

Transmission de valeur signifie copier les paramètres réels et les transmettre à la fonction lors de l'appel de la fonction, de sorte que si les paramètres sont modifiés dans la fonction, les paramètres réels ne seront pas affectés.
Pass by reference signifie transmettre l'adresse des paramètres réels directement à la fonction lors de l'appel de la fonction. Ensuite, les modifications apportées aux paramètres dans la fonction affecteront les paramètres réels.

Avec les concepts ci-dessus, vous pouvez ensuite écrire du code et le pratiquer pour voir s'il s'agit d'un passage de valeur ou d'un passage de référence en Java. Ainsi, le morceau de code le plus simple est sorti :

public static void main( String[] args) {
     ParamTest pt = new ParamTest();
    int i = 10;
    pt.pass(i);
    System.out.println( "print in main , i is " +i);
}
public void pass(int j){
    j = 20;
    system.out.println( "print in pass , j is " + j);
}

Dans le code ci-dessus, nous avons la valeur de. le paramètre j est modifié dans la méthode pass, puis la valeur du paramètre est imprimée respectivement dans la méthode pass et la méthode principale. Le résultat de sortie est le suivant :

print in pass , j is 20
print in main , i is 10

On peut voir que la modification de la valeur de i à l'intérieur de la méthode pass ne change pas la valeur du paramètre réel i. Ainsi, selon la définition ci-dessus, quelqu'un est arrivé à la conclusion : le passage de méthode Java est un passage de valeur.
Cependant, certaines personnes ont vite soulevé des questions (haha, alors ne tirez pas de conclusions hâtives.). Ensuite, ils retireront le code suivant :

public static void main(String[ ] args) {
    ParamTest pt = new ParamTest();
    User hollis = new User();
    hollis.setName( "Hollis");
    hollis.setGender("Male");
    pt.pass(hollis);
    system.out.println( "print in main , user is " + hollis);}public void pass(User user) {
    user.setName( "hollischuang");
    System.out.println( "print in pass , user is " + user);}

est également une méthode pass, et la valeur du paramètre est également modifiée au sein de la méthode pass. Le résultat de sortie est le suivant :

print in pass , user is User{name='hollischuang', gender='Male '}
print in main , user is User{name='hollischuang' , gender='Male '}

Une fois la méthode pass exécutée, la valeur du paramètre réel est modifiée. Selon la définition du passage par référence ci-dessus, la valeur du paramètre réel n'est pas appelée. en passant par référence ? Par conséquent, sur la base des deux morceaux de code ci-dessus, quelqu'un est arrivé à une nouvelle conclusion : dans les méthodes Java, lors du passage de types ordinaires, il est passé par valeur, et lors du passage de types d'objet, il est passé par référence.
Cependant, cette affirmation est toujours fausse. Si vous ne me croyez pas, jetez un œil au transfert de paramètres suivant où le type de paramètre est un objet :

public static void main( string[] args) {
    ParamTest pt = new ParamTest();
    string name = "Hollis";
    pt.pass(name ) ;
    System.out.println( "print in main , name is " + name);
}
public void pass(string name) {
    name = "hollischuang";
    system.out.println( "print in pass , name is " + name);
}

Le résultat de sortie du code ci-dessus est

print in pass , name is hollischuangprint in main , name is Hollis

Quelle est l'explication : un objet est également transmis, mais le La valeur du paramètre d'origine n'est pas modifiée. Est-il passé ? Les objets sont à nouveau passés par valeur ?

Transmission de valeur en Java

Ci-dessus, nous avons donné trois exemples, mais les résultats sont également différents. et même de nombreux programmeurs avancés ont des doutes sur Java. Il y a une raison de confusion sur la transmission des types. En fait, ce que je veux vous dire, c'est que le concept ci-dessus n'est pas faux, mais il y a un problème avec l'exemple de code. Allez, laissez-moi vous exposer les points clés du concept, puis vous donner quelques exemples vraiment pertinents.

Transmission de valeur signifie copier les paramètres réels et les transmettre à la fonction lors de l'appel de la fonction, de sorte que si les paramètres sont modifiés dans la fonction, les paramètres réels ne seront pas affectés.
Passage par référence signifie transmettre l'adresse des paramètres réels directement à la fonction lors de l'appel de la fonction. Ensuite, la modification des paramètres dans la fonction affectera les paramètres réels.

Alors, laissez-moi vous résumer les points clés de la différence entre le passage de valeur et le passage de référence.


Passage par valeur Passage par référence
La différence fondamentale créera une copie Ne crée pas de copie
Tous les fonctions ne peuvent pas être modifiées. objet original la fonction peut changer l'objet original

我们上面看过的几个pass的例子中,都只关注了实际参数内容是否有改变。如传递的是User对象,我们试着改变他的name属性的值,然后检查是否有改变。其实,在实验方法上就错了,当然得到的结论也就有问题了。

为什么说实验方法错了呢?这里我们来举一个形象的例子。再来深入理解一下值传递和引用传递,然后你就知道为啥错了。

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。

你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。

但是,不管上面那种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了。那你说你会不会受到影响?而我们在pass方法中,改变user对象的name属性的值的时候,不就是在“砸电视”么。

还拿上面的一个例子来举例,我们真正的改变参数,看看会发生什么?

public static void main(String[ ] args){
    ParamTest pt = new ParamTest();
    User hollis = new User();
    hollis.setName( "Hollis");
    hollis.setGender("Male" );
    pt.pass(hollis);
    system.out.println("print in main , user is " + hollis);
    public void pass(User user) {
        user = new User();
        user.setName( "hollischuang");
        user.setGender( "Male");
        system.out.println( "print in pass , user is " + user);

上面的代码中,我们在pass方法中,改变了user对象,输出结果如下:

print in pass , user is User{name='hollischuang ' , gender='Male '}
print in main , user is User{name='Hollis', gender= 'Male '}

我们来画一张图,看一下整个过程中发生了什么,然后我再告诉你,为啥Java中只有值传递。

Quelle est la différence entre passer par valeur et passer par référence en Java

稍微解释下这张图,当我们在main中创建一个User对象的时候,在堆中开辟一块内存,其中保存了name和gender等数据。然后hollis持有该内存的地址ex123456(图1)。当尝试调用pass方法,并且hollis作为实际参数传递给形式参数user的时候,会把这个地址ex123456交给user,这时,user也指向了这个地址(图2)。然后在pass方法内对参数进行修改的时候,即user = newUser();,会重新开辟一块 eX456789的内存,赋值给user。后面对user的任何修改都不会改变内存eX123456的内容(图3)。

上面这种传递是什么传递?肯定不是引用传递,如果是引用传递的话,在user=new User()的时候,实际参数的引用也应该改为指向eX456789,但是实际上并没有。

通过概念我们也能知道,这里是把实际参数的引用的地址复制了一份,传递给了形式参数。所以,上面的参数其实是值传递,把实参对象引用的地址当做值传递给了形式参数。

我们再来回顾下之前的那个“砸电视”的例子,看那个例子中的传递过程发生了什么。

Quelle est la différence entre passer par valeur et passer par référence en Java

同样的,在参数传递的过程中,实际参数的地址eX1213456被拷贝给了形参,只是,在这个方法中,并没有对形参本身进行修改,而是修改的形参持有的地址中存储的内容。

所以,值传递和引用传递的区别并不是传递的内容。而是实参到底有没有被复制一份给形参。在判断实参内容有没有受影响的时候,要看传的的是什么,如果你传递的是个地址,那么就看这个地址的变化会不会有影响,而不是看地址指向的对象的变化。就像钥匙和房子的关系。

那么,既然这样,为啥上面同样是传递对象,传递的String对象和User对象的表现结果不一样呢?我们在pass方法中使用name = “hollischuang”;试着去更改name的值,阴差阳错的直接改变了name的引用的地址。因为这段代码,会new一个String,在把引用交给name,即等价于name =new String(“hollischuang”);。而原来的那个”Hollis”字符串还是由实参持有着的,所以,并没有修改到实际参数的值。

Quelle est la différence entre passer par valeur et passer par référence en Java

所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。

总结

无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递。其实Java中的参数传递严格意义上说应该是按共享传递。

Le passage par partage signifie que lorsqu'une fonction est appelée, une copie de l'adresse du paramètre réel est transmise à la fonction (si le paramètre réel est sur la pile, la valeur est copiée directement). Lorsque vous utilisez des paramètres dans une fonction, vous devez copier l'adresse pour trouver la valeur spécifique avant d'opérer. Si la valeur est sur la pile, comme il s'agit d'une copie directe de la valeur, les opérations sur les paramètres de la fonction n'affecteront pas les variables externes. Si la copie originale est l'adresse de la valeur d'origine dans le tas, vous devez alors trouver l'emplacement correspondant dans le tas en fonction de l'adresse avant d'effectuer l'opération. Étant donné qu'une copie de l'adresse est transmise, l'opération sur la valeur dans la fonction est visible par la variable externe.

Pour faire simple, le transfert en Java se fait par valeur, et cette valeur est en fait une référence à un objet.
Le passage par partage n'est en réalité qu'un cas particulier de passage par valeur. On peut donc dire que passer en Java, c'est passer par partage, ou que passer en Java, c'est passer par valeur.

Ainsi, les paramètres de fonctionnement à l'intérieur de la fonction n'affecteront pas les variables externes. Si la copie originale est l'adresse de la valeur d'origine dans le tas, vous devez alors trouver l'emplacement correspondant dans le tas en fonction de l'adresse avant d'effectuer l'opération. Étant donné qu'une copie de l'adresse est transmise, l'opération sur la valeur dans la fonction est visible par la variable externe.

Pour faire simple, le transfert en Java se fait par valeur, et cette valeur est en fait une référence à un objet.

Et le passage par partage n'est en fait qu'un cas particulier de passage par valeur. On peut donc dire que passer en Java, c'est passer par partage, ou que passer en Java, c'est passer par valeur.

Pour plus de connaissances liées à la programmation, veuillez visiter : Enseignement de la programmation ! !

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn