目錄
- 物件的淺拷貝、深拷貝
- 淺拷貝常見的實作方式
- 使用Object類的clone()方法
- apache的BeanUtils工具類
- spring的BeanUtils工具類
- hutool提供的BeanUtil
- 使用建議
- 深拷貝常見的實作方式
- 自行實作深拷貝
- hutool提供的ObjectUtil
- 物件的屬性復制(型別轉換)
物件的淺拷貝、深拷貝
- 淺拷貝:參考型別的成員變數是直接拷貝參考(地址),和原成員變數指向的堆中的同一個物件,優點是速度快,開銷小,性能好
- 深拷貝:參考型別的成員變數是重新創建實體,速度慢,開銷大,但更安全,可以避免共用物件導致的問題
vo、dto、po之間經常要復制屬性進行轉換,物件的轉換、復制都可以使用getter、setter方法逐個復制屬性,對于參考型別,淺拷貝是直接set get獲取的參考,深拷貝是set設定new出來的新物件,但這種方式太繁瑣,基本不用,
淺拷貝常見的實作方式
使用Object類的clone()方法
優點:根類的clone()是native方法,速度快、性能高
Object的clone是protected方法,只能在子類中使用,需要重寫暴露給外部呼叫
@Data //需要實作標記介面 Cloneable,不然呼叫clone()會報例外 CloneNotSupportedException
public class User implements Cloneable {
//...
/**
* 修改權限為public,把回傳值設定為具體的型別,方法體中呼叫Object的clone()方法
*
* @return
* @throws CloneNotSupportedException
*/
@Override
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
}
apache的BeanUtils工具類
性能差,不推薦使用
spring的BeanUtils工具類
優點:不要求2個物件是同一個類的實體,直接拷貝匹配的屬性,可以用于型別轉換
//引數依次指定source、target
BeanUtils.copyProperties(user, userVO);
//可以指定要忽略的屬性,引數個數可變
BeanUtils.copyProperties(user, userVO, "password", "tel");
hutool提供的BeanUtil
//source、target
BeanUtil.copyProperties(user, userVO);
//可以指定要忽略的屬性
BeanUtil.copyProperties(user, userVO, "id", "username");
//可以指定欄位名是否忽略大小寫
BeanUtil.copyProperties(user, userVO, true);
//Convert.convert() 轉換型別,也可以實作淺拷貝
//引數指定目標型別、源物件
User user1 = Convert.convert(User.class, user);
使用建議
spring的BeanUtils、hutool的BeanUtil對代碼侵入最小、使用簡單、功能豐富,都可以使用,
深拷貝常見的實作方式
IO流傳輸物件時使用的是深拷貝,典型方式是物件的序列化、反序列化,這也是最常見的深拷貝方式,需要注意的是 源類要是可序列化的,
自行實作深拷貝
沒必要重寫每個要深拷貝的類的clone()方法,編碼量大、很麻煩,通常是提到工具類中
/**
* 操作物件的工具類
*/
public class ObjectUtil {
/**
* 深拷貝物件
*
* @param source 源物件
* @param <T> 目標型別
* @return 新物件
* @throws IOException, ClassNotFoundException
*/
public static <T> T clone(T source) throws IOException, ClassNotFoundException {
//序列化源物件
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(source);
//反序列化得到新物件
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
T target = (T) ois.readObject();
ois.close();
oos.close();
return target;
}
}
hutool提供的ObjectUtil
User user1 = ObjectUtil.cloneByStream(user);
實質也是基于序列化、反序列化實作的
物件的屬性復制(型別轉換)
可以使用spring的BeanUtils,也可以 hutool的BeanUtil、Convert,都不要求源物件、目標物件屬于同一個類,只復制匹配的欄位,但都是淺拷貝,
spring的BeanUtils
//引數依次指定source、target
BeanUtils.copyProperties(user, userVO);
//可以指定要忽略的屬性,引數個數可變
BeanUtils.copyProperties(user, userVO, "password", "tel");
hutool的BeanUtil、Convert
//source、target
BeanUtil.copyProperties(user, userVO);
//可以指定要忽略的屬性
BeanUtil.copyProperties(user, userVO, "id", "username");
//可以指定欄位名是否忽略大小寫
BeanUtil.copyProperties(user, userVO, true);
//引數指定目標型別,源物件
User user1 = Convert.convert(User.class, user);
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/336595.html
標籤:其他
上一篇:為什么美湯會回傳重復的結果?
下一篇:Ogre光源查找與設定
