Java深拷贝对象
2012-08-09 11:14
267 查看
这个问题一般很多时候在面试或者实际的开发过程中都会遇到!
首先分析一下Object类提供的clone方法,
读完上面的这些,应该都明白了这里实际上是浅拷贝!
下面举个例子看看浅拷贝可能会发生的问题:
1. 例如我们在程序中正在遍历一个List或者Set集合,就在遍历还没有完成的时候,需要对这个集合进行修改或者删除操作!
如果我们这个时候在另外一个线程中修改了这个集合,那么肯定会抛出ConcurrentModificationException异常,程序终止。
这个时候我们可能会想到拷贝一份出来,就开始调用clone方法,但是还是会抛出ConcurrentModificationException异常。
原因就是因为clone是浅拷贝。
最好的解决方法就是,为了不影响正在执行的遍历,调用上面的方法,对集合进行深拷贝即可解决!
/**
* 深度拷贝对象
* @param src 源对象
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Object deepCopy(Object src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bout);
objOut.writeObject(src);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream objIn =new ObjectInputStream(bin);
return objIn.readObject();
}
首先分析一下Object类提供的clone方法,
clone protected Object clone() throws CloneNotSupportedException创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式: x.clone() != x为 true,表达式: x.clone().getClass() == x.getClass()也为 true,但这些并非必须要满足的要求。一般情况下: x.clone().equals(x)为 true,但这并非必须要满足的要求。 按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。 按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。 Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。 Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。 返回: 此实例的一个副本。 抛出: CloneNotSupportedException - 如果对象的类不支持 Cloneable 接口,则重写 clone 方法的子类也会抛出此异常,以指示无法复制某个实例。 另请参见: Cloneable
读完上面的这些,应该都明白了这里实际上是浅拷贝!
下面举个例子看看浅拷贝可能会发生的问题:
1. 例如我们在程序中正在遍历一个List或者Set集合,就在遍历还没有完成的时候,需要对这个集合进行修改或者删除操作!
如果我们这个时候在另外一个线程中修改了这个集合,那么肯定会抛出ConcurrentModificationException异常,程序终止。
这个时候我们可能会想到拷贝一份出来,就开始调用clone方法,但是还是会抛出ConcurrentModificationException异常。
原因就是因为clone是浅拷贝。
最好的解决方法就是,为了不影响正在执行的遍历,调用上面的方法,对集合进行深拷贝即可解决!
/**
* 深度拷贝对象
* @param src 源对象
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Object deepCopy(Object src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bout);
objOut.writeObject(src);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream objIn =new ObjectInputStream(bin);
return objIn.readObject();
}
相关文章推荐
- 五星-原型模式常使用于以下场景--而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝
- 在序列化和返序列化深拷贝java对象时出现的 java.io.NotSerializableException
- JAVA 对象拷贝
- java传递是引用的拷贝,既不是引用本身,更不是对象
- java对象浅拷贝与深拷贝区别
- JAVA读取PROPERTIY文件/JAVA拷贝一个对象的方式
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
- Java中利用反射原理拷贝对象
- Java Object 对象拷贝
- 关于java基础--PIO操作xls文件、持久化对象以及拷贝文件
- Java对象拷贝
- java反射(对象拷贝)
- java对象的深拷贝浅拷贝
- java 复制Map对象(深拷贝与浅拷贝)
- Java对象克隆——浅拷贝与深拷贝
- Java 开发中的对象拷贝
- java关于使用Orika的mapperFactory进行对象拷贝以及集合拷贝
- 深入理解Java中对象的浅拷贝与深拷贝
- [改善Java代码]避免对象的浅拷贝
- 设计模式(Design Patterns)-可复用面向对象软件的基础 05:原型模式(Prototype)和Java中的深、浅拷贝