一,为什么要使用clone

在实际编程过程中,我们常常遇到这种情况:有一个对象 A,需要一个和 A 完全相同新对象 B,并且此后对 B 任何改动都不会影响到 A 中的值,也就是说,A 与 B 是两个独立的对象,但 B 的初始值是由 A 对象确定的。在 Java 语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需
求虽然有很多途径,但实现 clone()方法是其中最简单,也是最高效的手段。
 

二,new和clone的区别

new 
• 通过调用类的构造函数来创建新对象实例,这意味着可以定义对象的初始化状态
• 根据对象类型明确分配相应大小的内存空间
• 需要显式初始化,通常在构造函数中完成
• 涉及内存分配、构造函数调用和初始化,可能在复杂对象中相对较慢
• 不依赖已有对象,每次创建都是全新的实例
• 无需实现任何特殊接口
• 用于全新创建对象实例,无历史状态需求
• 生成完全独立的对象,互不影响
 

clone
• 不会调用构造函数,而是复制已有对象的属性,适用于快速创建一个具有相似状态的对象
• 分配内存给新对象,并且大小与原对象相同
• 继承了原对象的初始化状态,不需要再次初始化
• 通常认为较快,因为避免了构造函数调用和逐步初始化,但具体取决于JVM实现和场景
• 必须有一个原对象作为克隆的基础
• 需要实现Cloneable接口并重写clone()方法,否则会抛出CloneNotSupportedException异常
• 用于基于现有对象快速生成一个副本,例如保存当前状态进行操作或比较
• 虽然生成的是一个新对象,但如果涉及到引用类型字段,则需要深拷贝处理,否则可能存在依赖

三, 复制对象和复制引用的区别

四,浅拷贝和深拷贝

在Java编程中,clone()方法提供了一种创建对象副本的方式。通过实现Cloneable接口并重写clone()方法,我们可以轻松地创建一个对象的完整复制品。然而,关于使用clone()方法,存在许多细节和注意事项,尤其是在处理浅克隆(shallow copy)与深克隆(deep copy)时。本篇博客将深入探讨这一主题。
        在Java中,所有对象都继承自Object类,其中包含一个clone()方法,但该方法是受保护的(protected),意味着我们不能直接在非子类外部调用它。为了使得clone()方法可用,我们需要实现Cloneable接口,该接口是一个标记接口(marker interface),本身不包含任何方法,说明这个类可拷贝。
实现Cloneable接口后,我们可以通过重写clone()方法来提供自定义的复制逻辑。如果不重写clone()方法,对象将获得一个默认的浅复制行为,这意味着基本字段将被复制,但引用类型字段将只复制引用,而不是引用的对象

浅拷贝

 protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

 可以看到后面需要加上一个抛异常的代码,而且clone返回类型是Object

深拷贝

 protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;
    }

class Money implements Cloneable{
    public double money = 19.9;
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public int age;
    public Money m;
 
    public Person(int age) {
        this.age = age;
        this.m = new Money();
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                " age=" + age +
                '}';
    }
}
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(10);
        Person person2 = (Person)person1.clone();
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
        System.out.println("==========================");
        person2.m.money = 99.99;
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
    }
}

 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