In Java you only pass by value

“Only pass by value in Java”, as a beginner to see this word a little bit can not believe, countless times through the function to change the object, countless times told colleagues that Java is passed by reference when the object. Later, when I think about it, I think that Java objects are passed by reference because there are many concepts that are confused with C++. When converting from C++ to Java, the knowledge points in C++ are mapped to Java, which is conducive to the faster learning of Java. But once the mapping is wrong, it is easy to form fixed thinking.

There are references in both C++ and Java, but they are not the same thing at all. References in Java are more like Pointers in C++, and C++ references have no equivalent in Java. In C++, there are three kinds of passing by value, passing by pointer and passing by reference, while in Java, there is no C++ reference and pointer concepts, only passing by value.

Java data types are divided into basic data types and reference types, among which:

  • Basic types include byte/short/int/long/float/double/char/Boolean eight, namely in memory address in the basic types of itself value, it is generally allocated on the stack.

  • A reference type refers to an object, much like a C++ pointer. But C++ Pointers can point to primitive types and class objects, whereas Java references can only point to class (enumerations, interfaces, and so on) objects. In Java, objects themselves are allocated on the heap, whereas reference types are allocated on the stack, and their memory addresses hold the addresses of objects in the heap. The layout of the two types in memory is as follows:

 1 class MyInteger {
 2     int value;
 3 }
 4 
 5 public class TestReference {
 6 
 7     public static void changeBasic(int arg) {
 8         arg = 2;
 9     }
10 
11     public static void changeReference(MyInteger arg) {
12         arg.value = 2;
13     }
14 
15     public static void main(String[] args) {
16 
17         int basicTypeA = 1;
18 
19         MyInteger referenceTypeA = new MyInteger();
20         referenceTypeA.value = 1;
21 
22         System.out.println("Value of basicTypeA before calling changeBasic"+ basicTypeA);
23         changeBasic( basicTypeA);
24         System.out.println("Value of basicTypeA after calling changeBasic"+ basicTypeA);
25 
26         System.out.println("ReferenceTypeA value before calling changeReference"+ referenceTypeA.value);
27         changeReference( referenceTypeA);
28         System.out.println("ReferenceTypeA value after calling changeReference"+ referenceTypeA.value);
29     }
30 }
Copy the code

The running results are as follows:

In fact, the meaning of passing by value must be known: What is passed is a copy of the value. For example, when changeBasic(basicTypeA) is called in the above code, arG is a copy of basicTypeA, so anything done to the ARG does not affect the basicTypeA variable itself. While calling changeReference(referenceTypeA), arG is also a copy of referenceTypeA, but since arG and referenceTypeA are both reference types and they refer to the same object, So by modifying objects through arG, referenceTypeA can also be seen. The two types of variables are called in memory as follows:

So you can see that both primitive and reference types are passed by value. Just because they represent different things in memory, the final result is different. Similarly, passing by value, passing by pointer, and passing by reference in C++ can all theoretically be referred to as passing by value.

A pit for passing “references” by value

Java references are similar to C++ Pointers, but C++ object (excluding basic types) pass provides the object itself directly pass and pointer pass two ways (not to mention the reference mode), and Java objects only pass the reference this one, there is no direct object itself pass.

  • The advantage of passing objects is that you are passing a copy of the object, and any changes you make to the copied object in a function will not change the original object. However, if the passed object is very large and called frequently, performance can be affected.
  • The advantage of passing a reference (or pointer) to an object is that only one reference (or pointer) size of the data needs to be copied, and the original object contents can be changed in the function being called. The disadvantage is that it is easy to dig holes.

Sometimes we don’t want to change the contents of the original object in a function. Here I have a pit where an object is passed through a pipe in our project as follows:

FuncA and funcB are in charge of two different people. After one upgrade, the person in charge of funcB found that the object X obtained in the function was wrong. At first, he thought that there was an error in the interface of transferring object X, which was a huge check. It took a lot of time to realize that object X had been modified in funcA after the upgrade. Of course, the unreasonable flow design of this architecture is the main reason (we only need to manually copy object X at the time of distribution to avoid the above problems), but it does not affect us to throw out the drawback that Java can only pass references.

It’s easy to make this mistake in long call chains and various for/while loops. The solution, of course, is to copy objects manually. There are two ways to copy objects in Java:

  • Implement Cloneable interface and override clone() method in Object class.
  • Implement Serializable interface, through object serialization and deserialization to achieve cloning, you can achieve true deep cloning.

The second method avoids the shallow copy problem, but the call is time-consuming. The first method also avoids deep and shallow copying but requires you to write the corresponding code manually. If the nesting is deep, the code will be very complex. As for the depth of the copy problem can be baidu, its essence is just because the object reference was passed and caused by some problems. Remember to pay attention to the public account oh, recording a C++ programmer to Java learning road.