clone 方法使用詳解
clone顧名思義就是復制, 在Java語言中, clone方法被對象調(diào)用义黎,所以會復制對象禾进。所謂的復制對象豁跑,首先要分配一個和源對象同樣大小的空間,在這個空間中創(chuàng)建一個新的對象泻云。java創(chuàng)建對象的方式:
1 使用new操作符創(chuàng)建一個對象
2 使用clone方法復制一個對象
那么這兩種方式有什么相同和不同呢艇拍? new操作符的本意是分配內(nèi)存。程序執(zhí)行到new操作符時宠纯, 首先去看new操作符后面的類型卸夕,因為知道了類型,才能知道要分配多大的內(nèi)存空間婆瓜。分配完內(nèi)存之后快集,再調(diào)用構(gòu)造函數(shù),填充對象的各個域廉白,這一步叫做對象的初始化个初,構(gòu)造方法返回后,一個對象創(chuàng)建完畢猴蹂,可以把他的引用(地址)發(fā)布到外部院溺,在外部就可以使用這個引用操縱這個對象。而clone在第一步是和new相似的磅轻, 都是分配內(nèi)存珍逸,調(diào)用clone方法時,分配的內(nèi)存和源對象(即調(diào)用clone方法的對象)相同聋溜,然后再使用原對象中對應的各個域谆膳,填充新對象的域, 填充完成之后撮躁,clone方法返回摹量,一個新的相同的對象被創(chuàng)建,同樣可以把這個新對象的引用發(fā)布到外部。
復制對象 or 復制引用
public class fz {
public static void main(String[] args) {
Person p = new Person(23, "zhang");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
}
}
當Person p1 = p;執(zhí)行之后缨称,通過打印結(jié)果可以看出凝果,打印的地址值是相同的,既然地址值都是相同的睦尽,那么肯定是同一個對象器净。p和p1只是引用而已,他們都指向了一個相同的對象Person(23当凡,“zhang”)山害。可以把這種現(xiàn)場叫做引用的復制沿量。上面代碼執(zhí)行完成之后浪慌, 內(nèi)存中的情景如下圖所示:
而下面的代碼是真真正正的克隆了一個對象。
public class fz1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
System.out.println(p);
System.out.println(p1);
}
}
從打印結(jié)果可以看出朴则,兩個對象的地址是不同的权纤,也就是說創(chuàng)建了新的對象, 而不是把原對象的地址賦給了一個新的引用變量乌妒。以上代碼執(zhí)行完成后汹想, 內(nèi)存中的情景如下圖所示:
深拷貝 or 淺拷貝
深拷貝:復制對象
淺拷貝:復制引用(如果只是用Object中默認的clone方法,是淺拷貝)
上面的示例代碼中撤蚊,Person中有兩個成員變量古掏,分別是name和age, name是String類型侦啸, age是int類型槽唾。代碼非常簡單,如下所示:
public class Person implements Cloneable{
private int age ;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
由于age是基本數(shù)據(jù)類型光涂, 那么對它的拷貝沒有什么疑議庞萍,直接將一個4字節(jié)的整數(shù)值拷貝過來就行。但是name是String類型的顶捷, 它只是一個引用挂绰, 指向一個真正的String對象,那么對它的拷貝有兩種方式: 直接將源對象中的name的引用值拷貝給新對象的name字段服赎, 或者是根據(jù)原Person對象中的name指向的字符串對象創(chuàng)建一個新的相同的字符串對象葵蒂,將這個新字符串對象的引用賦給新拷貝的Person對象的name字段。這兩種拷貝方式分別叫做淺拷貝和深拷貝重虑。
下面通過代碼進行驗證践付。如果兩個Person對象的name的地址值相同, 說明兩個對象的name都指向同一個String對象缺厉, 也就是淺拷貝永高, 而如果兩個對象的name的地址值不同隧土, 那么就說明指向不同的String對象, 也就是在拷貝Person對象的時候命爬, 同時拷貝了name引用的String對象曹傀, 也就是深拷貝。驗證代碼如下:
public class fz2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
System.out.println("p.getName().hashCode() : " + p.getName().hashCode());
System.out.println("p1.getName().hashCode() : " + p1.getName().hashCode());
String result = p.getName().hashCode() == p1.getName().hashCode()
? "clone是淺拷貝的" : "clone是深拷貝的";
System.out.println(result);
}
}
覆蓋Object中的clone方法饲宛, 實現(xiàn)深拷貝
現(xiàn)在為了要在clone對象時進行深拷貝皆愉, 那么就要Clonable接口,覆蓋并實現(xiàn)clone方法艇抠,除了調(diào)用父類中的clone方法得到新的對象幕庐, 還要將該類中的引用變量也clone出來。如果只是用Object中默認的clone方法家淤,是淺拷貝的异剥,再次以下面的代碼驗證:
public class fz4 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Head /* implements Cloneable */{
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
}
static class Face{}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head());
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
}
在以上代碼中, 有兩個主要的類絮重, 分別為Body和head冤寿, 在Body類中, 組合了一個head對象绿鸣。當對Body對象進行clone時疚沐, 它組合的head對象只進行淺拷貝暂氯。
如果要使Body對象在clone時進行深拷貝潮模, 那么就要在Body的clone方法中,將源對象引用的Head對象也clone一份痴施。
public class fz4 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// return super.clone();
Body newBody = (Body) super.clone();
newBody.head = (Head) head.clone();
return newBody;
}
}
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Face{}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head());
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
}
由此可見擎厢, body和body1內(nèi)的head引用指向了不同的Head對象, 也就是說在clone Body對象的同時辣吃, 也拷貝了它所引用的Head對象动遭, 進行了深拷貝。
真的是深拷貝嗎神得?
如果想要深拷貝一個對象厘惦, 這個對象必須要實現(xiàn)Cloneable接口,實現(xiàn)clone方法哩簿,并且在clone方法內(nèi)部宵蕉,把該對象引用的其他對象也要clone一份 , 這就要求這個被引用的對象必須也要實現(xiàn)Cloneable接口并且實現(xiàn)clone方法节榜。
那么羡玛,按照上面的結(jié)論, Body類組合了Head類宗苍, 而Head類組合了Face類稼稿,要想深拷貝Body類薄榛,必須在Body類的clone方法中將Head類也要拷貝一份,但是在拷貝Head類時让歼,默認執(zhí)行的是淺拷貝敞恋,也就是說Head中組合的Face對象并不會被拷貝。驗證代碼如下:
public class fz6 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Body newBody = (Body) super.clone();
newBody.head = (Head) head.clone();
return newBody;
}
}
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Face {}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head(new Face()));
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
System.out.println("body.head.face == body1.head.face : " + (body.head.face == body1.head.face));
}
}
內(nèi)存結(jié)構(gòu)圖如下圖所示:
對于Body對象來說谋右,其實應該算是深拷貝耳舅,因為對Body對象內(nèi)所引用的其他對象(目前只有Head)都進行了拷貝,也就是說兩個獨立的Body對象內(nèi)的head引用已經(jīng)指向了獨立的兩個Head對象倚评。但是浦徊,這對于兩個Head對象來說,他們指向了同一個Face對象天梧,這就說明盔性,兩個Body對象還是有一定的聯(lián)系,并沒有完全的獨立呢岗。這應該說是一種不徹底的深拷貝冕香。
如何進行徹底的深拷貝
于上面的例子來說,怎樣才能保證兩個Body對象完全獨立呢后豫?只要在拷貝Head對象的時候悉尾,也將Face對象拷貝一份就可以了。這需要讓Face類也實現(xiàn)Cloneable接口挫酿,實現(xiàn)clone方法构眯,并且在在Head對象的clone方法中,拷貝它所引用的Face對象早龟。修改的部分代碼如下:
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Head newHead =(Head)super.clone();
newHead.face = (Face)face.clone();
return newHead;
}
}
static class Face implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
這說名兩個Body已經(jīng)完全獨立了惫霸,他們間接引用的face對象已經(jīng)被拷貝,也就是引用了獨立的Face對象葱弟。
依此類推壹店,如果Face對象還引用了其他的對象, 比如說Mouth芝加,如果不經(jīng)過處理硅卢,Body對象拷貝之后還是會通過一級一級的引用,引用到同一個Mouth對象藏杖。同理将塑, 如果要讓Body在引用鏈上完全獨立, 只能顯式的讓Mouth對象也被拷貝制市。到此抬旺,可以得到如下結(jié)論:如果在拷貝一個對象時,要想讓這個拷貝的對象和源對象完全彼此獨立祥楣,那么在引用鏈上的每一級對象都要被顯式的拷貝开财。所以創(chuàng)建徹底的深拷貝是非常麻煩的汉柒,尤其是在引用關(guān)系非常復雜的情況下, 或者在引用鏈的某一級上引用了一個第三方的對象责鳍, 而這個對象沒有實現(xiàn)clone方法碾褂, 那么在它之后的所有引用的對象都是被共享的。 舉例來說历葛,如果被Head引用的Face類是第三方庫中的類正塌,并且沒有實現(xiàn)Cloneable接口,那么在Face之后的所有對象都會被拷貝前后的兩個Body對象共同引用恤溶。假設Face對象內(nèi)部組合了Mouth對象乓诽,并且Mouth對象內(nèi)部組合了Tooth對象, 內(nèi)存結(jié)構(gòu)如下圖:
至于徹底深拷貝咒程,幾乎是不可能實現(xiàn)的鸠天。有些專家級的程序員干脆從來不去覆蓋clone方法,也從來不去調(diào)用它帐姻,除非拷貝數(shù)組稠集。
public class ArrCopyTest {
public static void main(String[] args) {
String[] arr1=new String[]{"a","b","c"};
ArrCopyTest.printArr(arr1);
System.out.println("arr1copy8=arr1.clone()");
String[] arr1copy8=arr1.clone();
ArrCopyTest.printArr(arr1copy8);
arr1[1]="well";//現(xiàn)在,我把原來數(shù)組arr1的值改變一下
ArrCopyTest.printArr(arr1);
ArrCopyTest.printArr(arr1copy8);
}
public static void printArr(String arr[]){
if(arr==null){
System.out.println("arr is null");
}else{
System.out.println("arr.hashCode is:"+arr.hashCode());
for(int i=0;i<arr.length;i++){
System.out.println("arr["+i+"]:"+arr[i]);
}
}
}
}
clone顧名思義就是復制饥瓷, 在Java語言中剥纷, clone方法被對象調(diào)用,所以會復制對象。所謂的復制對象,首先要分配一個和源對象同樣大小的空間熟丸,在這個空間中創(chuàng)建一個新的對象。java創(chuàng)建對象的方式:
1 使用new操作符創(chuàng)建一個對象
2 使用clone方法復制一個對象
那么這兩種方式有什么相同和不同呢鳖宾? new操作符的本意是分配內(nèi)存吼砂。程序執(zhí)行到new操作符時逆航, 首先去看new操作符后面的類型,因為知道了類型渔肩,才能知道要分配多大的內(nèi)存空間因俐。分配完內(nèi)存之后,再調(diào)用構(gòu)造函數(shù)周偎,填充對象的各個域抹剩,這一步叫做對象的初始化,構(gòu)造方法返回后蓉坎,一個對象創(chuàng)建完畢澳眷,可以把他的引用(地址)發(fā)布到外部,在外部就可以使用這個引用操縱這個對象蛉艾。而clone在第一步是和new相似的钳踊, 都是分配內(nèi)存衷敌,調(diào)用clone方法時,分配的內(nèi)存和源對象(即調(diào)用clone方法的對象)相同拓瞪,然后再使用原對象中對應的各個域缴罗,填充新對象的域, 填充完成之后祭埂,clone方法返回面氓,一個新的相同的對象被創(chuàng)建,同樣可以把這個新對象的引用發(fā)布到外部蛆橡。
復制對象 or 復制引用
public class fz {
public static void main(String[] args) {
Person p = new Person(23, "zhang");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
}
}
當Person p1 = p;執(zhí)行之后舌界,通過打印結(jié)果可以看出,打印的地址值是相同的泰演,既然地址值都是相同的禀横,那么肯定是同一個對象。p和p1只是引用而已粥血,他們都指向了一個相同的對象Person(23柏锄,“zhang”)「纯鳎可以把這種現(xiàn)場叫做引用的復制趾娃。上面代碼執(zhí)行完成之后, 內(nèi)存中的情景如下圖所示:
而下面的代碼是真真正正的克隆了一個對象缔御。
public class fz1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
System.out.println(p);
System.out.println(p1);
}
}
從打印結(jié)果可以看出抬闷,兩個對象的地址是不同的,也就是說創(chuàng)建了新的對象耕突, 而不是把原對象的地址賦給了一個新的引用變量笤成。以上代碼執(zhí)行完成后, 內(nèi)存中的情景如下圖所示:
深拷貝 or 淺拷貝
深拷貝:復制對象
淺拷貝:復制引用(如果只是用Object中默認的clone方法眷茁,是淺拷貝)
上面的示例代碼中炕泳,Person中有兩個成員變量,分別是name和age上祈, name是String類型培遵, age是int類型。代碼非常簡單登刺,如下所示:
public class Person implements Cloneable{
private int age ;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
由于age是基本數(shù)據(jù)類型籽腕, 那么對它的拷貝沒有什么疑議,直接將一個4字節(jié)的整數(shù)值拷貝過來就行纸俭。但是name是String類型的皇耗, 它只是一個引用, 指向一個真正的String對象揍很,那么對它的拷貝有兩種方式: 直接將源對象中的name的引用值拷貝給新對象的name字段郎楼, 或者是根據(jù)原Person對象中的name指向的字符串對象創(chuàng)建一個新的相同的字符串對象矾瘾,將這個新字符串對象的引用賦給新拷貝的Person對象的name字段。這兩種拷貝方式分別叫做淺拷貝和深拷貝箭启。
下面通過代碼進行驗證壕翩。如果兩個Person對象的name的地址值相同, 說明兩個對象的name都指向同一個String對象傅寡, 也就是淺拷貝放妈, 而如果兩個對象的name的地址值不同, 那么就說明指向不同的String對象荐操, 也就是在拷貝Person對象的時候芜抒, 同時拷貝了name引用的String對象, 也就是深拷貝托启。驗證代碼如下:
public class fz2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
System.out.println("p.getName().hashCode() : " + p.getName().hashCode());
System.out.println("p1.getName().hashCode() : " + p1.getName().hashCode());
String result = p.getName().hashCode() == p1.getName().hashCode()
? "clone是淺拷貝的" : "clone是深拷貝的";
System.out.println(result);
}
}
覆蓋Object中的clone方法宅倒, 實現(xiàn)深拷貝
現(xiàn)在為了要在clone對象時進行深拷貝, 那么就要Clonable接口屯耸,覆蓋并實現(xiàn)clone方法拐迁,除了調(diào)用父類中的clone方法得到新的對象, 還要將該類中的引用變量也clone出來疗绣。如果只是用Object中默認的clone方法线召,是淺拷貝的,再次以下面的代碼驗證:
public class fz4 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Head /* implements Cloneable */{
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
}
static class Face{}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head());
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
}
在以上代碼中多矮, 有兩個主要的類缓淹, 分別為Body和head, 在Body類中塔逃, 組合了一個head對象讯壶。當對Body對象進行clone時, 它組合的head對象只進行淺拷貝湾盗。
如果要使Body對象在clone時進行深拷貝伏蚊, 那么就要在Body的clone方法中,將源對象引用的Head對象也clone一份淹仑。
public class fz4 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// return super.clone();
Body newBody = (Body) super.clone();
newBody.head = (Head) head.clone();
return newBody;
}
}
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Face{}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head());
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
}
由此可見丙挽, body和body1內(nèi)的head引用指向了不同的Head對象, 也就是說在clone Body對象的同時匀借, 也拷貝了它所引用的Head對象, 進行了深拷貝平窘。
真的是深拷貝嗎吓肋?
如果想要深拷貝一個對象, 這個對象必須要實現(xiàn)Cloneable接口瑰艘,實現(xiàn)clone方法是鬼,并且在clone方法內(nèi)部肤舞,把該對象引用的其他對象也要clone一份 , 這就要求這個被引用的對象必須也要實現(xiàn)Cloneable接口并且實現(xiàn)clone方法均蜜。
那么李剖,按照上面的結(jié)論, Body類組合了Head類囤耳, 而Head類組合了Face類篙顺,要想深拷貝Body類,必須在Body類的clone方法中將Head類也要拷貝一份充择,但是在拷貝Head類時德玫,默認執(zhí)行的是淺拷貝,也就是說Head中組合的Face對象并不會被拷貝椎麦。驗證代碼如下:
public class fz6 {
static class Body implements Cloneable {
public Head head;
public Body() {
}
public Body(Head head) {
this.head = head;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Body newBody = (Body) super.clone();
newBody.head = (Head) head.clone();
return newBody;
}
}
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Face {}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head(new Face()));
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1));
System.out.println("body.head == body1.head : " + (body.head == body1.head));
System.out.println("body.head.face == body1.head.face : " + (body.head.face == body1.head.face));
}
}
內(nèi)存結(jié)構(gòu)圖如下圖所示:
對于Body對象來說宰僧,其實應該算是深拷貝,因為對Body對象內(nèi)所引用的其他對象(目前只有Head)都進行了拷貝观挎,也就是說兩個獨立的Body對象內(nèi)的head引用已經(jīng)指向了獨立的兩個Head對象琴儿。但是,這對于兩個Head對象來說嘁捷,他們指向了同一個Face對象凤类,這就說明,兩個Body對象還是有一定的聯(lián)系普气,并沒有完全的獨立谜疤。這應該說是一種不徹底的深拷貝。
如何進行徹底的深拷貝
于上面的例子來說现诀,怎樣才能保證兩個Body對象完全獨立呢夷磕?只要在拷貝Head對象的時候,也將Face對象拷貝一份就可以了仔沿。這需要讓Face類也實現(xiàn)Cloneable接口坐桩,實現(xiàn)clone方法,并且在在Head對象的clone方法中封锉,拷貝它所引用的Face對象绵跷。修改的部分代碼如下:
static class Head implements Cloneable {
public Face face;
public Head() {
}
public Head(Face face) {
this.face = face;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Head newHead =(Head)super.clone();
newHead.face = (Face)face.clone();
return newHead;
}
}
static class Face implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
這說名兩個Body已經(jīng)完全獨立了,他們間接引用的face對象已經(jīng)被拷貝成福,也就是引用了獨立的Face對象碾局。
依此類推,如果Face對象還引用了其他的對象奴艾, 比如說Mouth净当,如果不經(jīng)過處理,Body對象拷貝之后還是會通過一級一級的引用,引用到同一個Mouth對象像啼。同理俘闯, 如果要讓Body在引用鏈上完全獨立, 只能顯式的讓Mouth對象也被拷貝忽冻。到此真朗,可以得到如下結(jié)論:如果在拷貝一個對象時,要想讓這個拷貝的對象和源對象完全彼此獨立僧诚,那么在引用鏈上的每一級對象都要被顯式的拷貝遮婶。所以創(chuàng)建徹底的深拷貝是非常麻煩的,尤其是在引用關(guān)系非常復雜的情況下振诬, 或者在引用鏈的某一級上引用了一個第三方的對象蹭睡, 而這個對象沒有實現(xiàn)clone方法, 那么在它之后的所有引用的對象都是被共享的赶么。 舉例來說肩豁,如果被Head引用的Face類是第三方庫中的類,并且沒有實現(xiàn)Cloneable接口辫呻,那么在Face之后的所有對象都會被拷貝前后的兩個Body對象共同引用清钥。假設Face對象內(nèi)部組合了Mouth對象,并且Mouth對象內(nèi)部組合了Tooth對象放闺, 內(nèi)存結(jié)構(gòu)如下圖:
至于徹底深拷貝祟昭,幾乎是不可能實現(xiàn)的。有些專家級的程序員干脆從來不去覆蓋clone方法怖侦,也從來不去調(diào)用它篡悟,除非拷貝數(shù)組。
public class ArrCopyTest {
public static void main(String[] args) {
String[] arr1=new String[]{"a","b","c"};
ArrCopyTest.printArr(arr1);
System.out.println("arr1copy8=arr1.clone()");
String[] arr1copy8=arr1.clone();
ArrCopyTest.printArr(arr1copy8);
arr1[1]="well";//現(xiàn)在匾寝,我把原來數(shù)組arr1的值改變一下
ArrCopyTest.printArr(arr1);
ArrCopyTest.printArr(arr1copy8);
}
public static void printArr(String arr[]){
if(arr==null){
System.out.println("arr is null");
}else{
System.out.println("arr.hashCode is:"+arr.hashCode());
for(int i=0;i<arr.length;i++){
System.out.println("arr["+i+"]:"+arr[i]);
}
}
}
}