激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java 深拷貝與淺拷貝的分析

Java 深拷貝與淺拷貝的分析

2020-05-29 14:36java教程網 JAVA教程

本文主要介紹java 的深拷貝和淺拷貝,這里通過實例代碼對深拷貝和淺拷貝做了詳細的比較,希望能幫到有需要的小伙伴

在正式的進入主題之前,我們先來了解下深拷貝和前拷貝的概念:

淺拷貝

會創建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝,如果屬性是基本類型,拷貝的是基本類型的值;如果屬性是內存地址,拷貝的就是內存地址,因此如果一個對象改變了這個地址就會影響到另一個對象;

深拷貝:

不僅要復制對象的所有非引用成員變量值,還要為引用類型的成員變量創建新的實例,并且初始化為形式參數實例值;

了解完概念之后,我們來測試下普通的對象賦值操作屬于深拷貝還是淺拷貝:

測試代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DepthCopy {
  public static void main(String[] args) {
    Copy first = new Copy("hzw", 24);
    Copy second = first;
    second.name = "shanxi";
    System.out.println(first.name);//輸出shanxi
  }
}
class Copy
{
  public String name;
  public int age;
  public Copy(String name,int age) {
    this.name = name;
    this.age = age;
  }
}

可以發現,在second將name屬性值修改為shanxi之后,first的name屬性值也變成了shanxi,這點就可以看出普通的對象賦值屬于淺拷貝;

