Part 7 of the interview question series: Is a Java method passed by value or by reference?

"Java Interview Question Series": A long knowledge and very interesting column. In-depth digging, analyzing the source code, summarizing the principles, combining pictures and texts, creating a series of articles on the official account, and raising the level for interviews or not. Welcome to continue to pay attention to [Program New Vision]. This is the seventh chapter.

Key point: Is a Java method passed by value or by reference?

This issue has been debated in the technical discussion forum. It is very confusing for junior staff, even for many advanced developers. This article will take you to explore the underlying principles, and finally simplify the complexity, so that you can understand whether it is passed by value or passed by reference in a sentence or two.

Interview questions

For common interview questions, execute the following code to view the corresponding printed results:

@Test
public void test1() {
	String[] arr = {"关注", "程序", "新视界"};
	String name = "二师兄";
	System.out.println("before change : arr=" + Arrays.toString(arr));
	System.out.println("before change : name=" + name);
	change(arr, name);

	System.out.println("after change : arr=" + Arrays.toString(arr));
	System.out.println("after change : name=" + name);
}

public void change(String[] arr, String name) {
	arr[0] = "公众号";
	name = new String("Steven");

	System.out.println("in change method : arr=" + Arrays.toString(arr));
	System.out.println("in change method : name=" + name);
}

First think about the differences in the results printed in the three places, and then compare the results after executing the program:

before change : arr=[关注, 程序, 新视界]
before change : name=二师兄
in change method : arr=[公众号, 程序, 新视界]
in change method : name=Steven
after change : arr=[公众号, 程序, 新视界]
after change : name=二师兄

Is there a question, why the name is modified in the change method, but the final result is not modified? And arr modified the content of the 0th position but successfully modified it? Is the first parameter passed by reference and the second parameter passed by value?

Let's solve the above questions one by one and summarize the final conclusion.

Pass by value and pass by reference

First, let's understand the concepts of value passing and reference passing:

Pass by value means that when the function is called, the actual parameters are copied and passed to the function, and the parameters are modified in the function without affecting the actual parameters.

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

Through the concept, we can draw the essential difference between value passing and reference passing: whether the value of the actual parameter is copied or used directly.

Basic type and String transfer process

There is often a misunderstanding on this issue: the difference between value transfer and reference transfer is the content of the transfer, if it is a value, it is value transfer. If it is a reference, it is passed by reference.

Note that the above understanding is wrong. The manifestations of value passing and reference passing seem to be related to the object type, but are essentially irrelevant.

Let's first look at the basic types and the form of String types that usually exist in memory. More forms of presentation have been mentioned many times in the previous articles of this series.
Insert picture description here

To sum up, the reference and value of the basic type in the method are allocated on the stack, the String type reference is on the stack, and the value is on the heap (heap or string constant pool).

Let's first look at the memory structure of the basic type (take int as an example) when passed as a parameter to the method:

@Test
public void test2(){
	int a = 10;
	change(a);
}

public void change(int b) {
	b = 2;
}

First, when the method is not called, the memory distribution of variable a is as shown in the figure above. When the change method is called, the variables a and b of type int are in the memory as follows:

image

Obviously, for the formal parameter b of the method, a copy of the data of a is reproduced on the stack. At this point, re-assign b, the memory will change as follows:

image

And we know that the contents of the stack disappear as the execution of the (change) method is completed. In other words, the change method just copied the value of a during the entire process, and the operation of the variable b in the method did not affect the original value of a.

Compared with the above concepts, it is easy to find that this process is value transfer. Let's take a look at the memory structure changes for String objects.

@Test
public void test3(){
	String name = "Tom";
	change(name);
}

public void change(String str) {
	str = new String("Steven");
}

At first the memory structure is the same as in the first picture, the name is stored in the stack, and the value Tom is stored in the string constant pool. When the change method is called, the memory structure is as follows:
Insert picture description here

When calling the method, the formal parameter str of the change method copies the reference address stored in the variable name, and also points to the string "Tom".

When executing to the str assignment in the method, the memory structure is as follows:
image

At this point, you can see that the assignment operation performed in the method only changes the address of the string stored in the str variable, and does not affect the string pointed to by the original name variable.

The above is about the modification of the basic type and the String class meet the requirements of value transfer: copy the actual parameter, and modify the copied parameter value without affecting the original value. Only the actual value copied for the String type is the reference address stored in the variable.

A friend said: No, I pass in an object, and then call its set method to modify the content of the object!

So, let's take a look at the memory structure diagram of the reference type.

Reference type value passing

We all know that arrays are also reference types, but in order to be more clear, we create a new User object here for verification.

@Test
public void test4() {
	User user = new User();
	user.setName("Tom");
	change(user);
}

public void change(User paramUser) {
	paramUser.setName("Steven");
}

class User{

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Before executing the change method, the memory structure diagram is as follows:

image

After executing the set method in the change method, the memory structure becomes as follows:
Insert picture description here

It can be seen that the paramUser parameter also copies the address in the user parameter, so it also points to the User object in the heap. So, some friends said that the User object was indeed changed!

It should be noted that what we are concerned about is not whether the internal structure of the object has been changed, but whether the value of the copied original user parameter has been changed. It can be clearly seen from the above figure that the value (reference address) in the original user has not changed in any way.

Will assigning a new object directly to paramUser change the value of the original user variable? For further verification, let's modify the content in the change method:

@Test
public void test4() {
	User user = new User();
	user.setName("Tom");
	change(user);
}

public void change(User paramUser) {
	paramUser = new User();
	paramUser.setName("Steven");
}

Before the change method is executed, the memory structure is the same as the above structure, but after the execution, the memory structure has undergone new changes.
Insert picture description here

If it is passed by reference, then reassigning paramUser will definitely change the value corresponding to the original user. But here it is obvious that after the assignment, paramUser only points to a new object in the heap, and does not affect the original user value.

summary

Through the above step-by-step analysis and demonstration, we can clearly see: if it is a basic type, then the reference and value of the basic type (in the stack) are copied when the method is passed, and if it is a reference type, the copy is (In the stack) Reference address.

That is to say, no matter what type is passed, a copy operation is eventually performed, rather than a reference transfer that directly transfers the actual value. Therefore, in Java, there is essentially only value passing, which means that Java's parameter passing will only pass a copy of it, not the parameter itself.

Finally, through the above analysis process, do you find that after understanding the memory structure of the JVM, many puzzling problems can be easily solved? So, hurry up and learn more.

Original link: " Interview Question Series No. 7: Is a Java method passed by value or by reference?


New Vision of Procedure

The public account " New Vision of Program ", a platform that allows you to simultaneously improve your soft power and hard technology, providing massive amounts of data

WeChat Official Account: New Vision of Program

Guess you like

Origin blog.csdn.net/wo541075754/article/details/108440877