In depth analysis of method parameter passing in Java programming

  • 2020-04-01 04:15:57
  • OfStack

Before reading this article, according to their own experience and understanding, you can first think about and choose the Java function parameter transfer:
A. Is it passed by value?
B. by reference?
C. Part by value and part by reference?
Instead of announcing the correct answer, we'll let you find the answer with a simple example:
1. Define a type Value first


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 input parameter to modify the value 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 internal value of the object
  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:
This is a very common programming pattern: define | on the periphery to save | to get a value or object, pass the object as a parameter to a method, and modify the object's properties and behavior in the method. But the two methods newValue and modifyValue are not modified in the same way, after the method call, the object in the periphery looks very different! How to understand this difference? So the following concepts of passing by value and by reference:
* passing by value means that when an argument is passed to a function, the function receives a copy of the original value. Therefore, if the function modifies the parameter, only the copy is changed, and the original value remains the same.
* passing by reference means that when an argument is passed to a function, the function receives the memory address of the original value, not 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) changes as well.
The correct answer: A -- Java functions pass arguments by value!
Analyze the log:
* the first log output, value1 parameter is changed to point to the new object inside the newValue method, and the hashCode and value value of the new object are output, but after jumping out of the newValue method field, value1 in the main method does not change at all, which conforms to the definition and characteristics of passing by value; If passed by reference, value1 should change after calling the newValue(Value Value) method.
* the second log output shows that value2 performs setValue operation inside the modifyValue method, and the hashCode remains unchanged while the value is modified. After leaving the modifyValue method field, value2 does change in the main method. Anyone who has worked with C++ can easily interpret this as passing function arguments by reference! Because this is exactly like passing by reference in C++! But this is the place where the most mistakes are made!
The principle behind the difference between the two logs is that the Java language passes parameters by value and objects by reference. Objects manipulated in Java are actually references to manipulation objects, the object itself is stored in the "heap", while the object's "reference" is stored in a register or "stack".
The pseudo-code describes the difference between the newValue method and the modifyValue method:


newValue{ 
  Value_ref2 = value_ref1;  //Pass in a reference to 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;  //Point value_ref2 value_obj2
value_ref2 ->value_obj2.setValue( " xxx " ); //The value of value_obj2 is modified
printValueObj2();      //The value of obj2 is printed here
} 
modifyValue{ 
  Value_ref2 = value_ref1;  //Pass in a reference to 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();      //The value of obj1 is printed here
} 

That's clear enough! When value1_ref1 is passed in as an argument to a function, a copy of value1_ref2 is copied for the function field. The code in the newObject function [value = new value ();] points value1_ref1 to a new object, value_obj2; Set operations after this are all operations on the new object; The modifyValue function directly operates on value_obj1 through the set method, which is different from the newValue function.

Passing parameters by value
When calling a method, you must supply the arguments in the order specified in the argument 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);
}

The sample
The following example demonstrates the effect of passing by value.
This program creates a method that is used to exchange 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);
  }
  
  public static void swap(int n1, int n2) {
   System.out.println("tInside the swap method");
   System.out.println("ttBefore swapping n1 is " + n1
              + " n2 is " + n2);
   //Swap the values of n1 and n2
   int temp = n1;
   n1 = n2;
   n2 = temp;

   System.out.println("ttAfter swapping n1 is " + n1
              + " n2 is " + n2);
  }
}

The compilation and operation results of the above examples 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 1
After swap method, num1 is 1 and num2 is 2

Call the swap method by passing two arguments. Interestingly, the value of the argument does not change after the method is called.


Related articles: