欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java Clone深拷貝與淺拷貝的兩種實(shí)現方法

1.首先,你要知道怎么實(shí)現克?。簩?shí)現Cloneable接口,在bean里面重寫(xiě)clone()方法,權限為public。
2.其次,你要大概知道什么是地址傳遞,什么是值傳遞。
3.最后,你要知道你為什么使用這個(gè)clone方法。

先看第一條,簡(jiǎn)單的克隆代碼的實(shí)現。這個(gè)也就是我們在沒(méi)了解清楚這個(gè)Java的clone的時(shí)候,會(huì )出現的問(wèn)題。

看完代碼,我再說(shuō)明這個(gè)時(shí)候的問(wèn)題。

先看我要克隆的學(xué)生bean的代碼:

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
package com.lxk.model;
/**
 * 學(xué)生類(lèi):有2個(gè)屬性:1,基本屬性-String-name;2,引用類(lèi)型-Car-car。
 * <p>
 * Created by lxk on 2017/3/23
 */
public class Student implements Cloneable {
 private String name;
 private Car car;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public Car getCar() {
 return car;
 }
 public void setCar(Car car) {
 this.car = car;
 }
 @Override
 public String toString() {
 return "Student{" +
 "name='" + name + '\'' +
 ", car=" + car +
 '}';
 }
 @Override
 public Student clone() {
 Student student = null;
 try {
 student = (Student) super.clone();
 } catch (CloneNotSupportedException ignored) {
 System.out.println(ignored.getMessage());
 }
 return student;
 }
}

學(xué)生內部引用了Car這個(gè)bean

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
package com.lxk.model;
import java.util.List;
public class Car implements Comparable<Car> {
 private String sign;
 private int price;
 private List<Dog> myDog;
 private List<String> boys;
 public Car() {
 }
 public Car(String sign, int price) {
 this.sign = sign;
 this.price = price;
 }
 public Car(String sign, int price, List<Dog> myDog) {
 this.sign = sign;
 this.price = price;
 this.myDog = myDog;
 }
 public Car(String sign, int price, List<Dog> myDog, List<String> boys) {
 this.sign = sign;
 this.price = price;
 this.myDog = myDog;
 this.boys = boys;
 }
 public String getSign() {
 return sign;
 }
 public void setSign(String sign) {
 this.sign = sign;
 }
 public int getPrice() {
 return price;
 }
 public void setPrice(int price) {
 this.price = price;
 }
 public List<Dog> getMyDog() {
 return myDog;
 }
 public void setMyDog(List<Dog> myDog) {
 this.myDog = myDog;
 }
 public List<String> getBoys() {
 return boys;
 }
 public void setBoys(List<String> boys) {
 this.boys = boys;
 }
 @Override
 public int compareTo(Car o) {
 //同理也可以根據sign屬性排序,就不舉例啦。
 return this.getPrice() - o.getPrice();
 }
 @Override
 public String toString() {
 return "Car{" +
 "sign='" + sign + '\'' +
 ", price=" + price +
 ", myDog=" + myDog +
 ", boys=" + boys +
 '}';
 }
}

最后就是main測試類(lèi)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.lxk.findBugs;
import com.lxk.model.Car;
import com.lxk.model.Student;
/**
 * 引用傳遞也就是地址傳遞需要注意的地方,引起的bug
 * <p>
 * Created by lxk on 2017/3/23
 */
public class Bug2 {
 public static void main(String[] args) {
 Student student1 = new Student();
 Car car = new Car("oooo", 100);
 student1.setCar(car);
 student1.setName("lxk");
 //克隆完之后,student1和student2應該沒(méi)關(guān)系的,修改student1不影響student2的值,但是完之后發(fā)現,你修改car的值,student2也受影響啦。
 Student student2 = student1.clone();
 System.out.println("學(xué)生2:" + student2);//先輸出student2剛剛克隆完之后的值,然后在修改student1的相關(guān)引用類(lèi)型的屬性值(car)和基本屬性值(name)
 car.setSign("X5");
 student1.setName("xxx");
 System.out.println("學(xué)生2:" + student2);//再次輸出看修改的結果
 }
}

之后就該是執行的結果圖了:

對上面執行結果的疑惑,以及解釋說(shuō)明:

我們可能覺(jué)得自己在bean里面實(shí)現clone接口,重寫(xiě)了這個(gè)clone方法,那么學(xué)生2是經(jīng)由學(xué)生1clone,復制出來(lái)的,
那么學(xué)生1和學(xué)生2,應該是毫不相干的,各自是各自,然后,在修改學(xué)生1的時(shí)候,學(xué)生2是不會(huì )受影響的。

但是結果,不盡人意。從上圖執行結果可以看出來(lái),除了名字,這個(gè)屬性是沒(méi)有被學(xué)生1影響,關(guān)于car的sign屬性已經(jīng)因為學(xué)生1的變化而變化,這不是我希望的結果。

