亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中深拷貝的方式有哪些

發布時間:2022-08-27 09:22:30 來源:億速云 閱讀:108 作者:iii 欄目:開發技術

本篇內容介紹了“java中深拷貝的方式有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

前言

在java里,當我們需要拷貝一個對象時,有兩種類型的拷貝:淺拷貝與深拷貝。

  • 淺拷貝只是拷貝了源對象的地址,所以源對象的值發生變化時,拷貝對象的值也會發生變化。

  • 深拷貝則是拷貝了源對象的所有值,所以即使源對象的值發生變化時,拷貝對象的值也不會改變。

java中深拷貝的方式有哪些

方式1:構造函數深拷貝

我們可以調用構造函數進行深拷貝,形參如果是基本類型和字符串則是直接賦值,如果是對象,則是重新new一個。

測試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:28
 * 通過構造器進行深拷貝測試
 */
@Getter
public class UserConstruct {
    private String userName;
    private AddressConstruct address;
    public UserConstruct() {
    }
    public UserConstruct(String userName, AddressConstruct address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressConstruct address = new AddressConstruct("小區1", "小區2");
        UserConstruct user = new UserConstruct("小李", address);
        // 調用構造函數進行深拷貝
        UserConstruct copyUser = new UserConstruct(user.getUserName(), new AddressConstruct(address.getAddress1(), address.getAddress2()));
        // 修改源對象的值
        user.getAddress().setAddress1("小區3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1() == copyUser.getAddress().getAddress1());
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
        // true
        System.out.println(user.getAddress().getAddress2().equals(copyUser.getAddress().getAddress2()));
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:28
 */
@Getter
@Setter
public class AddressConstruct {
    private String address1;
    private String address2;
    public AddressConstruct() {
    }
    public AddressConstruct(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}

方式2:重載Clone()方法深拷貝

Object父類有個clone()的拷貝方法,不過它是protected類型的 ,我們需要重寫它并修改為public類型,除此之外,子類還需要實現Cloneable接口來告訴JVM這個類上市可以拷貝的。

測試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:49
 *
 */
@Setter
@Getter
public class AddressClone implements Cloneable{
    private String address1;
    private String address2;
    public AddressClone() {
    }
    public AddressClone(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
    @Override
    protected AddressClone clone() throws CloneNotSupportedException {
        return (AddressClone) super.clone();
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
/**
 * @author 凌兮
 * @date 2021/4/15 14:48
 * 通過實現Clone接口實現深拷貝
 */
@Setter
@Getter
public class UserClone implements Cloneable{
    private String userName;
    private AddressClone address;
    public UserClone() {
    }
    public UserClone(String userName, AddressClone address) {
        this.userName = userName;
        this.address = address;
    }
    /**
     * Object父類有個clone()的拷貝方法,不過它是protected類型的,
     * 我們需要重寫它并修改為public類型。除此之外,
     * 子類還需要實現Cloneable接口來告訴JVM這個類是可以拷貝的。
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected UserClone clone() throws CloneNotSupportedException {
        // 需要注意的是,super.clone()其實是淺拷貝,
        // 所以在重寫UserClone類的clone()方法時,address對象需要調用address.clone()重新賦值
        UserClone userClone = (UserClone) super.clone();
        userClone.setAddress(this.address.clone());
        return userClone;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        AddressClone address = new AddressClone("小區1", "小區2");
        UserClone user = new UserClone("小李", address);
        UserClone copyUser = user.clone();
        user.getAddress().setAddress1("小區3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

需要注意的是,super.clone()其實是淺拷貝,所以在重寫User類的clone()方法時,address對象需要調用address.clone()重新賦值。

方式3:Apache Commons Lang序列化方式深拷貝

Java提供了序列化的能力,我們可以先將源對象進行序列化,再反序列化生成拷貝對象。但是,使用序列化的前提是拷貝的類(包括其成員變量)需要實現Serializable接口。

Apache Commons Lang包對Java序列化進行了封裝,我們可以直接使用它。

測試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
 * @author 凌兮
 * @date 2021/4/15 15:11
 */
@Getter
@Setter
public class AddressSerializable implements Serializable {
    private String address1;
    private String address2;
    public AddressSerializable() {
    }
    public AddressSerializable(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;
/**
 * @author 凌兮
 * @date 2021/4/15 15:10
 * 通過Apache Commons Lang 序列化方式深拷貝
 * Java提供了序列化的能力,我們可以先將源對象進行序列化,再反序列化生成拷貝對象。
 * 但是,使用序列化的前提是拷貝的類(包括其成員變量)需要實現Serializable接口。
 * Apache Commons Lang包對Java序列化進行了封裝,我們可以直接使用它。
 */
@Getter
@Setter
public class UserSerializable implements Serializable {
    private String userName;
    private AddressSerializable address;
    public UserSerializable() {
    }
    public UserSerializable(String userName, AddressSerializable address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressSerializable address = new AddressSerializable("小區1", "小區2");
        UserSerializable user = new UserSerializable("小李", address);
        UserSerializable copyUser = SerializationUtils.clone(user);
        user.getAddress().setAddress1("小區3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

方式4:Gson序列化方式深拷貝

Gson可以將對象序列化成JSON,也可以將JSON反序列化成對象,所以我們可以用它進行深拷貝。

測試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:31
 */
@Data
public class AddressGson {
    private String address1;
    private String address2;
    public AddressGson() {
    }
    public AddressGson(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import com.google.gson.Gson;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:30
 * 使用Gson序列化方式進行深拷貝
 * Gson可以將對象序列化成JSON,也可以將JSON反序列化成對象,所以我們可以用它進行深拷貝
 */
@Data
public class UserGson {
    private String userName;
    private AddressGson address;
    public UserGson() {
    }
    public UserGson(String userName, AddressGson address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) {
        AddressGson address = new AddressGson("小區1", "小區2");
        UserGson user = new UserGson("小李", address);
        // 使用Gson序列化進行深拷貝
        Gson gson = new Gson();
        UserGson copyUser = gson.fromJson(gson.toJson(user), UserGson.class);
        user.getAddress().setAddress1("小區3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

方式5:Jackson序列化方式

Jackson與Gson相似,可以將對象序列化成JSON,明顯不同的地方是拷貝的類(包括其成員變量)需要有默認的無參構造函數。

測試案例

package com.lyj.demo.pojo.cloneTest;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:41
 */
@Data
public class AddressJackson {
    private String address1;
    private String address2;
    public AddressJackson() {
    }
    public AddressJackson(String address1, String address2) {
        this.address1 = address1;
        this.address2 = address2;
    }
}
package com.lyj.demo.pojo.cloneTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
/**
 * @author 凌兮
 * @date 2021/4/15 15:40
 * 通過Jackson方式實現深拷貝
 * Jackson與Gson相似,可以將對象序列化成JSON,明顯不同的地方是拷貝的類(包括其成員變量)需要有默認的無參構造函數。
 */
@Data
public class UserJackson {
    private String userName;
    private AddressJackson address;
    public UserJackson() {
    }
    public UserJackson(String userName, AddressJackson address) {
        this.userName = userName;
        this.address = address;
    }
    public static void main(String[] args) throws JsonProcessingException {
        AddressJackson address = new AddressJackson("小區1", "小區2");
        UserJackson user = new UserJackson("小李", address);
        // 使用Jackson序列化進行深拷貝
        ObjectMapper objectMapper = new ObjectMapper();
        UserJackson copyUser = objectMapper.readValue(objectMapper.writeValueAsString(user), UserJackson.class);
        user.getAddress().setAddress1("小區3");
        // false
        System.out.println(user == copyUser);
        // false
        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));
    }
}

總結

深拷貝方法優點缺點
構造函數1. 底層實現簡單 2. 不需要引入第三方包 3. 系統開銷小 4. 對拷貝類沒有要求,不需要實現額外接口和方法1. 可用性差,每次新增成員變量都需要新增新的拷貝構造函數
重載clone()方法1. 底層實現較簡單 2. 不需要引入第三方包 3. 系統開銷小1. 可用性較差,每次新增成員變量可能需要修改clone()方法 2. 拷貝類(包括其成員變量)需要實現Cloneable接口
Apache Commons Lang序列化1. 可用性強,新增成員變量不需要修改拷貝方法1. 底層實現較復雜 2. 需要引入Apache Commons Lang第三方JAR包 3. 拷貝類(包括其成員變量)需要實現Serializable接口 4. 序列化與反序列化存在一定的系統開銷
Gson序列化1. 可用性強,新增成員變量不需要修改拷貝方法 2. 對拷貝類沒有要求,不需要實現額外接口和方法1. 底層實現復雜 2. 需要引入Gson第三方JAR包 3. 序列化與反序列化存在一定的系統開銷
Jackson序列化1. 可用性強,新增成員變量不需要修改拷貝方法1. 底層實現復雜 2. 需要引入Jackson第三方JAR包 3. 拷貝類(包括其成員變量)需要實現默認的無參構造函數 4. 序列化與反序列化存在一定的系統開銷

“java中深拷貝的方式有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

保亭| 通榆县| 彭泽县| 涞源县| 山丹县| 南宫市| 凯里市| 嫩江县| 玉树县| 抚远县| 水城县| 铁岭县| 济宁市| 瓮安县| 呼图壁县| 于都县| 理塘县| 昌图县| 宁安市| 如皋市| 五河县| 菏泽市| 绩溪县| 望江县| 孟村| 丹巴县| 夏津县| 吴江市| 贡觉县| 马鞍山市| 图片| 郁南县| 廊坊市| 安顺市| 苏尼特右旗| 高州市| 来凤县| 班玛县| 桑植县| 察雅县| 灯塔市|