pass by value, pass by reference

​​​​​​Rumor rebuttal time

Misunderstanding 1: Passing by value and passing by reference, the condition for distinguishing is the content of the transfer, if it is a value, it is passed by value. If it's a reference, it's pass-by-reference.

Misunderstanding 2: Java is passed by reference.

Misunderstanding 3: If the passed parameter is a common type, it is passed by value, and if it is an object, it is passed by reference.

actual participation parameter

When defining a method in Java, parameters can be defined.

For example, the main method in Java public static void main(String[] args), where args is the parameter. Parameters are divided into formal parameters and actual parameters in the programming language.

Formal parameter: It is the parameter used when defining the function name and function body, and its purpose is to receive the parameters passed in when calling the function.

Actual parameters: When calling a function with parameters, there is a data transfer relationship between the calling function and the called function. When calling a function in the calling function, the parameters in parentheses after the function name are called "actual parameters".

Code example:

public static void main(String[] args) {
  ParamTest pt = new ParamTest();
  pt.sout("Hollis"); // 实际参数:Hollis
}

public void sout(String name) { // 形式参数:name
  System.out.println(name);
}

The actual parameter is the content that is actually passed when calling the parameterized method, and the formal parameter is the parameter used to receive the content of the actual parameter.


evaluation strategy

We say that when a method call is made, the actual parameters need to be passed to the formal parameters, so what exactly is passed in the process of passing?

This is actually the concept of evaluation strategies in programming .

In computer science, an evaluation strategy is a set of (usually deterministic) rules that determine the evaluation of expressions in a programming language. The evaluation strategy defines when and in what order the actual arguments given to the function are evaluated, when they are substituted into the function, and in what form the substitution takes place.

Evaluation strategies fall into two basic categories, based on how the actual arguments given to the function are handled, bitwise strict and nonstrict.

​​​​​​​​Strict evaluation

In "strict evaluation", during a function call, the actual arguments given to the function are always evaluated before the function is applied. Most existing programming languages ​​use strict evaluation for functions. So this article only focuses on strict evaluation.

There are three key evaluation strategies in strict evaluation that are of more concern——

Call by value, Call by reference, Call by sharing .

  • call by value (pass by value)
    • In a call by value, the actual parameter is first evaluated, and then its value is copied to the formal parameter of the called function. Because the formal parameter is only a "local copy", if the formal parameter value is changed in the called function, the actual parameter value will not be changed.
  • call by reference (pass by reference)
    • In a call by reference, what is passed to the function is an implicit reference to its actual parameter rather than a copy of the actual parameter. Because the reference is passed, if the value of the formal parameter is changed in the called function, the change is visible to the caller.
  • Pass shared object call (shared object transfer)
    • In calling by passing a shared object, first obtain the address of the actual parameter, then copy it, and pass the copy of the address to the formal parameter of the called function. Because the addresses of the parameters all point to the same object, we call it "passing shared objects". Therefore, if the value of the formal parameter is changed in the called function, the caller can see this change.

I don’t know if I found it. In fact, the process of passing a shared object call and passing a value call is almost the same, both of which are "evaluation", "copy", and "pass". You taste it again, and you taste it carefully.

However, the results of the shared object call and the internal reference call are the same. If the content of the parameter is changed in the called function, this change will also affect the caller. You taste it again, and you taste it carefully.

So, what is the relationship between shared object passing and value passing and reference passing?

For this problem, we should pay attention to the process, not the result, because the process of passing a shared object call is the same as the process of passing a value call, and there is a key operation, that is " copy ", so it is generally considered that the shared object Object call is a special case of call by value.

Let’s put the shared object call aside first, and then review the main differences between call by value and call by reference:

Call by value: When calling a function, 复制a copy of the actual parameter is passed to the function.

Call by reference: When calling a function, a reference to the actual parameter is 直接passed into the function.

​​​​​​So , the main difference between the two is whether it is passed directly or a copy is passed.

Here is a vivid example. Let's take a deeper look at call by value and call by reference:

You have a key, and when your friend wants to come to your house, if you 直接give him your key , this is pass-by-reference . In this case, if he does something to the key, such as engraving his name on the key, when the key is returned to you, your own key will also have his engraved name on it.

You have a key. When your friend wants to go to your house, you give him 复刻a new key , and your own is still in your hand. This is value transfer . In this case, nothing he does to the key will affect the key in your hand.


Why is there only passing by value in Java?

Java's evaluation strategy

The special case of call by value, call by reference, and call by value and call by shared object has been introduced earlier. So, which evaluation strategy is used in Java?

Many people say that the basic data types in Java are passed by value. There is basically nothing to discuss about this, and they generally think so.