明白了對象之間賦值是淺拷貝之后,接下來我們來看看克隆到底是深拷貝還是淺拷貝,測試代碼是讓上面的Copy對象實現Cloneable接口里面的clone方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DepthCopy {
  public static void main(String[] args) {
    Copy first = new Copy("hzw", 24);
    Copy second = null;
    try {
      second = (Copy) first.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    second.name = "shanxi";
    System.out.println(first.name);//輸出: hzw
    System.out.println(first);//輸出: com.hzw.day33.Copy@7f39ebdb
    System.out.println(second);//輸出: com.hzw.day33.Copy@33abb81e
  }
}
class Copy implements Cloneable
{
  public String name;
  public int age;
  public Copy(String name,int age) {
    this.name = name;
    this.age = age;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}

可以看出原先創建出的對象first和克隆創建出的對象second是兩個實例,因此對于second中name屬性的修改并不會影響first中的name屬性;但是,我們并不能單純的認為克隆就是深拷貝的,比如下面這個例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class DepthCopy {
  public static void main(String[] args) {
    Student student = new Student(95);
    Copy first = new Copy("hzw", 24,student);
    Copy second = null;
    try {
      second = (Copy) first.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    second.name = "shanxi";
    second.student.score = 60;
    System.out.println(first == second);//false
    System.out.println(first.student == second.student);//true
    System.out.println(first.student.score);//60
  }
}
class Copy implements Cloneable
{
  public String name;
  public int age;
  public Student student;
  public Copy(String name,int age,Student student) {
    this.name = name;
    this.age = age;
    this.student = student;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
class Student 
{
  public int score;
  public Student(int score) {
    this.score = score;
  }
}

看到沒有呢?我們通過克隆的方式創建了second,很明顯發現first和second是兩個實例,因為first == second輸出為false,但是first和second里面的student對象卻是一樣的,通過second修改了student的score值之后,first里面student的score也發生了改變,這也就是說first和second里面的student是相同的,這也就說明了克隆是淺拷貝的,我們要想實現克隆的深拷貝,必須讓Copy對象里面的Student對象也要實現Cloneable接口里面的clone方法,并且在Copy里面的克隆方法返回Student的一個克隆即可,這樣就可以保證Student的唯一啦,修改之后的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class DepthCopy {
  public static void main(String[] args) {
    Student student = new Student(95);
    Copy first = new Copy("hzw", 24,student);
    Copy second = null;
    try {
      second = (Copy) first.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
    second.name = "shanxi";
    second.student.score = 60;
    System.out.println(first == second);//false
    System.out.println(first.student == second.student);//false
    System.out.println(first.student.score);//95
    System.out.println(second.student.score);//60
  }
}
class Copy implements Cloneable
{
  public String name;
  public int age;
  public Student student;
  public Copy(String name,int age,Student student) {
    this.name = name;
    this.age = age;
    this.student = student;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    Copy copy = (Copy)super.clone();
    copy.student = (Student) student.clone();
    return copy;
  }
}
class Student implements Cloneable
{
  public int score;
  public Student(int score) {
    this.score = score;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}

可以看到此時first和second和first.student和second.student都不是相同的,因此我們修改second的student的score之后并沒有影響到first里的student的score值,達到了深拷貝的目的;

但是,仔細一想問題就出來了,假如我們上面例子的Student類中也存在引用類型的屬性,比如College類,那么我們必須讓College類實現Cloneable接口,然后在Student類里面的clone方法里面調用College類的clone方法,在Copy類的clone方法中調用Student類的clone方法,發現沒有了,這個過程好復雜,必須讓類中的有關引用類型全部實現Cloneable接口,感覺好麻煩是不是,好的,接下來就該牛人登場了;

解決深拷貝問題最好的方式就是采用序列化方式,這樣各種類均不用實現Cloneable接口的,直接序列化反序列化就可以啦,我們來見識下吧。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class DepthCopy {
  public static void main(String[] args) {
    College school = new College("nongda");
    Student student = new Student(95, school);
    Copy copy = new Copy("hzw",23, student);
    Copy another = null;//表示反序列化出來的類實例
    //進行序列化操作
    try {
      FileOutputStream fos = new FileOutputStream(new File("d:/copy.txt"));
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(copy);
    } catch (Exception e) {
      e.printStackTrace();
    }
    //進行反序列化操作
    FileInputStream fis;
    try {
      fis = new FileInputStream(new File("d:/copy.txt"));
      ObjectInputStream ois = new ObjectInputStream(fis);
      another = (Copy) ois.readObject();
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println(copy == another);//false
    System.out.println(copy.student == another.student);//false
    System.out.println(copy.student.school == another.student.school);//false
    another.student.school.schoolName = "wuda";
    System.out.println(copy.student.school.schoolName);//nongda
  }
}
class Copy implements Serializable
{
  public String name;
  public int age;
  public Student student;
  public Copy(String name,int age,Student student) {
    this.name = name;
    this.age = age;
    this.student = student;
  }
}
class Student implements Serializable
{
  public int score;
  public College school;
  public Student(int score,College school) {
    this.score = score;
    this.school = school;
  }
}
class College implements Serializable
{
  public String schoolName;
  public College(String schoolName) {
    this.schoolName = schoolName;
  }
}

從輸出就可以看出來,反序列化之后生成的對象完全就是對原對象的一份拷貝,除了屬性值相同之外并不和原對象有任何關系,因此當我們修改反序列化生成對象的schoolName為"wuda"的時候并沒有修改原來實例的schoolName值,還是輸出"nongda",因此達到了真正的深拷貝效果,但是要想實現序列化,所有的有關類都必須實現Serializable接口,這總也比既實現Cloneable接口又實現clone方法更方便吧。

以上就是對Java 深拷貝和淺拷貝的詳細講解,有需要的可以參考下。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人三级电影网站 | 久久大胆视频 | 日本欧美一区二区三区在线播 | 国产成年人网站 | 一本到免费视频 | 国产成人综合在线观看 | 欧美精品久久久久久久多人混战 | 色欲香天天天综合网站 | 国产大片全部免费看 | 亚洲精品欧美在线 | 日韩av片在线播放 | 国产精品视频亚洲 | 在线成人免费观看视频 | 精品成人久久久 | 一区二区三区国产好的精 | 美女91视频 | 欧美一级免费看 | 亚洲一区二区 | 娇妻被各种姿势c到高潮小说 | 欧洲成人在线视频 | 99热1| 国产大片在线观看 | 免费黄色小视频网站 | 国产精品一区在线免费观看 | 国产欧美精品一区二区三区四区 | 久久国产成人精品国产成人亚洲 | 欧美三级欧美成人高清www | 一区二区三区欧美在线观看 | 免费看成年人网站 | 青草久久久久 | 免费99热在线观看 | jizzzxxxxhd| 久久精品亚洲国产奇米99 | 一区国产精品 | 一区二区三区视频播放 | 成人福利在线看 | 欧美日韩免费观看视频 | 免费黄色大片在线观看 | 黄色7777| 男女无遮挡羞羞视频 | 欧美三级美国一级 |