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

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

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 實例分析java對象中淺克隆和深克隆

實例分析java對象中淺克隆和深克隆

2021-06-03 11:40Java之家 Java教程

在本篇文章中我們給大家分享了關于java對象中淺克隆和深克隆的相關知識點和相關代碼內容,有興趣的朋友們學習下。

引言:

在object基類中,有一個方法叫clone,產生一個前期對象的克隆,克隆對象是原對象的拷貝,由于引用類型的存在,有深克隆和淺克隆之分,若克隆對象中存在引用類型的屬性,深克隆會將此屬性完全拷貝一份,而淺克隆僅僅是拷貝一份此屬性的引用。首先看一下容易犯的幾個小問題

clone方法是object類的,并不是cloneable接口的,cloneable只是一個標記接口,標記接口是用用戶標記實現該接口的類具有某種該接口標記的功能,常見的標記接口有三個:serializable、cloneable、randomaccess,沒有實現cloneable接口,那么調用clone方法就會爆出clonenotsupportedexception異常。

object類中的clone方法是protected修飾的,這就表明我們在子類中不重寫此方法,就在子類外無法訪問,因為這個protected權限是僅僅能在object所在的包和子類能訪問的,這也驗證了子類重寫父類方法權限修飾符可以變大但不能變小的說法。

?
1
protected native object clone() throws clonenotsupportedexception;

重寫clone方法,內部僅僅是調用了父類的clone方法,其實是為了擴大訪問權限,當然你可以把protected改為public,以后再繼承就不用重寫了。當然只是淺克隆的clone函數,深克隆就需要修改了。

?
1
2
3
4
@override
protected object clone() throws clonenotsupportedexception {   
 return super.clone();
}

屬性是string的情況,string也是一個類,那string引用類型嗎?string的表現有的像基本類型,歸根到底就是因為string不可改變,克隆之后倆個引用指向同一個string,但當修改其中的一個,改的不是string的值,卻是新生成一個字符串,讓被修改的引用指向新的字符串。外表看起來就像基本類型一樣。

淺克隆:

淺克隆就是引用類型的屬性無法完全復制,類user中包含成績屬性mark,mark是由chinese和math等等組成的,淺克隆失敗的例子

?
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
class mark{
  private int chinese;
  private int math;
  public mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
 
  public void setchinese(int chinese) {
    this.chinese = chinese;
  }
 
  public void setmath(int math) {
    this.math = math;
  }
 
