编程知识 cdmana.com

Record a java reference passing problem

Preface

I've been writing for the first two months PHP Went to the , I feel like I haven't written for a long time Java Code , Because I'm going to restructure the company's Java project , Also put Java pick up . In the process of writing code , There's one thing I didn't pay much attention to before , Almost stepped on , Just make a simple record through this article .

Java Value passing and reference passing

Java There are two main types of data in , Basic types and object types . Corresponding , There are also two types of variables : Basic types and reference types .

  • Basic types of variables hold the original values , That is, the value it represents is the value itself ;
  • Variables of reference type save reference values ," Reference value " The address to the memory space , Represents a reference to an object , Not the object itself , The object itself is stored in the location of the address represented by the reference value .

Value passing is limited to four categories and eight basic data types :

Get rid of these four categories and eight basic types , The others are objects , That is, reference types , Include : Class types , Interface types and arrays .

As for the memory allocation of the stack , I won't draw this , No example , There is a lot of information on the Internet .

reference

We ArrayList Take... For example “ reference ”, I 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;
}

Sample 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());
    }

    //  Get the elements inside , It's actually a reference to get , Modify the element value , It will affect personList Value
    DeptDTO dept = deptList.get(0);
    dept.setDeptCode("333");

//        //  Modify the value , It will directly affect deptList Value , prove deptList.add() What is stored is 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 , obtain deptList The value of the inside , And then modify it , It will directly affect deptList The value of the inside , Because we got deptList The reference of the value inside . Maybe you think this is very simple , But writing habits Go and PHP Classmate , There will be some discomfort , such as PHP Get the data of the array , It's worth passing on , Not by reference , If you need to modify the data inside , Need to pass through deptList The corresponding index value can be modified directly .

Let's let go of the notes above :

//  Modify the value , It will directly affect deptList Value , prove deptList.add() What is stored is the reference of the object 
dept1.setDeptCode("444");

//  Output :
// Print deptCode:111
// Print deptCode:222
// Print deptCode:444
// Print deptCode:222

You can find dept、dept1 and deptList.get(0), Always point to the same address area , Let's simply verify , 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 to use ArrayList and HashMap when , Encountered the problem of reference passing , Let's add another object :

@Data
public class DeptCalcuateDTO  extends DeptDTO {
    /**
     *  Calculate the data
     */

    private Integer calculateNumber;
}

In fact, the function I want is very simple , There is one List< DeptDTO > A, Now I need to bring A The data in is converted to DeptTreeDTO B, I wrote the following code :

DeptCalcuateDTO deptCalcuateDTO = (DeptCalcuateDTO) dept1;
deptCalcuateDTO.setDeptCode("333");

If the above grammar holds , Because it's passed by reference , So modify deptCalcuateDTO, Will affect A Data in , however A It's basic data , It is not allowed to modify , This goes against my original intention .

In fact, I found out later that I thought too much , Because I write Deom Use case, only to find that the above cast doesn't work , Because it throws ClassCastException() abnormal , however C++ This type of cast is supported .

solve the problem

It's actually a copy problem , I can just put A The data in is assigned to B, But the actual situation is that there are too many attributes , I don't want to switch every time , I borrowed a tool library , It feels good to use , Just record it .

Bring in the package first :

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.2.0.Final</version>
</dependency>

Add entity translator :

@Mapper(componentModel = "spring")
public interface AppDeptConverter {
    AppDeptConverter INSTANCE = Mappers.getMapper(AppDeptConverter.class);

    DeptCalcuateDTO toDeptCalcuate(DeptDTO deptDTO);
}

The 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, what this tool does is very simple , Generate a DeptCalcuateDTO object , And then A The values of are assigned to B, For detailed usage, please refer to :https://mapstruct.org/

Welcome to like it more , More articles , Please follow the WeChat public account “ Louzi's way to advancement ”, Focus , Neverlost ~~

版权声明
本文为[Lou Zi]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/11/20211109094851829W.html

Scroll to Top