Java transfer mechanism: value transfer or reference transfer? (Detailed graphic version)

Preface

Understanding the transfer mechanism in Java helps us better understand the address pointing to Java in memory. I will explain this article as simple as possible to let everyone better understand.


1. Delivery type

First of all, we need to know that the transfer type refers to the way the parameters passed in when calling the function . There are two types of transfer : value transfer and reference transfer

Value transfer : we pass in the actual parameter copy a copy of the formal parameter passed to the function, operating the formal parameter in the function does not change the value of the actual parameter

Pass by reference: Pass the reference address of the actual parameter to the method

For languages ​​such as C++, there are both value passing and reference passing
. The implementation of value passing: int func(int a, int b);
and the implementation of passing by reference is realized by pointer or reference , for example: int func(int *a, int &b);

For Java, there is only value passing, no reference passing


2. Value passing mechanism in Java

In order to let everyone better understand, I will show it through a lot of drawings. Insert picture description here
Here I found a JVM memory structure diagram from the Internet, you can see that the Java program is divided into various areas in the memory. In order to help everyone understand, the Java value transfer mechanism to be discussed here mainly focuses on the two most common areas of the stack area and the heap area, and ignores the details inside.

First of all, we need to know that there are two types of variables in Java: basic types and reference types . Next, I use a few examples to help you better understand the Java value transfer mechanism.

First example

public class Main01 {
    
    
	
	public static void main(String[] args) {
    
    
		int a = 10, b = 20;
		exchange(a, b);
		System.out.println("a = " + a + ", b = " + b);
	}
	
	public static void exchange(int a, int b) {
    
    
		int tmp = a;
		a = b;
		b = tmp;
	}
}

First look at an example of a basic type, look at this code, and guess what the result is?

a = 10, b = 20

It should not be difficult to understand, because Java uses a value transfer mechanism, and what is passed in is a copy of the actual parameter. Changing the value of the formal parameter in the function will not affect the original value. Next, understand it through memory.

The stack area in Java is composed of stack frames, one stack frame corresponds to one method, and the start and end of the method correspond to the stacking and popping process. When the program is executed, the stack frame composed of the main method main() is first pushed onto the stack. During the execution of the main method, the execution of the method is corresponding to the stack, the end of the method is encountered, and the stack is popped. When the execution of the main method ends, the program ends.

First example

The above code looks like this by drawing a picture, first open up the stack frame corresponding to the main method main(). Then push the stack frame corresponding to the exchange() method, pop out of the stack after the exchange() method ends, and finally the end of the main method main() means the end of the program. It can be seen that changing the formal parameters a'and b'in the exchange() method does not affect the values ​​of the actual parameters a and b in the main method main().

We then look down and analyze a piece of code about reference types

Second example

public class Main01 {
    
    
	
	public static void main(String[] args) {
    
    
		Student s1 = new Student("张三");
		Student s2 = new Student("李四");
		exchange(s1, s2);
		System.out.println(s1);
		System.out.println(s2);
	}
	
	public static void exchange(Student s1, Student s2) {
    
    
		Student tmp = s1;
		s1 = s2;
		s2 = tmp;
	}
}

class Student {
    
    
	
	public Student(String name) {
    
    
		this.name = name;
	}
	
	public String name;
	
	@Override
	public String toString() {
    
    
		return "Student [name=" + name + "]";
	}
	
}

What is the result this time?

Student [name=张三]
Student [name=李四]

As you can see, the name values ​​of s1 and s2 have not changed

Why is this? The reference type passes in the address, which is exchanged in the exchange() method. Why are the points of s1 and s2 in the main method main() not exchanged?

After reading this example, if you already have an answer to this question, that would be great. You must have a certain understanding of Java value passing? If there are still doubts, then follow me to continue the analysis!

When analyzing, we need to bring a question, is there any difference between basic types and reference types by value passing?

We also use the memory graph to analyze

Second example
You just have to remember one thing, a copy of the actual parameters passed by Java value transfer. In this example, the exchange() function also carries a copy of s1 and s2, but this time, they point to The same memory space in the heap area.

When the exchange() function is executed, the memory address points of the formal parameters s1' and s2' are exchanged. For the actual parameters s1 and s2, the pointers have not changed.

After reading the previous two examples, you seem to think that both basic types and reference types are passed by value. Passing is a copy and cannot really change the original value?

But is this really the case?

Next we look at the last example of reference types, maybe it can help you really understand Java's value passing

The third example

public class Main01 {
    
    
	
	public static void main(String[] args) {
    
    
		Student s1 = new Student();
		Student s2 = new Student();
		s1.name = "张三";
		s2.name = "李四";
		exchange(s1, s2);
		System.out.println(s1);
		System.out.println(s2);
	}
	
	public static void exchange(Student s1, Student s2) {
    
    
		Student tmp = new Student();
		tmp.name = "张三";
		s1.name = s2.name;
		s2.name = tmp.name;
	}
}

class Student {
    
    
	
	public String name;
	
	@Override
	public String toString() {
    
    
		return "Student [name=" + name + "]";
	}
	
}

Analyze this code carefully, what is your result?

Do you think s1.name is still "Zhang San" and s2.name is still "Li Si"?

Let's look at the result

Student [name=李四]
Student [name=张三]

Eh? Why is it different from what you think? Doesn't it mean that the reference type is passed, even if it is a copy of the address, changing the point of the formal parameter address cannot change the point of the actual parameter?

Correct! This is indeed the case, value transfer, changing the address of the formal parameter does not affect the address of the actual parameter, but the third example changes the value of the address space.

Haha, are you stupefied by me?

Let us then draw a memory graph for analysis

Before executing exchange():
Insert picture description here
At this time, only the stack frame corresponding to the main method main()

Then execute the exchange() method, and the stack frame corresponding to exchange() is pushed onto the stack

First, create a new Student object tmp, let its name = "Zhang San"

Then, the formal parameters s1' and s2' are exchanged to point to the name value of the object in the heap memory space

So it becomes the following

Insert picture description here
Seeing this, do you understand? Note the difference between the third example and the second example.

The second example is to change the direction of the formal parameters s1' and s2', but does not change the direction of the actual parameters s1 and s2, so the actual parameters have not changed.

The third example does not change the pointers of the actual parameters s1 and s2, and the memory space pointed to by the heap area has not changed, but we changed the name value of the corresponding heap area object, so the output has changed. In essence, changing the value of a formal parameter does not change the direction of the formal parameter, which is called value transfer.

Through the above three examples, do you have a deep understanding of Java value transfer mechanism?

ps. I am a second-year dog, with limited ability, and the big guy is squirting, if there is any part that I don’t understand, please leave a message in the comment area!

Guess you like

Origin blog.csdn.net/qq_45590494/article/details/105978255