  @override
  public string tostring() {
    return "mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class user implements cloneable{
  private string name;
  private int age;
  private mark mark;
 
  public user(string name, int age,mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @override
  public string tostring() {
    return "user{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @override
  protected object clone() throws clonenotsupportedexception {
    return super.clone();
  }
 
  public static void main(string[] args) throws clonenotsupportedexception {
    mark mark = new mark(100,99);
    user user = new user("user",22,mark);
    user userclone = (user) user.clone();
    system.out.println("原user:"+user);
    system.out.println("克隆的user:"+userclone);
    //修改引用類型的mark屬性
    user.mark.setmath(60);
    system.out.println("修改后的原user:"+user);
    system.out.println("修改后的克隆user:"+userclone);
  }
}

輸出結果為:   

原user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
克隆的user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
修改后的原user:user{name='user', age=22, mark=mark{chinese=100, math=60}}
修改后的克隆user:user{name='user', age=22, mark=mark{chinese=100, math=60}}

很清楚的看到user的mark更改后,被克隆的user也修改了。而要想不被影響,就需要深克隆了。

深克隆:

方式一:clone函數的嵌套調用

既然引用類型無法被完全克隆,那將引用類型也實現cloneable接口重寫clone方法,在user類中的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
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
class mark implements cloneable{
  private int chinese;
  private int math;
  public mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
  }
  public void setchinese(int chinese) {
    this.chinese = chinese;
  }
  public void setmath(int math) {
    this.math = math;
  }
  @override
  protected object clone() throws clonenotsupportedexception {
    return super.clone();
  }
  @override
  public string tostring() {
    return "mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class user implements cloneable{
  private string name;
  private int age;
  private mark mark;
 
  public user(string name, int age,mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @override
  public string tostring() {
    return "user{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
 
  @override
  protected object clone() throws clonenotsupportedexception {
    user user = (user) super.clone();
    user.mark = (mark) this.mark.clone();
    return user;
  }
 
  public static void main(string[] args) throws clonenotsupportedexception {
    mark mark = new mark(100,99);
    user user = new user("user",22,mark);
    user userclone = (user) user.clone();
    system.out.println("原user:"+user);
    system.out.println("克隆的user:"+userclone);
    //修改引用類型的mark屬性
    user.mark.setmath(60);
    system.out.println("修改后的原user:"+user);
    system.out.println("修改后的克隆user:"+userclone);
  }
}

輸出結果為: 

原user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
克隆的user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
修改后的原user:user{name='user', age=22, mark=mark{chinese=100, math=60}}
修改后的克隆user:user{name='user', age=22, mark=mark{chinese=100, math=99}}

方式二:序列化

上一種方法已經足夠滿足我們的需要,但是如果類之間的關系很多,或者是有的屬性是數組呢,數組可無法實現cloneable接口(我們可以在clone方法中手動復制數組),但是每次都得手寫clone方法,很麻煩,而序列化方式只需要給每個類都實現一個serializable接口,也是標記接口,最后同序列化和反序列化操作達到克隆的目的(包括數組的復制)。序列化和反序列化的知識請參照下一篇

?
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
import java.io.*;
class mark implements serializable {
  private int chinese;
  private int math;
  public mark(int chinese, int math) {
    this.chinese = chinese;
    this.math = math;
}
  public void setchinese(int chinese) {
    this.chinese = chinese;
  }
  public void setmath(int math) {
    this.math = math;
  }
  @override
  public string tostring() {
    return "mark{" +
        "chinese=" + chinese +
        ", math=" + math +
        '}';
  }
}
public class user implements serializable{
  private string name;
  private int age;
  private mark mark;
 
  public user(string name, int age,mark mark) {
    this.name = name;
    this.age = age;
    this.mark = mark;
  }
 
  @override
  public string tostring() {
    return "user{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", mark=" + mark +
        '}';
  }
  public static void main(string[] args) throws ioexception, classnotfoundexception {
    mark mark = new mark(100,99);
    user user = new user("user",22,mark);
 
    bytearrayoutputstream bo = new bytearrayoutputstream();
    objectoutputstream oo = new objectoutputstream(bo);
    oo.writeobject(user);//序列化
    bytearrayinputstream bi = new bytearrayinputstream(bo.tobytearray());
    objectinputstream oi = new objectinputstream(bi);
    user userclone = (user) oi.readobject();//反序列化
 
    system.out.println("原user:"+user);
    system.out.println("克隆的user:"+userclone);
    user.mark.setmath(59);
    system.out.println("修改后的原user:"+user);
    system.out.println("修改后的克隆user:"+userclone);
  }
}

輸出結果:

原user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
克隆的user:user{name='user', age=22, mark=mark{chinese=100, math=99}}
修改后的原user:user{name='user', age=22, mark=mark{chinese=100, math=60}}
修改后的克隆user:user{name='user', age=22, mark=mark{chinese=100, math=99}}

帶數組屬性的克隆

?
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
import java.io.*;
import java.util.arrays;
 
public class user implements serializable{
  private string name;
  private int age;
  private int[] arr;
 
  public user(string name, int age, int[] arr) {
    this.name = name;
    this.age = age;
    this.arr = arr;
  }
  @override
  public string tostring() {
    return "user{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", arr=" + arrays.tostring(arr) +
        '}';
  }
  public static void main(string[] args) throws ioexception, classnotfoundexception {
    int[] arr = {1,2,3,4,5,6};
    user user = new user("user",22,arr);
 
    bytearrayoutputstream bo = new bytearrayoutputstream();
    objectoutputstream oo = new objectoutputstream(bo);
    oo.writeobject(user);//序列化
    bytearrayinputstream bi = new bytearrayinputstream(bo.tobytearray());
    objectinputstream oi = new objectinputstream(bi);
    user userclone = (user) oi.readobject();//反序列化
 
    system.out.println("原user:"+user);
    system.out.println("克隆的user:"+userclone);
    user.arr[1] = 9;
    system.out.println("修改后的原user:"+user);
    system.out.println("修改后的克隆user:"+userclone);
  }
}

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 中文字幕亚洲一区二区三区 | 欧美成人一区二区三区电影 | 国产亚洲精品久久久久婷婷瑜伽 | 欧美一级二级毛片视频 | 在线播放一区二区三区 | 国产羞羞视频免费在线观看 | 91成人免费在线观看 | 欧美成人免费看 | 久久国产成人精品国产成人亚洲 | 黄色av.com | 国产一区在线视频观看 | 精品一区二区在线播放 | 国产成人精品午夜视频' | 中文字幕天堂在线 | 亚洲黑人在线观看 | 中文字幕在线免费 | 18一20岁一级毛片 | 亚洲特黄a级毛片在线播放 久久久入口 | 粉嫩粉嫩一区二区三区在线播放 | 欧美毛片| 色域tv | 黄色片快播 | 精品久久久久久久久中文字幕 | 91九色视频| 毛片免费观看视频 | 日韩a毛片免费观看 | 国产精品区在线12p 午夜视频色 | av电影在线网站 | 免费三级大片 | 国产精品视频一区二区三区四区五区 | 黄色网络免费看 | 国产一区视频观看 | 一级大片一级一大片 | 国产成人在线网站 | 中文字幕一区二区三区久久 | www.射| 27xxoo无遮挡动态视频 | 亚洲婷婷日日综合婷婷噜噜噜 | 亚洲字幕av | 久久精品国产99国产精品澳门 | 少妇一级淫片免费放播放 |