java中深拷贝和浅拷贝
2015-10-28 10:41
776 查看
先看代码,从结果中分析和总结深拷贝和浅拷贝的区别和实质。
publicclass Father {
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
}
public class Person implements Cloneable{
public String name;
private int age;
public Father father;
public Person(String name,int age,Father father){
this.name=name;
this.age=age;
this.father=father;
}
@Override
protected Object clone(){
Person p=null;
try {
p=(Person)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
客户端程序如下:
publicstaticvoid main(String[] args) {
Person person1 = new Person("son",14,new
Father("father", 52));
Person person2=person1;
System.out.println(person1==person2);//指向同一个对象
Person person3=(Person) person1.clone();
System.out.println(person1==person3);
person3.father.name="wangwu";
System.out.println(person1.father.name);
}
打印结果是:
true
false
Wangwu
我们可以看出person1和person2是指向同一个对象而person1和person3指向不同的对象,通过修改person3的futher的name值person1的也改变了,也就是说person1和person3中futher成员变量指向同一个地址,这时候我们就说这种拷贝是浅拷贝。
修改一下程序将Futher类也实现Cloneable接口
publicclass Father implements Cloneable{
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
@Override
public Object clone()throws CloneNotSupportedException
{
return super.clone();
}
}
Person类的代码也作稍微的修改
public class Person implements Cloneable{
public String name;
private int age;
public Father father;
public Person(String name,int age,Father futher){
this.name=name;
this.age=age;
this.father=father;
}
@Override
protected Object clone(){
Person p=null;
try {
p=(Person)super.clone();
p.futher=(Father)father.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
这样打印的结果是:
true
false
Father
这种拷贝是深拷贝。
浅拷贝是指拷贝对象时仅仅拷贝对象本身(对象中的基本数据类型),而不拷贝对象中包含的引用数据类型,拷贝过后引用数据类型指向被拷贝对象中引用数据类型变量的地址。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
深拷贝代码可以这样写:
public Object clone()throws CloneNotSupportedException {
Person
p=new Person();
p.age=this.age;
p.name=this.name;
p.father=new Futher(father.name,father.age);
returnp;
}
对于拷贝可能我们比较常用的方式是将对象序列化,序列化拷贝对象的缺点是效率比较低。
修改代码如下:
public class Father implements Serializable{
private static final longserialVersionUID
= 1L;
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
}
public class Person implements Serializable{
private static final long serialVersionUID
= 1L;
public String name;
private int age;
public Father father;
public Person(String name,int age,Father father){
this.name=name;
this.age=age;
this.father=father;
}
public Object deepCopy()
throws IOException,ClassNotFoundException{
//写对象到流中
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(os);
oos.writeObject(this);
//流中读取对象
ObjectInputStream ois=new ObjectInputStream(newByteArrayInputStream(os.toByteArray()));
Object readObject = ois.readObject();
return readObject;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
客户端调用deepCopy()方法也可以实现深拷贝。
publicclass Father {
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
}
public class Person implements Cloneable{
public String name;
private int age;
public Father father;
public Person(String name,int age,Father father){
this.name=name;
this.age=age;
this.father=father;
}
@Override
protected Object clone(){
Person p=null;
try {
p=(Person)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
客户端程序如下:
publicstaticvoid main(String[] args) {
Person person1 = new Person("son",14,new
Father("father", 52));
Person person2=person1;
System.out.println(person1==person2);//指向同一个对象
Person person3=(Person) person1.clone();
System.out.println(person1==person3);
person3.father.name="wangwu";
System.out.println(person1.father.name);
}
打印结果是:
true
false
Wangwu
我们可以看出person1和person2是指向同一个对象而person1和person3指向不同的对象,通过修改person3的futher的name值person1的也改变了,也就是说person1和person3中futher成员变量指向同一个地址,这时候我们就说这种拷贝是浅拷贝。
修改一下程序将Futher类也实现Cloneable接口
publicclass Father implements Cloneable{
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
@Override
public Object clone()throws CloneNotSupportedException
{
return super.clone();
}
}
Person类的代码也作稍微的修改
public class Person implements Cloneable{
public String name;
private int age;
public Father father;
public Person(String name,int age,Father futher){
this.name=name;
this.age=age;
this.father=father;
}
@Override
protected Object clone(){
Person p=null;
try {
p=(Person)super.clone();
p.futher=(Father)father.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
这样打印的结果是:
true
false
Father
这种拷贝是深拷贝。
浅拷贝是指拷贝对象时仅仅拷贝对象本身(对象中的基本数据类型),而不拷贝对象中包含的引用数据类型,拷贝过后引用数据类型指向被拷贝对象中引用数据类型变量的地址。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
深拷贝代码可以这样写:
public Object clone()throws CloneNotSupportedException {
Person
p=new Person();
p.age=this.age;
p.name=this.name;
p.father=new Futher(father.name,father.age);
returnp;
}
对于拷贝可能我们比较常用的方式是将对象序列化,序列化拷贝对象的缺点是效率比较低。
修改代码如下:
public class Father implements Serializable{
private static final longserialVersionUID
= 1L;
public String name;
public int age;
public Father(String name,int age){
this.name=name;
this.age=age;
}
}
public class Person implements Serializable{
private static final long serialVersionUID
= 1L;
public String name;
private int age;
public Father father;
public Person(String name,int age,Father father){
this.name=name;
this.age=age;
this.father=father;
}
public Object deepCopy()
throws IOException,ClassNotFoundException{
//写对象到流中
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(os);
oos.writeObject(this);
//流中读取对象
ObjectInputStream ois=new ObjectInputStream(newByteArrayInputStream(os.toByteArray()));
Object readObject = ois.readObject();
return readObject;
}
@Override
public String toString() {
return"Person [name=" +name
+ ", age=" +age +
", fatherName=" +father.name+",fatherAge="+father.age
+
"]";
}
}
客户端调用deepCopy()方法也可以实现深拷贝。
相关文章推荐
- 从头认识java-5.1 为什么需要访问权限?
- java.lang.NoClassDefFoundError:weblogic/server
- JAVA中的final关键字
- java的System.getProperty()方法可以获取的值
- 解决maven与eclipse中@override出现must override a superclass method错误
- HIVESERVER2 HA配置及使用(java)
- Struts的标签--实例
- Spring MVC 配置 druid 数据源实例
- Spring整合Junit进行单元测试
- JAVA获取随机数
- 单个工程中Spring+Mybatis连接多个数据库的配置(个人分享版本)
- 关于spring事务回滚的处理2、3事
- eclipse提示workspace无法打开的问题
- spring的isotion的属性的特征
- 获取JAVA文件路径(包括服务器环境文件路径)
- java Vamei快速教程15 IO基础
- java中有关“变量”内存分配问题
- java IO输入输出流详解
- java ee web开发学习笔记
- Spring MVC前台属性数据的传递和后台属性数据的接收