java拷贝对象

本文详细解释了Java中对象的深克隆和浅克隆概念,强调了实现Cloneable接口和使用Object.clone()方法的区别,以及通过序列化进行对象拷贝的要求。
摘要由CSDN通过智能技术生成

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接口
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值