But many people mistakenly believe that object passing in Java is passing by reference. The reason for this misunderstanding is mainly because there is a reference relationship between variables and objects in Java. In the Java language, objects are manipulated through object references. Therefore, many people think that the passing of objects is the passing of references.

And many people also cited the following code examples:

public static void main(String[] args) {
  Test pt = new Test();

  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);
}

Output result:

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

It can be seen that after the object type is passed to the pass method, its content is changed within the method, and finally the object in the main method of the caller also changes.

So many people say that this is the same as the phenomenon of passing by reference, that is, changing the value of the parameter in the method will affect the caller.

However, this is actually a misunderstanding.

Object passing in Java

Many people use the phenomenon of code examples to explain that Java objects are passed by reference, so let's start with the phenomenon and first refute this point of view.

As mentioned earlier, whether it is passing by value or passing by reference, it is just a kind of evaluation strategy, and there are many other evaluation strategies, such as the phenomenon of shared object passing mentioned above and passing by reference. Then why do you say that parameter passing in Java must be passed by reference instead of shared object?


So, what is the form of object passing in Java? In fact, it is shared object transfer.

In "The Java™ Tutorials", there are instructions for this part of the content.

1. First, the basic types are described as follows:

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.

That is, the original parameter is passed to the method by value. This means that any changes to parameter values ​​only exist within the scope of the method. When the method returns, the parameters disappear and any changes to them are lost.

2. The description of object transfer is as follows:

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object’s fields can be changed in the method, if they have the proper access level.

That is, reference data type parameters such as objects are also passed to methods by value. This means that when the method returns, the reference passed in still refers to the same object as before. However, object fields can change their values ​​within a method if they have the appropriate access level.


The official documentation on this point has clearly pointed out that Java is passing by value, but passing the reference of the object as a value to the method. Take a closer look, isn't this the transfer of shared objects?

In fact, the evaluation strategy used in Java is to pass the shared object call, that is to say, Java will pass a copy of the address of the object to the formal parameter of the called function. It's just that the word "pass shared object call" is not commonly used, so people in the Java community usually say "Java is call by value", which is correct, because call by shared object is actually a special case of call by value.


Does the phenomenon of value passing and shared object passing conflict?

Seeing this, there may be a question, since shared object transfer is a special case of value transfer, why is the phenomenon completely different?

Is it possible that during the value transfer process, if the value is changed in the called method, may it also affect the caller? So when will it be affected and when will it not be affected?

In fact, there is no conflict. The reason for this confusion is that everyone has misunderstood what a "change value" is.

Let's go back to the above example and see what actually happens during the call?

During parameter passing, the address of the actual parameter 0X1213456is copied to the formal parameter. This process is actually value passing, but the value passed is the application of the object.

Then why did changing the value of the attribute in the user affect the original user?

In fact, this process is like: you copied a key of your house to your friend, and after he got the key, he did not make any changes to the key, but opened the room of your house through the key. Open the door, enter the house, and smash your TV.

This process has no effect on the key in your hand, but the contents of the house corresponding to your key have been changed.

That is to say, the transfer of Java objects is to pass the reference relationship by copying. If we do not change the reference relationship, but find the reference address and change the content inside, it will have an impact on the caller. Because everyone points to the same shared object.

So, if we change the content of the pass method:

public void pass(User user) {
  user = new User();
  user.setName("hollischuang");
  user.setGender("Male");
  System.out.println("print in pass , user is " + user);
}

In the above code, in the pass method, a new user object is recreated, and its value is changed. The output is as follows:

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

Let's take a look at what happened in the whole process:

This process is like you copied a key to your friend. After your friend got the key you gave him, he found a locksmith to modify the key. The key to the home lock. At this time, if he opened his house, even if he ordered the house, it would have no effect on the keys in your hand or your house.

Therefore, if the object transfer in Java is to modify the reference, it will not have any impact on the original object, but if you directly modify the value of the property of the shared object, it will have an impact on the original object.


Summarize

We know that programming languages ​​need to pass parameters between methods, and this passing strategy is called an evaluation strategy.

In programming, there are many evaluation strategies, the more common ones are passing by value and passing by reference. There is also a special case of value transfer - shared object transfer.

The biggest difference between passing by value and passing by reference is whether a copy is copied during the passing process. If a copy is passed, it is passed by value, otherwise it is passed by reference.

In Java, it is actually parameter passing through value passing, but for the passing of Java objects, the content passed is a reference to the object.

It can be concluded that the evaluation strategy in Java is shared object passing, which is completely correct.

However, in order for everyone to understand, it is said that there is only value transfer in Java, but the content passed is a reference to the object.

However, one should never assume that there is pass-by-reference in Java.

Guess you like

Origin blog.csdn.net/wangshiqi666/article/details/130706808