Before reading this article, based on your own experience and understanding, you can first think about and choose the parameter passing method of Java functions:
A. Is it passed by value?
B. Passed by reference?
C. Partly by value and partly by reference?
The correct answer will not be announced here yet. We will let you find the answer by yourself through a simple example:
1. First define a type Value
public static class Value { private String value = "value"; public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
2. Write two functions newValue and modifyValue: newValue will point the input parameter to a new object, and modifyValue will call the setValue method of the input parameter to modify the value of the object.
public static void newValue(Value value) { value = new Value(); value.setValue("new value"); System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); } public static void modifyValue(Value value) { value.setValue("new value"); System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); }
3. Simple test code
public static void main(String[] args) { Value value1 = new Value(); System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() ); // Point value1 to the new Value object newValue(value1); System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "/n"); Value value2 = new Value(); System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); // Use the set method of object to modify the object's internal value modifyValue(value2); System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); }
4. Execution result log:
Before modify, HashCode = 12677476, value = value In newValue, HashCode = 33263331, value = new value After modify, HashCode = 12677476, value = value Before modify, HashCode = 6413875, value = value In modifyValue, HashCode = 6413875, value = new value After modify, HashCode = 6413875, value = new value
5. Result analysis:
The above code is a very common programming pattern: define | save | get a value or object in the periphery, pass the object as a parameter to a method, and modify the properties and behavior of the object in the method. However, the modification methods of the two methods newValue and modifyValue are different. After the method is called, the object looks very different from the outside! How to understand this difference? Let’s first review the concepts of pass by value and pass by reference:
* Passing by value means that when you pass an argument to a function, the function receives a copy of the original value. Therefore, if the function modifies the parameter, only the copy is changed, while the original value remains unchanged.
* Passing by reference means that when an argument is passed to a function, the function receives the memory address of the original value rather than a copy of the value. Therefore, if the function modifies the parameter, the original value of the parameter (in the calling code outside the function block) also changes.
Correct answer: A - Java functions pass parameters by value!
Analyze the log:
* In the first section of log output, the value1 parameter is changed to point to a new object inside the newValue method, and the hashCode and value of the new object are output. However, after jumping out of the newValue method domain, no change occurs to value1 in the main method. This It complies with the definition and characteristics of passing by value; if it is passed by reference, value1 should change after calling the newValue(Value value) method.
* The second log output shows that value2 performs a setValue operation inside the modifyValue method. The hashCode remains unchanged but the value is modified. After leaving the modifyValue method domain, value2 does change in the main method. People who have used C++ can easily understand this phenomenon as: passing function parameters by reference! Because this is very similar to pass by reference in C++! But this is exactly where it is most likely to fall into misunderstandings!
The hidden principle behind the different phenomena of the two logs is that the Java language passes parameters by value and objects by reference; the objects operated in Java are actually references to the operating objects, and the objects themselves are stored in the "heap" , and the "reference" of the object is stored in a register or "stack".
Pseudocode describes the difference between the newValue method and the modifyValue method:
newValue{ Value_ref2 = value_ref1; // Pass in the reference value_ref1 by value and get a copy of value_ref1 value_obj2 = new Value(); // value_obj2 is created and initialized in the "heap" value_ref2 -> value_obj2; // value_ref2 points to value_obj2 value_ref2 - >value_obj2.setValue(“xxx”); // value_obj2 The value is modified printValueObj2(); // What is printed here is the value of obj2} modifyValue{ Value_ref2 = value_ref1; // Pass in the reference value_ref1 by value and get a copy of value_ref1 value_ref2 ->value_obj1.setValue("xxx"); // The value of value_obj1 is modified printValueObj1(); // What is printed here is the value of obj1}
That's clear enough! When value1_ref1 is passed into the function as a parameter, a copy of value1_ref2 is first copied for use in the function domain. At this time, both refs point to the same value_obj; code in the newObject function [value = new Value(); ] In fact, value1_ref1 points to a new object value_obj2; the set operations after this are all operations on the new object; the modifyValue function directly operates value_obj1 through the set method, which is different from the newValue function.
Pass parameters by value
When calling a method, you need to provide parameters, and you must provide them in the order specified in the parameter list.
For example, the following method prints a message n times in a row:
public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) System.out.println(message);}
Example The following example demonstrates the effect of passing by value.
This program creates a method that exchanges two variables.
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; System.out.println("Before swap method, num1 is " + num1 + " and num2 is " + num2) ; // Call the swap method swap(num1, num2); System.out.println("After swap method, num1 is " + num1 + " and num2 is " + num2); } /** Method to swap two variables*/ public static void swap(int n1, int n2) { System.out.println("/tInside the swap method"); System.out.println("/t/tBefore swapping n1 is " + n1 + " n2 is " + n2); // Swap the values of n1 and n2 int temp = n1; n1 = n2; n2 = temp; System.out.println("/t/tAfter swapping n1 is " + n1 + " n2 is " + n2); }}
The compilation and running results of the above example are as follows:
Before swap method, num1 is 1 and num2 is 2 Inside the swap method Before swapping n1 is 1 n2 is 2 After swapping n1 is 2 n2 is 1After swap method, num1 is 1 and num2 is 2
Call the swap method passing two parameters. Interestingly, the values of the actual parameters do not change after the method is called.