java拷贝对象
深克隆、浅克隆
- 深克隆
被复制对象的所有成员变量也都包含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过来的新对象,而不再是原有的那些被引用的对象。
也就是,深克隆得到的对象和原来的是两个不同的对象,他们的所有变量都在独立的对象(内存,不同的地址)中,其中原始类型的变量的值是相等的,但是引用类型的值是不相等的,即引用类型的变量引用的是不相同的对象(这两个对象使用==比较时,返回false)。 - 浅克隆
在浅克隆中,被复制对象的所有原始类型的变量(普通成员变量)都具有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
也就是,浅克隆得到的对象和原来的对象是两个不同的对象,它们的所有变量都在独立的对象(内存)中,其中原始类型的变量的值是相等的,而且引用类型的值也是相等的,即引用类型的变量引用的是同一个对象(这两个对象使用==比较时,返回true)。
Object clone()
public class Object {
/**
* Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
* The general intent is that, for any object {@code x}, the expression: x.clone() != x will be true,
* and that the expression: x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
* While it is typically the case that: x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object clone() throws CloneNotSupportedException;
}
如果要使用clone方法,对象必须实现java.lang.Cloneable 接口,否则调用clone方法会报错:throws CloneNotSupportedException ,
从上面对clone方法的注解可知clone方法的通用约定:对于任意一个对象X,
- 表达式 x.clone != x将会是true
- 表达式x.clone().getClass()==x.getClass()将会是true,但不是绝对的
- 通常情况下,表达式③x.clone().equals(x)将会是true,但是这也不是绝对的
- clone()方法返回的对象与原对象是否相等取决于你如何重写equals()方法和clone()方法
Cloneable接口
/**
* A class implements the <code>Cloneable</code> interface to
* indicate to the {@link java.lang.Object#clone()} method that it
* is legal for that method to make a
* field-for-field copy of instances of that class.
* <p>
* Invoking Object's clone method on an instance that does not implement the
* <code>Cloneable</code> interface results in the exception
* <code>CloneNotSupportedException</code> being thrown.
* <p>
* By convention, classes that implement this interface should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* <p>
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
*
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
- 要使类具有克隆能力能力时,需要实现Cloneable接口
- Cloneable是一个空接口(标记接口),它决定了Object中受保护的clone方法的实现行为:如果一个类实现了Cloneable接口,Object的clone方法就返回这个对象的逐域拷贝,否则就抛出CloneNotSupportedException异常
- clone 方法默认是浅拷贝的,即返回一个新的对象,但是新对象里的引用类型变量地址指向的还是原对象内引用类型地址
序列化方式实现对象拷贝
/**
* Java 序列化
*/
public static Object clone(Object obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
// Write the original object to output stream
oos.writeObject(obj);
oos.close();
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
// Read and return the cloned object from input stream
Object clonedObj = ois.readObject();
ois.close();
return clonedObj;
}
- 需要注意的是,和克隆对象相关的引用类都需要实现Serializable接口