赋值、浅拷贝和深拷贝

来源:互联网 发布:淘宝有机证书编号 编辑:程序博客网 时间:2024/05/29 10:12

直接赋值

  先定义了一个变量a,然后将a变量赋值给b。则a、b两个变量都指向内存中同一个对象。

public static <T> T[] extendsArray(T[] data){    int newLength = (data.length * 3)/2 + 1;    return Arrays.copyOf(data, newLength);}public static void main(String[] args) {    TestClass[] arr = new TestClass[10];    arr[0] = new TestClass("yanjun", 24);    TestClass[] arr2 = extendsArray(arr);    arr2[0].setAge(18);    System.out.println("arr[0].age: " + arr[0].getAge());//输出18    System.out.println("arr2[0].age: " + arr2[0].getAge());//输出18}

浅拷贝

  如果先定义一个a变量,然后使用clone方法拷贝一份给b变量。这实际上是创建一个新的对象给b变量,然后将a变量指向的对象的属性赋值给b变量指向的对象。这是浅拷贝,它对于基本数据类型和String的属性是实现了拷贝,但是对于引用类型的属性(如本例中的cat),两个对象是指向同一个对象。

public static void main(String[] args) {    TestClass aaa = new TestClass("yanjun", 23);    aaa.getCat().setColor("red");    aaa.getCat().setSize(23);    TestClass bbb = (TestClass) aaa.clone();    aaa.setName("new yanjun");    aaa.setAge(18);    aaa.getCat().setColor("blue");    aaa.getCat().setSize(18);    System.out.println(aaa.getName() + "--------" + bbb.getName()); //输出new yanjun--------yanjun    System.out.println(aaa.getAge() + "--------" + bbb.getAge());//输出18--------23    System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//输出blue--------blue    System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//输出18--------18}class TestClass implements Cloneable{    private String name;    private int age;    private Cat cat;    public TestClass(String name, int age){        this.name = name;        this.age = age;        this.cat = new Cat();    }    //省去get和set方法    public Object clone(){         Object o=null;         try{             o=(TestClass)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。         }         catch(CloneNotSupportedException e){             System.out.println(e.toString());         }         return o;     }  }class Cat{    private String color;    private int size;    //省去get和set方法    public Cat() {        this.color = "red";        this.size = 23;    }}

深拷贝

  深拷贝有两种方式实现:层层clone的方法和利用串行化来做深拷贝

1、层层clone的方法

  在浅拷贝的基础上实现,给引用类型的属性添加克隆方法,并且在拷贝的时候也实现引用类型的拷贝。此种方法由于要在多个地方实现拷贝方法,可能会造成混论。

public static void main(String[] args) {    TestClass aaa = new TestClass("yanjun", 23);    aaa.getCat().setColor("red");    aaa.getCat().setSize(23);    TestClass bbb = (TestClass) aaa.clone();    aaa.setName("new yanjun");    aaa.setAge(18);    aaa.getCat().setColor("blue");    aaa.getCat().setSize(18);    System.out.println(aaa.getName() + "--------" + bbb.getName()); //输出new yanjun--------yanjun    System.out.println(aaa.getAge() + "--------" + bbb.getAge());//输出18--------23    System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//输出blue--------red    System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//输出18--------23}class TestClass implements Cloneable{    private String name;    private int age;    private Cat cat;    public TestClass(String name, int age){        this.name = name;        this.age = age;        this.cat = new Cat();    }    //省去get和set方法    public Object clone(){         TestClass o=null;         try{             o=(TestClass)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。         }         catch(CloneNotSupportedException e){             System.out.println(e.toString());         }         o.cat = (Cat)o.cat.clone();        return o;     }  }class Cat{    private String color;    private int size;    //省去get和set方法    public Cat() {        this.color = "red";        this.size = 23;    }    public Object clone(){         Object o=null;         try{             o=(Cat)super.clone();//Object 中的clone()识别出你要复制的是哪一个对象。         }         catch(CloneNotSupportedException e){             System.out.println(e.toString());         }         return o;     }  }
2、利用串行化来做深拷贝

  为避免复杂对象中使用clone方法可能带来的换乱,可以使用串化来实现深拷贝。先将对象写到流里,然后再重流里读出来。

public Object deepClone() throws IOException, ClassNotFoundException{     //将对象写到流里     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()); }