直接赋值
先定义了一个变量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());
}