preface
I have been writing PHP for the past two months. I feel that I haven't written java code for a long time, because I recently want to reconstruct the company's Java project and pick up Java. In the process of writing code, I didn't pay much attention to one point before. I almost stepped on it. I'll simply record it through this article.
Value passing and reference passing in Java
Data types in Java are divided into two categories: basic types and object types. Accordingly, there are two types of variables: basic type and reference type.
-
The basic type of variable saves the original value, that is, the value it represents is the value itself;
-
A variable of reference type holds a reference value. The "reference value" points to the address of the memory space and represents the reference of an object, not the object itself. The object itself is stored at the address represented by the reference value.
Value transfer is limited to four categories and eight basic data types:
Except for these four types and eight basic types, the others are objects, that is, reference types, including class types, interface types and arrays.
As for the memory allocation of the stack, I won't draw it or give an example. There are a lot of information on the Internet.
Reference passing
Let's take ArrayList as an example to see "reference passing". I have defined the following two objects:
@Data @NoArgsConstructor public class DeptDTO { /** * Department ID dept_code */ private String deptCode; /** * Department name dept_name */ private String deptName; /** * Department level dept_level */ private Integer deptLevel; }
Example code:
public static void main(String[] args) { DeptDTO dept1 = new DeptDTO(); DeptDTO dept2 = new DeptDTO(); dept1.setDeptCode("111");; dept2.setDeptCode("222");; List<DeptDTO> deptList = new ArrayList<>(); deptList.add(dept1); deptList.add(dept2); for (DeptDTO deptRecord : deptList) { System.out.println("Print deptCode:" + deptRecord.getDeptCode()); } // Getting the element inside is actually the obtained reference. Modifying the element value will affect the value of personList DeptDTO dept = deptList.get(0); dept.setDeptCode("333"); // // Modifying this value will directly affect the value of deptList, proving that deptList.add() stores the reference of the object // dept.setDeptCode("444"); for (DeptDTO deptRecord : deptList) { System.out.println("Print deptCode:" + deptRecord.getDeptCode()); } } // Output: // Print deptCode:111 // Print deptCode:222 // Print deptCode:333 // Print deptCode:222
We found that obtaining and modifying the value in the deptList will directly affect the value in the deptList because we get the reference of the value in the deptList. You may think this is very simple, but students who are used to writing Go and PHP will not adapt to it. For example, when PHP obtains array data, it is value transfer, not reference transfer. If you need to modify the data inside, you need to modify it directly through the index value corresponding to deptList.
Let's release the note above:
// Modifying this value will directly affect the value of deptList, proving that deptList.add() stores the reference of the object dept1.setDeptCode("444"); // Output: // Print deptCode:111 // Print deptCode:222 // Print deptCode:444 // Print deptCode:222
We can find that dept, dept1 and deptList.get(0) always point to the same address area. Let's simply verify it and add the code at the end:
System.out.println(System.identityHashCode(dept)); System.out.println(System.identityHashCode(dept1)); System.out.println(System.identityHashCode(deptList.get(0))); // Output: // 1612799726 // 1612799726 // 1612799726
Problem introduction
In fact, my problem is mainly the problem of reference passing when using ArrayList and HashMap. Let's add another object:
@Data public class DeptCalcuateDTO extends DeptDTO { /** * Calculation data */ private Integer calculateNumber; }
In fact, the function I want is very simple, that is, there is a list < deptdto > A. now I need to convert the data in a to deptdto B. I wrote the following code:
DeptCalcuateDTO deptCalcuateDTO = (DeptCalcuateDTO) dept1; deptCalcuateDTO.setDeptCode("333");
If the above syntax holds, because it is passed by reference, modifying deptcalculatedto will affect the data in A, but A is the basic data and cannot be modified, which is contrary to my original intention.
In fact, I found out later that I thought too much, because when I wrote the Deom use case, I found that the above coercion did not work, because ClassCastException() exception would be thrown, but C + + supports this type of coercion.
solve the problem
In fact, it's A problem of copying. I can directly assign the data in A to B, but the actual situation is that there are too many attributes in it. I don't want to convert every time, so I borrow A tool library. I feel it's easy to use. Just record it.
Import package first:
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.2.0.Final</version> </dependency>
Add entity adapter:
@Mapper(componentModel = "spring") public interface AppDeptConverter { AppDeptConverter INSTANCE = Mappers.getMapper(AppDeptConverter.class); DeptCalcuateDTO toDeptCalcuate(DeptDTO deptDTO); }
Test case:
public static void main(String[] args) { DeptDTO dept1 = new DeptDTO(); DeptDTO dept2 = new DeptDTO(); dept1.setDeptCode("111"); dept2.setDeptCode("222"); List<DeptDTO> deptList = new ArrayList<>(); deptList.add(dept1); deptList.add(dept2); DeptCalcuateDTO deptCalcuateDTO = AppDeptConverter.INSTANCE.toDeptCalcuate(dept1); deptCalcuateDTO.setDeptCode("333"); for (DeptDTO deptRecord : deptList) { System.out.println("Print deptCode:" + deptRecord.deptCode); } } // Output: // Print deptCode:111 // Print deptCode:222
In fact, the tool is very simple. Generate A deptcalculatedto object, and then assign the value of A to B in turn. For details, please refer to: https://mapstruct.org/
Welcome to the many more articles, please pay attention to the official account of WeChat public, "the road of Lou Tsai", pay attention to it and not lose your way.