Java clone

参考:

java.lang Interface Cloneable

java.lang Class Object


下面学习 Java 中的 Object.clone() 方法 和 cloneable 接口的概念和使用,学习关于 强复制(克隆,拷贝)和浅复制 的区别和联系


主要内容:

  1. Object.clone() 方法和 cloneable 接口
  2. Object.clone() 方法的实现
  3. 深复制和浅复制

Object.clone() 方法和 cloneable 接口

参考:java.lang Class Object

Object.clone() 方法

Object 类是 Java 中类层次结构的根,是所有类的超类。新建一个类,如果没有继承超类,Java 默认使用 Object 类作为该类的超类

Object.clone() 方法格式如下:

protected native Object clone() throws CloneNotSupportedException;

功能:创建并返回复制对象

Cloneable 接口

Cloneable 接口没有任何方法,它仅用于表明类想要重载 Object.clone() 方法。如果没有继承该接口就重载 Object.clone() 方法,Object.clone() 方法将抛出 java.lang.CloneNotSupportedException 异常


Object.clone() 方法的实现

创建新类 Cloner,继承接口 Cloneable,并重载 clone 方法

import java.util.Arrays;

/**
 * Created by zj on 2017/10/16.
 */
public class Cloner implements Cloneable {

    private int num;
    private String str;
    private Person person;

    public Cloner(int num, String str, Person person) {
        this.num = num;
        this.str = str;
        this.person = person;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void setStr(String str) {
        this.str = str;
    }

    public void setName(String name) {
        this.person.setName(name);
    }

    public void setAge(int age) {
        this.person.setAge(age);
    }

    @Override
    public String toString() {
        return "Cloner{" +
                "num=" + num +
                ", str='" + str + '\'' +
                ", person=" + person +
                '}';
    }

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

    @Override
    protected Object clone() {
        Cloner cloner = null;
        try {
            cloner = (Cloner) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return cloner;
    }

    static class Person {
        String name;
        int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

重载方法 clone(),调用超类的 clone() 方法即可实现对象复制,因为 clone() 方法会抛出检查时异常 CloneNotSupportedException,所以修改代码如上所示

测试代码如下:

    public static void main(String[] args) throws CloneNotSupportedException {
        int num = 10;
        String str = "str";
        Person person = new Person("zj", 1111);

        Cloner src = new Cloner(10, "str", person);
        Cloner dst = (Cloner) src.clone();
        System.out.println("Before...");
        System.out.println(src);
        System.out.println(dst);

        dst.setNum(20);
        dst.setStr("str2");
        dst.setName("name");
        dst.setAge(100);

        System.out.println("After...");
        System.out.println(src);
        System.out.println(dst);
    }

这里写图片描述

问题:创建一个类 Cloner 的实例 src,并得到它的克隆对象 dst,修改 dst 的值,发现 src 的部分属性也发生了变化


深复制和浅复制

参考:

java clone()机制

使用 clone() 方法进行对象的复制,就是在堆上新建一个和原先对象同样大小的存储空间,将原先对象的内容复制到该存储空间

优点如下:

  1. 操作简单:仅需重载 clone() 方法即可
  2. 执行效率高:如果使用 new 关键字重新建一个对象,然后进行属性的复制,需要耗费大量的操作

缺点如下:

如果仅执行 super.clone() 方法进行复制,对复制对象的操作有可能会改变原先对象的属性

原始类型(primitive type)

参考:

Java的原始类型(Primitive Type)

Java 的原始类型就是指基本数据类型,即

  • byte
  • char
  • short
  • int
  • long
  • float
  • double
  • boolean

可变(mutable),不可变(immutable)对象

参考:

如何创建不可变(Immutable)的Java类或对象

Java中mutable对象和immutable对象的区别

不可变对象指对象被创建后无法改变状态的对象,即每次对它进行操作都是产生了新的对象,如 String

而可变对象与之相反,对象在创建后,可以在本身发送改变,如 StringBuffer

浅复制

直接使用 Object.clone() 方法进行复制的操作属于浅复制

即如果该对象内部包含了对可变对象的引用,那么复制得到的新对象同样拥有对该可变对象的引用,所以在新对象中进行可变对象的操作后,原对象的属性也发生了变化

深复制

如果复制得到的对象的操作不会影响到原对象,那么这种操作就是深复制

为实现深复制,需要在重载 clone() 方法的时候对可变对象创建新的地址空间,

上面代码修改如下:

@Override
protected Object clone() {
    Cloner cloner = null;
    try {
        cloner = (Cloner) super.clone();
        cloner.person = new Person(this.person.name, this.person.age);
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    return cloner;
}

重新测试,结果如下:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值