可見(jiàn),這個(gè)簡(jiǎn)單的克隆實(shí)現也僅僅是個(gè)“淺克隆”,也就是基本類(lèi)型數據,他是會(huì )給你重新復制一份新的,但是引用類(lèi)型的,他就不會(huì )重新復制份新的。引用類(lèi)型包括,上面的其他bean的引用,list集合,等一些引用類(lèi)型。

那么怎么實(shí)現深克隆呢?

對上述代碼稍作修改,如下:
學(xué)生bean的clone重寫(xiě)方法如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public Student clone() {
Student student = null;
try {
student = (Student) super.clone();
if (car != null) {
student.setCar(car.clone());
}
} catch (CloneNotSupportedException ignored) {
System.out.println(ignored.getMessage());
}
return student;
}

然后還要Car類(lèi)實(shí)現cloneable接口,復寫(xiě)clone方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public Car clone() {
Car car = null;
try {
car = (Car) super.clone();
if (myDog != null) {
car.setMyDog(Lists.newArrayList(myDog));
}
if (boys != null) {
car.setBoys(Lists.newArrayList(boys));
}
} catch (CloneNotSupportedException ignored) {
System.out.println(ignored.getMessage());
}
return car;
}

主測試代碼不動(dòng),這個(gè)時(shí)候的執行結果如下:

可以看到,這個(gè)時(shí)候,你再修改學(xué)生1的值,就不會(huì )影響到學(xué)生2的值,這才是真正的克隆,也就是所謂的深克隆。

怎么舉一反三?

可以看到,這個(gè)例子里面的引用類(lèi)型就一個(gè)Car類(lèi)型的屬性,但是實(shí)際開(kāi)發(fā)中,除了這個(gè)引用其他bean類(lèi)型的屬性外,可能還要list類(lèi)型的屬性值用的最多。

那么要怎么深克隆呢,就像我在Car bean類(lèi)里面做的那樣,把所有的引用類(lèi)型的屬性,都在clone一遍。那么你在最上層調用這個(gè)clone方法的時(shí)候,他就是真的深克隆啦。

我代碼里面那么判斷是為了避免空指針異常。當然,這個(gè)你也得注意咯。

注意 重寫(xiě)clone方法的時(shí)候,里面各個(gè)屬性的null的判斷哦。

上面的是override clone()方法來(lái)實(shí)現深克隆的。如果你這個(gè)要克隆的對象很復雜的話(huà),你就不得不去每個(gè)引用到的對象去復寫(xiě)這個(gè)clone方法,這個(gè)太啰嗦來(lái),改的地方,太多啦。

還有個(gè)方法就是使用序列化來(lái)實(shí)現這個(gè)深拷貝

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
/**
* 對象的深度克隆,此處的對象涉及Collection接口和Map接口下對象的深度克隆
* 利用序列化和反序列化的方式進(jìn)行深度克隆對象
*
* @param object 待克隆的對象
* @param <T> 待克隆對象的數據類(lèi)型
* @return 已經(jīng)深度克隆過(guò)的對象
*/
public static <T extends Serializable> T deepCloneObject(T object) {
T deepClone = null;
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
bais = new ByteArrayInputStream(baos
 .toByteArray());
ois = new ObjectInputStream(bais);
deepClone = (T)ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(baos != null) {
 baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(oos != null) {
 oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try{
if(bais != null) {
 bais.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try{
if(ois != null) {
 ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return deepClone;
}

具體的使用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 使用序列化來(lái)實(shí)現深拷貝簡(jiǎn)單。但是,所涉及到的所有對象都的實(shí)現序列化接口。
*/
private static void cloneBySerializable() {
Student student1 = new Student();
Car car = new Car("oooo", 100, Lists.newArrayList(new Dog("aaa", true, true)));
student1.setCar(car);
student1.setName("lxk");
Student student2 = deepCloneObject(student1);
System.out.println("學(xué)生2:" + student2);
car.setSign("X5");
car.setMyDog(null);
student1.setName("xxx");
System.out.println("學(xué)生2:" + student2);
}

實(shí)現的效果,還是和上面的一樣的,但是這個(gè)就簡(jiǎn)單多來(lái),只需要給涉及到的每個(gè)引用類(lèi)型,都去實(shí)現序列化接口就好啦。

總結

以上就是這篇文章的全部?jì)热萘?,希望本文的內容對大家的學(xué)習或者工作具有一定的參考學(xué)習價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內容請查看下面相關(guān)鏈接

原文鏈接:https://blog.csdn.net/qq_27093465/article/details/65443355

微信公眾號搜索 “ 腳本之家 ” ,選擇關(guān)注

程序猿的那些事、送書(shū)等活動(dòng)等著(zhù)你

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
一種c#深拷貝方式完勝java深拷貝(實(shí)現上的對比分析)
java的深拷貝
java clone - ttitfly的筆記 - JavaEye技術(shù)網(wǎng)站
java.lang.Object.clone()分析
Java 淺拷貝和深拷貝的理解和實(shí)現方式
審查Java 代碼的十一種常見(jiàn)錯誤
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久