Why is there only value passing in Java?

For beginners, it is difficult to answer this question correctly. When sorting out the answers the next day, I found that I couldn't describe the matter in simple language. Unfortunately, I didn't find any article on the Internet that could explain the matter easily. Therefore, I have the original intention of writing this article. In this article, I will start with what are the actual parameters and formal parameters of methods, and explain why it is said that there is only value passing in Java.

Rumor refutation time has also triggered extensive discussion on stackoverflow. It seems that many programmers have different understanding of this problem, and even many people understand it wrong. Others may know that parameter passing in Java is value passing, but they can't say why.

Before we begin our in-depth explanation, it is necessary to correct our previous wrong views. If you have the following ideas, you need to read this article.

Misunderstanding 1: value transfer and reference transfer are distinguished by the content of the transfer. If it is a value, it is value transfer. If it is a reference, it is reference passing.

Error understanding 2: Java is reference passing.

Error understanding 3: if the passed parameter is a common type, it is value passing. If it is an object, it is reference passing.

As we all know, parameters can be defined when defining methods in Java. For example, the main method in Java:

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

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

For 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 real content passed when calling the parameterized method, while the formal parameter is the parameter used to receive the actual parameter content.

As mentioned above, when we call a function with parameters, we will pass the actual parameters to the formal parameters. However, in a programming language, there are two cases of transmission in this transmission process, namely value transmission and reference transmission. Let's look at how value passing and reference passing are defined and distinguished in a programming language.

Pass by value refers to copying and passing a copy of the actual parameters to the function when calling the function, so that if the parameters are modified in the function, the actual parameters will not be affected.

Pass by reference refers to directly passing the address of the actual parameter to the function when calling the function. The modification of the parameter in the function will affect the actual parameter.

With the above concepts, you can write code to practice. Let's see whether Java is value transfer or reference transfer. Therefore, the simplest piece of code comes out:

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

In the above code, we modify the value of the parameter J in the pass method, and then print the value of the parameter in the pass method and the main method respectively. The output results are as follows

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

It can be seen that the modification of the value of name in the pass method does not change the value of the actual parameter I. Then, according to the above definition, someone comes to the conclusion that Java method passing is value passing.

However, it was soon questioned (haha, so don't jump to conclusions.) then, they will move out the following code:

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

It is also a pass method, which modifies the value of the parameter in the pass method. The output results are as follows:

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

After the pass method is executed, the value of the actual parameter is changed. According to the definition of reference passing above, the value of the actual parameter is changed. This is reference passing. Therefore, according to the above two pieces of code, someone comes to a new conclusion: in Java methods, when passing ordinary types, it is value passing, and when passing object types, it is reference passing.

However, this statement is still wrong. If you don't believe it, the following parameter types are passed as object parameters:

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

The output of the above code is

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

How can this be explained? Similarly, an object is passed, but the value of the original parameter has not been modified. Does the passing object become value passing again?

Above, we give three examples of value transfer in Java, but the results are different. This is also the reason why many beginners and even many advanced programmers are confused about the transfer type of Java.

In fact, what I want to tell you is that the above concept is not wrong, but there is a problem with the code example. Here, let me draw the key points of the concept, and then give some really appropriate examples.

Pass by value refers to copying and passing a copy of the actual parameters to the function when calling the function, so that if the parameters are modified in the function, the actual parameters will not be affected.

Pass by reference refers to directly passing the address of the actual parameter to the function when calling the function. The modification of the parameter in the function will affect the actual parameter.

So, let me summarize the difference between value passing and reference passing.

Why is the experimental method wrong? Here we give an example of image. Take a closer look at value passing and reference passing, and you'll know why you're wrong.

You have a key. When your friend wants to go to your house, if you give him your key directly, this is citation transmission. In this case, if he does something to the key, for example, he engraves his name on the key, when the key is returned to you, his engraved name will be added to your own key.

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

But no matter what happens above, your friend takes the key you gave him, enters your home and smashes your TV. Do you think you will be affected? In the pass method, when we change the value of the name attribute of the user object, we are "smashing the TV". What you change is not the key, but the house opened by the key.

Take the above example. Let's really change the parameters to see what happens?

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

In the above code, we changed the user object in the pass method, and the output results are as follows:

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

Let's draw a diagram to see what happened in the whole process, and then I'll tell you why there is only value passing in Java.

Explain this figure a little. When we create a user object in main, we open up a piece of memory in the heap, which holds data such as name and gender. Hollis then holds the memory address 0x123456 (Figure 1).

When you try to call the pass method and Hollis is passed as an actual parameter to the formal parameter user, you will give the address 0x123456 to the user. At this time, the user also points to this address (Figure 2).

Then, when modifying parameters in the pass method, that is, user = new user();, A memory of 0x456789 will be reopened and assigned to user. Any subsequent changes to the user will not change the contents of memory 0x123456 (Figure 3).

What is the above transmission? It must not be passed by reference. If it is passed by reference, execute user = new user(); The reference of the actual parameter should also be changed to point to 0x456789, but it doesn't.

We can also know from the concept that the reference address of the actual parameter is copied and passed to the formal parameter. Therefore, the above parameter is actually value passing, and the address referenced by the argument object is passed to the formal parameter as a value.

Let's review the previous example of "smashing TV" and see what happened in the transmission process in that example.

Similarly, in the process of parameter transfer, the address 0x1213456 of the actual parameter is copied to the formal parameter. However, in this method, the formal parameter itself is not modified, but the content stored in the address held by the modified formal parameter.

Therefore, the difference between value passing and reference passing is not the content of passing. But whether the argument has been copied to the formal parameter. When judging whether the actual parameter content is affected, it depends on what is passed. If you pass an address, it depends on whether the change of the address will be affected, rather than the change of the object pointed to by the address. It's like the relationship between the key and the house.

So, in this case, why is the above also the passing object, and the performance results of the passed string object and the user object are different? We use name = "hollischuang" in the pass method; Try to change the value of name. By mistake, you directly change the address referenced by name. Because this code will create a new string and give the reference to name, which is equivalent to:

name = new String("hollischuang");

The original "Hollis" string is still held by the argument, so it is not modified to the value of the actual parameter.

Therefore, Java is actually value passing, but for object parameters, the content of the value is the reference of the object.

Summary whether value passing or reference passing is actually an evaluation strategy. Another evaluation strategy is called call by sharing. In fact, parameter passing in Java should strictly be shared.

Pass by share means that when a function is called, A copy of the address of the argument is passed to the function (if the argument is in the stack, copy the value directly). When operating on the parameter inside the function, you need to find the specific value from the copied address before operating. If the value is in the stack, because it is a directly copied value, the operation on the parameter inside the function will not affect the external variables. If the original copy is the address of the original value in the heap, Then you need to find the corresponding location in the heap according to the address before operation. Because a copy of the address is passed, the operation on the value in the function is visible to the external variable.

Simply put, the transfer in Java is a value transfer, and this value is actually a reference to an object.

Passing by share is just a special case of passing by value. So we can say that the transfer in Java is shared transfer, or the transfer in Java is value transfer.

This is the official account Hollis-----------------------------------------

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>