最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java四種拷貝方式實(shí)戰(zhàn)總結(jié)(一文掃清所有拷貝問(wèn)題)

 更新時(shí)間:2025年07月11日 10:43:10   作者:小W求學(xué)之旅  
在Java中文件拷貝可以通過(guò)多種方式實(shí)現(xiàn),不同方式的性能和適用場(chǎng)景有所差異,文中通過(guò)代碼介紹的非常詳細(xì),這篇文章主要介紹了Java四種拷貝方式的相關(guān)資料,需要的朋友可以參考下

前言

作為Java開(kāi)發(fā)者,日常開(kāi)發(fā)中經(jīng)常會(huì)遇到數(shù)據(jù)拷貝的需求。最近在面試中也有被問(wèn)到一次大文件拷貝,抽空專(zhuān)門(mén)總結(jié)一下,從基礎(chǔ)概念到實(shí)戰(zhàn)技巧,配合流程圖,讓原理和流程一目了然~

一、淺拷貝VS深拷貝

一開(kāi)始做spring項(xiàng)目時(shí),就被淺拷貝坑過(guò)。當(dāng)時(shí)想復(fù)制一個(gè)對(duì)象,結(jié)果改了新對(duì)象的屬性,老對(duì)象也跟著變了。后來(lái)才知道,這就是淺拷貝的“鍋”。

淺拷貝就像拍證件照,照片上的人看著和你一模一樣,但本質(zhì)上還是兩張紙。Java里的淺拷貝只會(huì)復(fù)制對(duì)象的基本屬性,遇到引用類(lèi)型(比如自定義類(lèi)),就直接把地址抄過(guò)來(lái)。所以你改新對(duì)象里的引用屬性,老對(duì)象也會(huì)跟著遭殃。

深拷貝就靠譜多了,它會(huì)把對(duì)象里里外外都復(fù)制一遍,就像克隆人,新對(duì)象和老對(duì)象完全獨(dú)立。雖然麻煩點(diǎn),但勝在安全,適合處理復(fù)雜對(duì)象。

舉個(gè)例子,有個(gè)Person類(lèi)包含nameAddress屬性:

class Address {
    String city;
}

class Person {
    String name;
    Address address;

    // 淺拷貝
    Person shallowCopy() {
        Person copy = new Person();
        copy.name = this.name;
        copy.address = this.address;
        return copy;
    }

    // 深拷貝
    Person deepCopy() {
        Person copy = new Person();
        copy.name = this.name;
        copy.address = new Address();
        copy.address.city = this.address.city;
        return copy;
    }
}

二、大文件拷貝:別讓你的程序“龜速運(yùn)行”

之前做文件上傳功能,用傳統(tǒng)IO方式拷貝大文件,結(jié)果服務(wù)器直接卡住。后來(lái)?yè)Q成NIO,速度直接起飛!

傳統(tǒng)IO就像螞蟻搬家,一次搬一點(diǎn),頻繁讀寫(xiě)磁盤(pán);NIO則像卡車(chē)運(yùn)輸,直接把數(shù)據(jù)從一個(gè)地方搬到另一個(gè)地方,速度快得多。

// 傳統(tǒng)IO方式,適合小文件
public static void copyFileByIO(File source, File dest) throws IOException {
    try (InputStream is = new FileInputStream(source);
         OutputStream os = new FileOutputStream(dest)) {
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
    }
}

// NIO方式,適合大文件
public static void copyFileByNIO(File source, File dest) throws IOException {
    try (FileChannel sourceChannel = new FileInputStream(source).getChannel();
         FileChannel destChannel = new FileOutputStream(dest).getChannel()) {
        destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
    }
}

三、對(duì)象拷貝的進(jìn)階方案:使用造好的輪子

手動(dòng)寫(xiě)深拷貝代碼太麻煩?別慌,Java提供給我們有不少寫(xiě)好的辦法。

1. 序列化與反序列化

就像把對(duì)象打包成快遞,寄出去再拆開(kāi)。雖然速度慢點(diǎn),但能保證完全獨(dú)立的拷貝。不過(guò)要注意,所有相關(guān)類(lèi)都得實(shí)現(xiàn)Serializable接口。

public static <T extends Serializable> T deepCopyBySerialization(T obj) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos)) {
        oos.writeObject(obj);
        try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return (T) ois.readObject();
        }
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

2. JSON序列化

用Jackson或Gson把對(duì)象轉(zhuǎn)成JSON字符串,再轉(zhuǎn)回來(lái),簡(jiǎn)單粗暴。不過(guò)這種方式要求對(duì)象的屬性都能被JSON正確解析。

import com.fasterxml.jackson.databind.ObjectMapper;

public static <T> T deepCopyByJSON(T obj, Class<T> clazz) {
    try {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(obj);
        return mapper.readValue(json, clazz);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

四、數(shù)組和集合的拷貝

數(shù)組的clone()方法看似簡(jiǎn)單,實(shí)則暗藏玄機(jī):基本類(lèi)型數(shù)組用它是深拷貝,對(duì)象數(shù)組就是淺拷貝。

int[] intArray = {1, 2, 3};
int[] copiedIntArray = intArray.clone(); // 深拷貝

Person[] personArray = new Person[2];
Person[] copiedPersonArray = personArray.clone(); // 淺拷貝

集合類(lèi)的構(gòu)造函數(shù)也是淺拷貝,比如new ArrayList<>(originalList)。想深拷貝集合,得手動(dòng)遍歷每個(gè)元素。

List<Person> originalList = new ArrayList<>();
List<Person> deepCopiedList = originalList.stream()
        .map(Person::deepCopy)
        .collect(Collectors.toList());

五、第三方庫(kù):站在巨人的肩膀上

不想自己造輪子?Apache Commons Lang和Dozer能幫你大忙。前者提供了便捷的序列化拷貝工具,后者擅長(zhǎng)對(duì)象屬性映射,用起來(lái)超方便。

<!-- Apache Commons Lang依賴(lài) -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

// 使用示例
Person copiedPerson = SerializationUtils.clone(originalPerson);

六、總結(jié):看不同場(chǎng)景選擇合適的拷貝方式

  • 簡(jiǎn)單對(duì)象用淺拷貝,復(fù)雜對(duì)象用深拷貝
  • 大文件優(yōu)先用NIO,小文件用傳統(tǒng)IO
  • 能偷懶就偷懶,善用第三方庫(kù)
  • 多寫(xiě)測(cè)試用例,別讓拷貝“埋雷”

到此這篇關(guān)于Java四種拷貝方式實(shí)戰(zhàn)文章就介紹到這了,更多相關(guān)Java四種拷貝方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

策勒县| 固原市| 修文县| 鞍山市| 宝丰县| 隆昌县| 弥渡县| 宽城| 大同市| 林周县| 高清| 黔东| 泰宁县| 汤原县| 曲沃县| 阳城县| 清河县| 吴川市| 北票市| 托克逊县| 满洲里市| 苍山县| 克什克腾旗| 同心县| 洪江市| 滦平县| 亳州市| 永昌县| 宜章县| 清河县| 柘荣县| 永州市| 旬阳县| 东乌珠穆沁旗| 宁武县| 滨海县| 昂仁县| 郎溪县| 龙岩市| 云安县| 赫章县|