Java的拷贝分为深拷贝和浅拷贝
浅拷贝:把一个对象中所有的非static成员变量(包括对其它对象的引用,java中的引用相当于C/C++中的指针变量)都拷贝一遍,而不拷贝引用所指向的对象
深拷贝:把一个对象中所有的非static成员变量(包括对其它对象的引用)都拷贝一遍,引用所指向的对象也拷贝一份
这篇文章先讲述浅拷贝,深拷贝下篇文章讲述
一个类的对象如果想要具有拷贝的功能,比如符号如下条件:
1.必须实现Cloneable接口(这个接口中没有定义方法,叫做标记接口)
2.重写Object类的clone()方法,该方法实现的是浅拷贝
3.在该类的clone()方法中的第一句,比如调用super.clone()来调用Object的clone()方法来实现拷贝
以下是一个浅拷贝的例子:
view plaincopy to clipboardprint?
package com.test;
public class CloneTest
{
public static void main(String[] args)
{
Student s1 = new Student();
s1.setAge(20);
s1.setName("wudi");
School school = new School();
school.setName("Peiyang University");
school.setBornYear(1895);
s1.setSchool(school);
System.out
.println("s1:" + s1.getName() + " " + s1.getAge() + " "
+ s1.getSchool().getName() + " "
+ s1.getSchool().getBornYear());
try
{
//拷贝一个学生
Student s2 = (Student)s1.clone();
s2.setAge(21);
s2.setName("WUDI");
System.out
.println("s2:" + s2.getName() + " " + s2.getAge() + " "
+ s2.getSchool().getName() + " "
+ s2.getSchool().getBornYear());
System.out.println("after s2 changing some property:");
//通过学生s2改变了他所在学校的名称和成立时间
s2.getSchool().setName("Tianjin University");
s2.getSchool().setBornYear(1951);
System.out
.println("s1:" + s1.getName() + " " + s1.getAge() + " "
+ s1.getSchool().getName() + " "
+ s1.getSchool().getBornYear());
System.out
.println("s2:" + s2.getName() + " " + s2.getAge() + " "
+ s2.getSchool().getName() + " "
+ s2.getSchool().getBornYear());
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
}
}
class School
{
private String name;
private int bornYear;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getBornYear()
{
return bornYear;
}
public void setBornYear(int bornYear)
{
this.bornYear = bornYear;
}
}
class Student implements Cloneable
{
private int age;
private String name;
private School school;
public School getSchool()
{
return school;
}
public void setSchool(School school)
{
this.school = school;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}
package com.test;
public class CloneTest
{
public static void main(String[] args)
{
Student s1 = new Student();
s1.setAge(20);
s1.setName("wudi");
School school = new School();
school.setName("Peiyang University");
school.setBornYear(1895);
s1.setSchool(school);
System.out
.println("s1:" + s1.getName() + " " + s1.getAge() + " "
+ s1.getSchool().getName() + " "
+ s1.getSchool().getBornYear());
try
{
//拷贝一个学生
Student s2 = (Student)s1.clone();
s2.setAge(21);
s2.setName("WUDI");
System.out
.println("s2:" + s2.getName() + " " + s2.getAge() + " "
+ s2.getSchool().getName() + " "
+ s2.getSchool().getBornYear());
System.out.println("after s2 changing some property:");
//通过学生s2改变了他所在学校的名称和成立时间
s2.getSchool().setName("Tianjin University");
s2.getSchool().setBornYear(1951);
System.out
.println("s1:" + s1.getName() + " " + s1.getAge() + " "
+ s1.getSchool().getName() + " "
+ s1.getSchool().getBornYear());
System.out
.println("s2:" + s2.getName() + " " + s2.getAge() + " "
+ s2.getSchool().getName() + " "
+ s2.getSchool().getBornYear());
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
}
}
class School
{
private String name;
private int bornYear;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getBornYear()
{
return bornYear;
}
public void setBornYear(int bornYear)
{
this.bornYear = bornYear;
}
}
class Student implements Cloneable
{
private int age;
private String name;
private School school;
public School getSchool()
{
return school;
}
public void setSchool(School school)
{
this.school = school;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}
从运行结果可以看出,通过学生s2将其引用school所指向的对象的name和bornYear属性改变,相应的s1的也被改变,这说明学生s1和学生s2里面的school引用指向的始终是同一个School对象。这就是浅拷贝的含义。