1.落筆緣由
突然看到以前的筆記,思緒回到了上學(xué)的時(shí)候,滿滿的都是回憶鹉勒,以前的不堪與幼稚的想法現(xiàn)在想起來(lái)都會(huì)忍不住笑出聲了。現(xiàn)在打算整理以前的東西墩新,算是朝花夕拾吧贸弥。
2.淺拷貝和深拷貝概念
1)淺復(fù)制(淺克隆) :
網(wǎng)上有很多說(shuō)法海渊,但是我認(rèn)為淺復(fù)制就是只復(fù)制被復(fù)制對(duì)象的引用(這里的對(duì)象指的不上JAVA里的一種數(shù)據(jù)類型绵疲,而是一種泛指,這個(gè)對(duì)象可以是JAVA里的基本類型臣疑,String類型或通過(guò)new創(chuàng)建的對(duì)象等)盔憨,而不復(fù)制被復(fù)制對(duì)象的內(nèi)容。最明顯的現(xiàn)象就是如果改變復(fù)制對(duì)象的值讯沈,被復(fù)制的對(duì)象的值也會(huì)改變郁岩。
2)深復(fù)制(深克隆) :
而深拷貝則是復(fù)制被復(fù)制對(duì)象的內(nèi)容缺狠,最明顯的現(xiàn)象就是如果改變復(fù)制對(duì)象的值问慎,被復(fù)制的對(duì)象的值不會(huì)改變,也就是說(shuō)復(fù)制對(duì)象和被復(fù)制對(duì)象是兩個(gè)獨(dú)立的個(gè)體挤茄,不會(huì)因?yàn)橐粋€(gè)發(fā)生了改變而引起另一個(gè)發(fā)生改變如叼。
3.JAVA中用”=”來(lái)賦值,對(duì)于基本類型穷劈,String類型和對(duì)象來(lái)說(shuō)是深拷貝還是淺拷貝?
1)"="對(duì)基本類型來(lái)說(shuō)是深拷貝
這里我就以整型來(lái)做例子
public class TestNum {
public static void main(String[] args) {
int int1 = 111;
int int2 = int1;
System.out.println("int1:"+int1);
System.out.println("int2:"+int2);
int2 = 222;
System.out.println("After:");
System.out.println("int1:"+int1);
System.out.println("int2:"+int2);
}
}
//輸出結(jié)果:
//int1:111
//int2:111
//After:
//int1:111
//int2:222
我們可以看到改變了int2之后笼恰,int1并不會(huì)跟著改變,這是因?yàn)榛绢愋痛娣旁趦?nèi)存的棧區(qū)里歇终,當(dāng)將111賦值給int1的時(shí)候社证,會(huì)在棧區(qū)存放111,int1指向111评凝,當(dāng)將int2=int1的時(shí)候追葡,int2也是指向存放111的內(nèi)存地址,而不會(huì)在棧區(qū)再另外開一個(gè)地址來(lái)存放111肥哎,也就是說(shuō)棧區(qū)只會(huì)存放一個(gè)111整型辽俗。當(dāng)int2=222的時(shí)候,這時(shí)候會(huì)在棧區(qū)新建一個(gè)地址用來(lái)存放222這個(gè)數(shù)值篡诽,這時(shí)候int2指向這個(gè)存放222的內(nèi)存地址崖飘。
2)"="對(duì)String類型來(lái)說(shuō)是深拷貝
public class TestString {
public static void main(String[] args) {
String str1 = "lgy";
String str2 = str1;
System.out.println("str1:"+str1);
System.out.println("str2:"+str2);
str2 = "lss";
System.out.println("After:");
System.out.println("str1:"+str1);
System.out.println("str2:"+str2);
}
}
//輸出結(jié)果:
//str1:lgy
//str2:lgy
//After:
//str1:lgy
//str2:lss
其實(shí)String有點(diǎn)像基本類型,只不過(guò)它是存放在常量池里(String被final修飾)杈女。
3)"="對(duì)對(duì)象來(lái)說(shuō)是淺拷貝
/**
* @author LGY
* 對(duì)對(duì)象用=號(hào)來(lái)賦值是一種淺拷貝
*/
public class TestObject {
public static void main(String[] args) {
Child child1 = new Child();
child1.setAge(5);
child1.setName("jerry");
Child child2 = child1;
System.out.println("child1---name:"+child1.getName()+" age:"+child1.getAge());
System.out.println("child2---name:"+child2.getName()+" age:"+child2.getAge());
System.out.println("After:");
child2.setAge(7);
child2.setName("Tom");
System.out.println("child1---name:"+child1.getName()+" age:"+child1.getAge());
System.out.println("child2---name:"+child2.getName()+" age:"+child2.getAge());
}
}
//輸出結(jié)果:
//child1---name:jerry age:5
//child2---name:jerry age:5
//After:
//child1---name:Tom age:7
//child2---name:Tom age:7
用等于號(hào)來(lái)對(duì)對(duì)象拷貝朱浴,child1 和child2引用指向的是堆里的同一個(gè)對(duì)象吊圾,可以看到改變child2的信息,child1的信息也跟著改變了翰蠢,這就是淺拷貝的效果项乒。
4.對(duì)對(duì)象類型進(jìn)行深拷貝
在網(wǎng)上也看了,對(duì)對(duì)象進(jìn)行很拷貝好像有好幾種方法梁沧,沒仔細(xì)看檀何。這里只介紹Cloneable這個(gè)方法。其實(shí)只需要實(shí)現(xiàn)Cloneable接口廷支,重寫里面的clone方法即可,先了解一下這個(gè)例子要表達(dá)的意思频鉴,我要將克隆一個(gè)Child,以ChildDeepCopy 1為模版,生成一個(gè)新的Child恋拍,也就是ChildDeepCopy 2垛孔,ChildDeepCopy 1和ChildDeepCopy 2互不影響。
首先施敢,我們讓這個(gè)ChildDeepCopy 實(shí)現(xiàn)Cloneable接口周荐,重寫clone方法,如下:
public class ChildDeepCopy implements Cloneable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Object clone() {
Object o=null;
try{
o= super.clone();
}catch(CloneNotSupportedException e){
System.out.println(e.toString());
}
return o;
}
}
然后我們只要調(diào)用clone方法既可克隆出一個(gè)新的個(gè)體:
public class TestObjectDeepCopy {
public static void main(String[] args) {
ChildDeepCopy child1 = new ChildDeepCopy();
child1.setAge(5);
child1.setName("jerry");
ChildDeepCopy child2 = (ChildDeepCopy) child1.clone();
System.out.println("child1---name:"+child1.getName()+" age:"+child1.getAge());
System.out.println("child2---name:"+child2.getName()+" age:"+child2.getAge());
System.out.println("After:");
child2.setAge(7);
child2.setName("Tom");
System.out.println("child1---name:"+child1.getName()+" age:"+child1.getAge());
System.out.println("child2---name:"+child2.getName()+" age:"+child2.getAge());
}
}