賦值、淺拷貝和深拷貝
阿新 • • 發佈:2018-12-30
直接賦值
先定義了一個變數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());
}