Java對象的引用和指派分析及BeanUtils.copyProperties()使用執行個體
前言
在最近一個項目開發中遇到了複制一個對象并修改其中一個屬性值的情況,當時并沒有意識到有什麼問題,直到後面測試的時候發現不僅新對象的屬性值改了,原對象的屬性值也被修改了,這才意識到原來是犯了一個很基礎的錯誤,于是在這裡記錄下對象引用、指派問題的分析以及BeanUtils.copyProperties()方法的使用。
對象的引用
原理分析
對象是類所聲明的變量,負責存放引用,以確定對象可以操作配置設定給該對象的變量以及調用類中的方法。
當我們直接new兩個對象時,兩個對象的引用是不同的,如下圖
如果我們進行如下的指派操作的話,兩個對象就擁有了相同的引用,那麼他們的引用指向相同的實體
java複制代碼object2 = object1;
此時它們的指向則變成
看到這裡,大家應該就知道我前言中說的問題了,我将原對象的引用指派給了新對象,此時這兩個對象的引用是相同的也就是指向同一個實體,當我通過新對象去修改變量(屬性)值時,就是修改了這個實體的變量值,因為原對象和新對象的引用都指向這個實體,是以就和我的需求不一樣了
代碼示範
這裡先建立一個User類
java複制代碼package com.example.studytest.entity;
import lombok.Data;
/**
* @Description: User
* @Author: Olrookie
* @Date: 2023/6/11
*/
@Data
public class User {
/**
* 姓名
*/
private String name;
/**
* 年齡
*/
private int age;
/**
* 性别
*/
private String sex;
}
下面我們先複刻一下我的錯誤
java複制代碼public void test() {
System.out.println("test開始執行!!");
// 建立一個原對象sourceUser
User sourceUser = new User();
sourceUser.setName("小陳");
sourceUser.setAge(25);
sourceUser.setSex("女");
System.out.println("原始sourceUser:" + sourceUser);
// 建立一個對象tempUser,将原對象sourceUser的引用指派給tempUser
User tempUser = new User();
tempUser = sourceUser;
System.out.println("指派後的tempUser:" + tempUser);
// 通過新對象tempUser修改變量age的值
tempUser.setAge(18);
System.out.println("tempUser修改Age屬性後的tempUser:" + tempUser);
System.out.println("tempUser修改Age屬性後的sourceUser:" + sourceUser);
}
代碼的輸出的結果為:
java複制代碼test開始執行!!
原始sourceUser:User(name=小陳, age=25, sex=女)
指派後的tempUser:User(name=小陳, age=25, sex=女)
tempUser修改Age屬性後的tempUser:User(name=小陳, age=18, sex=女)
tempUser修改Age屬性後的sourceUser:User(name=小陳, age=18, sex=女)
通過輸出結果我們可以看到對象sourceUser的引用指向的實體的age也變成了18
BeanUtils.copyProperties()拷貝對象
這裡我們直接通過代碼來示範BeanUtils.copyProperties()拷貝對象,為了友善對比我們在上面的代碼下再new一個對象
java複制代碼// 導入包 org.springframework.beans.BeanUtils;
public void test() {
System.out.println("test開始執行!!");
// 建立一個原對象sourceUser
User sourceUser = new User();
sourceUser.setName("小陳");
sourceUser.setAge(25);
sourceUser.setSex("女");
System.out.println("原始sourceUser:" + sourceUser);
// 建立一個對象tempUser,将原對象sourceUser的引用指派給tempUser
User tempUser = new User();
tempUser = sourceUser;
System.out.println("指派後的tempUser:" + tempUser);
tempUser.setAge(18);
System.out.println("tempUser修改Age屬性後的tempUser:" + tempUser);
System.out.println("tempUser修改Age屬性後的sourceUser:" + sourceUser);
// 建立一個對象targetUser,通過BeanUtils.copyProperties()方法進行對象拷貝
User targetUser = new User();
BeanUtils.copyProperties(sourceUser, targetUser);
System.out.println("複制後的targetUser:" + targetUser);
// 通過對象targetUser修改變量age
targetUser.setAge(25);
System.out.println("修改完Age屬性後的targetUser:" + targetUser);
System.out.println("targetUser修改完Age屬性後的sourceUser:" + sourceUser);
}
程式的輸出結果為:
java複制代碼test開始執行!!
原始sourceUser:User(name=小陳, age=25, sex=女)
指派後的tempUser:User(name=小陳, age=25, sex=女)
tempUser修改Age屬性後的tempUser:User(name=小陳, age=18, sex=女)
tempUser修改Age屬性後的sourceUser:User(name=小陳, age=18, sex=女)
複制後的targetUser:User(name=小陳, age=18, sex=女)
修改完Age屬性後的targetUser:User(name=小陳, age=25, sex=女)
targetUser修改完Age屬性後的sourceUser:User(name=小陳, age=18, sex=女)
結合代碼及輸出結果我們可以得知:執行完**BeanUtils.copyProperties(sourceUser, targetUser);**後,targetUser和sourceUser輸出的結果一樣;再當我們通過targetUser修改了變量age為25後,targetUser和sourceUser輸出的結果已經不一樣了,此時他們的引用已經不同,也指向了不同的實體
結語
基礎還是太重要了,自己學習隻想着過一遍趕緊去實作需求進而忽略了重要的基礎和原理。後面還是要慢慢填坑,以上作為這次問題的記錄也是對自己一個警示,如有問題歡迎各位指出。
最後,祝大家都能沖破沖破桎梏,變得更強!
原文連結:https://juejin.cn/post/7243234089292890172