java浅克隆和深克隆

浅克隆和深克隆的概念

浅克隆

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

深克隆

被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。



浅克隆的实现

Object 类提供有一个clone方法,它的方法签名如下:

protected native Object clone() throws CloneNotSupportedException;

如果我们要使用clone方法,那么我们就要重写这个方法,将它的方法属性改为public,并且该类要实现 Cloneable接口。这个方法其实就提供了浅克隆的功能。

package test;

public class CloneTest {

    public static void main(String[] args) throws CloneNotSupportedException {

        new CloneTest().run();

    }

    public void run() throws CloneNotSupportedException{
        int a = 999;
        int num[] = {1,2,3};
        String str = "str1";
        String str2 = new String("str2");

        ABC abc = new ABC();
        abc.setA(a);
        abc.setAbc(num);
        abc.setStr(str);
        abc.setStr2(str2);

        System.out.println(abc);
        System.out.println();

        ABC aaa = abc.clone();

        num[0] = 0;
        a = 998;
        str = "str1str1";
        str2 = new String("str2str2");

        System.out.println(abc);
        System.out.println(aaa);
        System.out.println();

        abc.setA(997);
        abc.getAbc()[0]=100;
        abc.setStr("str1...");
        abc.setStr2(str2);

        System.out.println(abc);
        System.out.println(aaa);
        System.out.println();


    }

    public void run2() {

    }

    class ABC implements Cloneable{
        int a ;
        int []abc ;
        String str;
        String str2;

        public String getStr2() {
            return str2;
        }
        public void setStr2(String str2) {
            this.str2 = str2;
        }
        public int getA() {
            return a;
        }
        public void setA(int a) {
            this.a = a;
        }
        public String getStr() {
            return str;
        }
        public void setStr(String str) {
            this.str = str;
        }
        public int[] getAbc() {
            return abc;
        }
        public void setAbc(int[] abc) {
            this.abc = abc;
        }

        @Override 
        public ABC clone() throws CloneNotSupportedException{    
            return (ABC)super.clone();    
         }    

        @Override 
        public String toString(){
            String num = "";
            for(int i:abc){
                num+=i+" ";
            }

            return "a:"+this.a+"\n"+
                   "str1:"+this.str+"\n"+
                   "str2:"+this.str2+"\n"+
                    "abc:"+num;
        }
    }
}
结果:
    a:999
    str1:str1
    str2:str2
    abc:1 2 3 

    a:999
    str1:str1
    str2:str2
    abc:0 2 3 
    a:999
    str1:str1
    str2:str2
    abc:0 2 3 

    a:997
    str1:str1...
    str2:str2str2
    abc:100 2 3 
    a:999
    str1:str1
    str2:str2
    abc:100 2 3 

值得注意的一点是,如果引用类型是不可变的,如String类,则不必进行深克隆。

深克隆的实现

利用串行化来做深复制:把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。
应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。

package test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepCloneTest implements Serializable{

    private statssic final long serialVersionUID = 1L;

    public static void main(String[] args) throws Exception {

        new DeepCloneTest().run();

    }

    private void run() throws Exception {
        int a = 999;
        int num[] = {1,2,3};
        String str = "str1";
        String str2 = new String("str2");

        ABC abc = new ABC();
        abc.setA(a);
        abc.setAbc(num);
        abc.setStr(str);
        abc.setStr2(str2);

        ABC aaa = (ABC) abc.deepClone();

        System.out.println(abc);
        System.out.println(aaa);
        System.out.println();

        abc.getAbc()[0] = 100;

        System.out.println(abc);
        System.out.println(aaa);
        System.out.println();

    }

    class ABC implements Serializable{
        private static final long serialVersionUID = -5763470826096290328L;     
        int a ;
        int []abc ;
        String str;
        String str2;

        public String getStr2() {
            return str2;
        }
        public void setStr2(String str2) {
            this.str2 = str2;
        }
        public int getA() {
            return a;
        }
        public void setA(int a) {
            this.a = a;
        }
        public String getStr() {
            return str;
        }
        public void setStr(String str) {
            this.str = str;
        }
        public int[] getAbc() {
            return abc;
        }
        public void setAbc(int[] abc) {
            this.abc = abc;
        } 

        public Object deepClone() throws Exception {
            // 将对象写到流里
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(bo);
            oo.writeObject(this);
            // 从流里读出来
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            return (oi.readObject());
        }

        @Override 
        public String toString(){
            String num = "";
            for(int i:abc){
                num+=i+" ";
            }

            return "a:"+this.a+"\n"+
                   "str1:"+this.str+"\n"+
                   "str2:"+this.str2+"\n"+
                    "abc:"+num;
        }
    }
}    
结果:
    a:999
    str1:str1
    str2:str2
    abc:1 2 3 
    a:999
    str1:str1
    str2:str2
    abc:1 2 3 

    a:999
    str1:str1
    str2:str2
    abc:100 2 3 
    a:999
    str1:str1
    str2:str2
    abc:1 2 3 

你可能感兴趣的:(JAVA)