[clone]Java中的深拷贝和浅拷贝 实例解析
2015-08-16 11:25
477 查看
我们平时在开发中经常用到clone这个Object类的方法,但是super.clone()方法所返回的拷贝是浅拷贝,(所谓浅拷贝和深拷贝是相对的,浅拷贝中的内部对象与原始对象的内部对象是共享的,是同一个;而深拷贝中的内部对象也是不同的。),有些情况下,我们需要得到对象的深拷贝,如下面的情况
package day0815;
import java.io.File;
import java.util.Stack;
import org.junit.Test;
public class BaseTree{
@Test
public void testDelete(){
Tree first = new Tree(6,null,null);
first = first.put(first, 2);
first.put(first, 8);
first.put(first, 1);
first.put(first, 4);
first.put(first, 3);
//1 2 3 4 6 8
System.out.println(first);
System.out.println(first);
//
}
}
class Tree implements Cloneable{//需要实现<span style="font-family: Arial, Helvetica, sans-serif;">Cloneable接口</span>
private Object date;
private Tree left;
private Tree right;
public Tree() {
super();
}
public Tree(Object date, Tree left, Tree right) {
super();
this.date = date;
this.left = left;
this.right = right;
}
@Override
public String toString(){
StringBuffer buffer = new StringBuffer();
Tree tree = null;
try {
tree = (Tree) this.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Stack<Tree> stack = new Stack<Tree>();
while(tree!=null&&stack.size()>=0){
if(tree.getLeft()==null){
buffer.append(tree.date.toString()+" ") ;
if(tree.getRight()!=null){
tree = tree.getRight();
}else{
if(stack.size()==0){
break;
}
tree = stack.pop();
}
}else{
stack.push(tree);
Tree t = tree.getLeft();
tree.setLeft(null);
tree = t;
}
}
return buffer.toString();
}
public Tree put(Tree tree,int i){
if(i>(Integer)tree.date){
if(tree.right==null)
tree.right = new Tree(i,null,null);
else
put(tree.getRight(),i);
}else if(i==(Integer)tree.date){
return tree;
}else{
if(tree.left==null)
tree.left = new Tree(i,null,null);
else
put(tree.getLeft(),i);
}
return tree;
}
public Object getDate() {
return date;
}
public void setDate(Object date) {
this.date = date;
}
public Tree getLeft() {
return left;
}
public void setLeft(Tree left) {
this.left = left;
}
public Tree getRight() {
return right;
}
public void setRight(Tree right) {
this.right = right;
}
}
运行结果:
1 2 3 4 6 8
3 4 6 8
因为没有重写clone方法,所以得到的拷贝是浅拷贝,里面的Left属性是共享的,所以输出结构错误
可以通过下面的方法来实现深拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
Tree o = null;
o = (Tree) super.clone();
if(o.getLeft()!=null)
o.setLeft((Tree) o.getLeft().clone());
if(o.getRight()!=null)
o.setRight((Tree) o.getRight().clone());
return o;
}运行结果:
1 2 3 4 6 8
1 2 3 4 6 8
还可以通过反序列化来得到深拷贝,但是速度慢
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = null;
try {
oo = new ObjectOutputStream(bo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oo.writeObject(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = null;
try {
oi = new ObjectInputStream(bi);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
return (oi.readObject());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
package day0815;
import java.io.File;
import java.util.Stack;
import org.junit.Test;
public class BaseTree{
@Test
public void testDelete(){
Tree first = new Tree(6,null,null);
first = first.put(first, 2);
first.put(first, 8);
first.put(first, 1);
first.put(first, 4);
first.put(first, 3);
//1 2 3 4 6 8
System.out.println(first);
System.out.println(first);
//
}
}
class Tree implements Cloneable{//需要实现<span style="font-family: Arial, Helvetica, sans-serif;">Cloneable接口</span>
private Object date;
private Tree left;
private Tree right;
public Tree() {
super();
}
public Tree(Object date, Tree left, Tree right) {
super();
this.date = date;
this.left = left;
this.right = right;
}
@Override
public String toString(){
StringBuffer buffer = new StringBuffer();
Tree tree = null;
try {
tree = (Tree) this.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Stack<Tree> stack = new Stack<Tree>();
while(tree!=null&&stack.size()>=0){
if(tree.getLeft()==null){
buffer.append(tree.date.toString()+" ") ;
if(tree.getRight()!=null){
tree = tree.getRight();
}else{
if(stack.size()==0){
break;
}
tree = stack.pop();
}
}else{
stack.push(tree);
Tree t = tree.getLeft();
tree.setLeft(null);
tree = t;
}
}
return buffer.toString();
}
public Tree put(Tree tree,int i){
if(i>(Integer)tree.date){
if(tree.right==null)
tree.right = new Tree(i,null,null);
else
put(tree.getRight(),i);
}else if(i==(Integer)tree.date){
return tree;
}else{
if(tree.left==null)
tree.left = new Tree(i,null,null);
else
put(tree.getLeft(),i);
}
return tree;
}
public Object getDate() {
return date;
}
public void setDate(Object date) {
this.date = date;
}
public Tree getLeft() {
return left;
}
public void setLeft(Tree left) {
this.left = left;
}
public Tree getRight() {
return right;
}
public void setRight(Tree right) {
this.right = right;
}
}
运行结果:
1 2 3 4 6 8
3 4 6 8
因为没有重写clone方法,所以得到的拷贝是浅拷贝,里面的Left属性是共享的,所以输出结构错误
可以通过下面的方法来实现深拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
Tree o = null;
o = (Tree) super.clone();
if(o.getLeft()!=null)
o.setLeft((Tree) o.getLeft().clone());
if(o.getRight()!=null)
o.setRight((Tree) o.getRight().clone());
return o;
}运行结果:
1 2 3 4 6 8
1 2 3 4 6 8
还可以通过反序列化来得到深拷贝,但是速度慢
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = null;
try {
oo = new ObjectOutputStream(bo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oo.writeObject(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = null;
try {
oi = new ObjectInputStream(bi);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
return (oi.readObject());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
相关文章推荐
- Python动态类型的学习---引用的理解
- 土人系列AS入门教程 -- 对象篇
- C#托管堆对象实例包含内容分析
- C#中使用DataContractSerializer类实现深拷贝操作示例
- javascript asp教程第十一课--Application 对象
- PowerShell中使用Out-String命令把对象转换成字符串输出的例子
- C#中4种深拷贝方法介绍
- VBS教程:对象-正则表达式(RegExp)对象
- C#检查指定对象是否存在于ArrayList集合中的方法
- 简单谈谈C#中深拷贝、浅拷贝
- jquery的clone方法应用于textarea和select的bug修复
- sql2008启动代理未将对象应用到实例解决方案
- 浅拷贝和深拷贝深入理解(shallow copy VS deep copy)
- php中将一个对象保存到Session中的方法
- php对象和数组相互转换的方法
- PHP中把对象转换为关联数组代码分享
- Python高级:细说Python浅拷贝和深拷贝
- Python回顾与整理2:Python对象
- python面向对象之类成员
- struts2学习笔记(十一)文件上传