preface
First of all, it is clear that method parameters in Java are passed by value. For basic types (int a, long b), values are passed when parameters are passed. For example, if int a = 5, 5 is passed. If it is a reference type, pass the address value pointing to the memory address of the specific object, such as system out. Println (New object()) printed out Java lang. Object@7716f4 7716f4 after the @ symbol in is the hexadecimal memory address, system out. Println actually calls the toString method of the object by default,
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
You can see that 7716f4 is output by hashCode(). If an object rewrites the hashCode method, the output may not be the initial memory address of the object. Therefore, if you want to accurately obtain the initial address of the object, it is recommended to call system identityHashCode().
It is worth mentioning that it is generally meaningless to obtain the memory address of an object in Java, because it may be changed by the JVM with actions such as garbage collection during program operation. However, in the following, we can see various situations of parameter passing according to whether the referenced object addresses are the same.
Examples
Basic types are passed as parameters
public class ValuePass { public static void main(String[] args) { //Example of value transfer int num = 10; System.out.println("Change previous value:" + num); modify(num); System.out.println("Changed value:" + num); } private static void modify(int num2) { num2 = 11; } }
The output result is
Change previous value:10 Changed value:10
This example shows that when the basic data type is passed as a parameter, a copy of the value is passed. No matter how the copy is changed, the original value will not change.
Object is passed as a parameter
Objects can be divided into ordinary objects, collection types and array types. Let's take a look at the effect in turn
Common object
public class ReferenceBasicPass { static class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int x) { val = x; } public void setVal(int val) { this.val = val; } public int getVal() { return val; } } public static void main(String[] args) { //Common object TreeNode node = new TreeNode(10); System.out.println("Argument node The memory address pointed to is:" + node.hashCode()); System.out.println("Change previous value:" + node.getVal()); modify(node); System.out.println("Changed value:" + node.getVal()); } private static void modify(TreeNode node) { System.out.println("Formal parameter node The memory address pointed to is:" + node.hashCode()); //It refers to the same block of address and operates on the same block of heap memory node.setVal(11); } }
Output results
Argument node The memory address pointed to is 366712642 Change previous value:10 Formal parameter node The memory address pointed to is 366712642 Changed value:11
This shows that when the reference object parameter is passed, the address pointing to the real object is passed, and when the formal parameter node in the function gets the same address, it passes through node SETVAL (11) will find the real object through the address for operation.
Collection object
Since ArrayList overrides the hashcode() method, system. XML is used here Identityhashcode gets the address value.
public class ReferencePass { public static void main(String[] args) { //Collection object List<TreeNode> nodes = new ArrayList<>(); nodes.add(new TreeNode(1)); nodes.add(new TreeNode(2)); System.out.println("Modify previous arguments node The memory address pointed to is:" + System.identityHashCode(nodes)); System.out.println("Modify previous arguments node The contents of the object stored at the address are:" + JsonUtils.toJson(nodes)); modify(nodes); System.out.println("Modified argument node The memory address pointed to is:" + System.identityHashCode(nodes)); System.out.println("Modified argument node The contents of the object stored at the address are:" + JsonUtils.toJson(nodes)); System.out.println("\n------------------------------------------------\n"); modify2(nodes); System.out.println("Modify the argument again node The memory address pointed to is:" + System.identityHashCode(nodes)); System.out.println("Modify the argument again nodes The contents of the object stored at the address are:" + JsonUtils.toJson(nodes)); } private static void modify(List<TreeNode> nodes) { //It refers to the same block of address and operates on the same block of heap memory nodes.add(new TreeNode(3)); } private static void modify2(List<TreeNode> nodes) { System.out.println("Formal parameter nodes Memory address to:" + nodes.hashCode()); //The formal parameter nodes points to the new memory address, which is operated on, but does not affect the real object of the memory address pointed to by the argument nodes = new ArrayList<>(); nodes.add(new TreeNode(5)); System.out.println("Formal parameter nodes New memory address to:" + nodes.hashCode()); System.out.println("Formal parameter nodes The contents of the object stored at the new address are:" + JsonUtils.toJson(nodes)); } }
The output result is
Modify previous arguments node The memory address pointed to is 366712642 Modify previous arguments node The contents of the object stored at the address are:[{"val":1},{"val":2}] Modified argument node The memory address pointed to is 366712642 Modified argument node The contents of the object stored at the address are:[{"val":1},{"val":2},{"val":3}] ------------------------------------------------ Formal parameter nodes Memory address pointed to: 1110478811 Formal parameter nodes New memory address pointed to: 1458540949 Formal parameter nodes The contents of the object stored at the new address are:[{"val":5}] Modify the argument again node The memory address pointed to is 366712642 Modify the argument again nodes The contents of the object stored at the address are:[{"val":1},{"val":2},{"val":3}]
For the collection, the reference address is also passed. After the reference address is copied through the formal parameter in the function, the real object is operated. As a result, the actual parameter has been modified when accessing the real object. If the parameter points to a new memory address, the modification will not affect the value of the original object.
Note: JsonUtils is implemented by Jackson.
array
Ordinary arrays, like collections, are reference types
public class ReferenceArrayPass { public static void main(String[] args) { //An ordinary array, like a collection, is a reference type, and an array is essentially a reference type int[] ints = new int[3]; ints[0] = 1; ints[1] = 2; System.out.println("Argument ints The memory address pointed to is:" + System.identityHashCode(ints)); System.out.println("Before modification ints Value with index 2" + ints[2]); modify(ints); System.out.println("After modification ints Value with index 2" + ints[2]); //The class of an ordinary array is [I, and I represents int type System.out.println(ints.getClass()); } private static void modify(int[] ints) { //It refers to the same block of address and operates on the same block of heap memory System.out.println("Formal parameter ints The memory address pointed to is:" + System.identityHashCode(ints)); ints[2] = 3; } }
output
Argument ints The memory address pointed to is 366712642 Before modification ints Value with index 2: 0 Formal parameter ints The memory address pointed to is 366712642 After modification ints Value with index 2: 3
The same is true for arrays and collections.
Packing type of basic type
It should be noted that for the basic type of packaging type, the parameter transfer also belongs to address value transfer;
public class ValuePass { public static void main(String[] args) { //Example of value transfer int num = 10; System.out.println("before modify result:" + num); modify(num); System.out.println("after modify result:" + num); Integer integer = 20; System.out.println("before modify result:" + integer); modify(num); System.out.println("after modify result:" + integer); } private static void modify(int num2) { num2 = 11; } private static void modify(Integer integer) { integer = 21; } }
The output result is
before modify result:10 after modify result:10 before modify result:20 after modify result:20
And because jdk1 5. For the above automatic boxing feature, Integer i = 20 is equivalent to executing Integer I = Integer Valueof (20), the valueOf() method will get an Integer object from the constant pool and return it according to the passed value if it is between - 128-127. If it is not within the range, it will return new Integer(20).
That is, the address of integer will change with the change of value, which is actually the assignment of reference type, pointing to the new memory address. For example, the example of integer = 21 above is equivalent to integer = integer Valueof (21), whether or not it has been created before 21, integer points to the new memory address, but does not affect the argument. The external is still 20