美文网首页
Java Object之clone()方法

Java Object之clone()方法

作者: 我不吃甜食 | 来源:发表于2018-01-02 17:52 被阅读0次

Object中的clone方法定义如下:
protected native Object clone() throws CloneNotSupportedException;

定义一个可克隆的对象,一般的步骤如下:

  1. implements Cloneable;
  2. override clone()
Example
//Person及其子类都有了克隆能力
class Person implements Cloneable {
        private int age;
        private String name;

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

        public String getName() {
            return name;
        }

        @Override
        public Object clone() {
            try {
                //实际调用了Object的clone()
                return super.clone();
            } catch (CloneNotSupportedException e){
                e.printStackTrace();
                return null;
            }
        }

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

如果调用Person personOfClone = person.clone(),实际上进行的是 shallow copy,即person和personOfClone中的name引用的是同一块内存地址。对personOfClone的修改可能会影响到person。那么如何进行 deep copy?若要实现 deep copy,则必须对对象内部的引用进行clone(前提是这些引用是可克隆的)直到所有的引用都进行了clone。

默认浅克隆是合理的,因为不能确定所有的引用都是可以克隆的。

通过序列化实现 deep copy
Example
public class Compete {
    public static final int SIZE = 25000;

    public static void main(String[] args) throws Exception {
        Thing2[] a = new Thing2[SIZE];
        for (int i = 0; i < a.length; i++)
            a[i] = new Thing2();
        long t1 = System.currentTimeMillis();
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(buf);
        for (int i = 0; i < a.length; i++)
            o.writeObject(a[i]);
        // Now get copies:
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));

        Thing2[] c = new Thing2[SIZE];
        for (int i = 0; i < c.length; i++)
            //这里实际上已经进行了copy
            c[i] = (Thing2) in.readObject();
        long t2 = System.currentTimeMillis();
        System.out.println("Duplication via serialization: " +
                (t2 - t1) + " Milliseconds");

        //clone
        Thing4[] b = new Thing4[SIZE];
        for (int i = 0; i < b.length; i++)
            b[i] = new Thing4();

        t1 = System.currentTimeMillis();
        Thing4[] d = new Thing4[SIZE];
        for (int i = 0; i < d.length; i++)
            d[i] = (Thing4) b[i].clone();
        t2 = System.currentTimeMillis();
        System.out.println("Duplication via cloning: " +
                (t2 - t1) + " Milliseconds");
    }
    static class Thing1 implements Serializable {
    }

    static class Thing2 implements Serializable {
        Thing1 o1 = new Thing1();
    }

    static class Thing3 implements Cloneable {
        public Object clone() {
            Object o = null;
            try {
                o = super.clone();
            } catch (CloneNotSupportedException e) {
                System.err.println("Thing3 can't clone");
            }
            return o;
        }
    }

    static class Thing4 implements Cloneable {
        private Thing3 o3 = new Thing3();

        public Object clone() {
            Thing4 o = null;
            try {
                o = (Thing4) super.clone();
            } catch (CloneNotSupportedException e) {
                System.err.println("Thing4 can't clone");
            }
            // Clone the field, too:
            o.o3 = (Thing3) o3.clone();
            return o;
        }
    }
}

运行后发现,直接clone的速度要远快于序列化

控制克隆能力

上述例子中,一个对象首先要实现Cloneable对象,然后覆写clone()才能具有克隆能力,那么为何这样设计?

  • 假如Object.clone()是public的
    实际上,java起初是这样设计的,Object中添加了public 的clone(),那么任何对象都可以克隆了,但是如果每个对象都是可以随意克隆的,就会出现安全性问题(你不一定愿意别人克隆你的对象);今天看到的样子,是做了许多修补之后的版本:Object 中的 clone()被声明为 protected,你必须重载它、实现 Cloneable 接口、并做异常处理
  • 假如Object.clone()是private的
    这样的话,子类都不能使用Object中的native方法了。

为何调用Object.clone()

调用Object.clone()时实际会发生什么,致使你重载clone()时必须要调用super.clone() 呢? 原因大概如下:

  • Object 类的 clone()方法负责创建正确容量的存储空间,并将属性值由原对象复制到新对象的存储空间中;
  • 此方法是native的,效率很高;
  • 可以防止不能克隆的对象进行克隆;此方法会在运行期间通过Cloneable对象判断对象是否可以克隆,如果不能克隆,则会抛异常。所以,若子类的方法没有调用Object.clone(),那么实际上是不用实现Cloneable接口的。但为了使具备克隆能力的对象保持一致性,可克隆的对象应该都实现该接口。

相关文章

  • Java Object之clone()方法

    Object中的clone方法定义如下:protected native Object clone() throw...

  • 10.21

    哪个类包含 clone 方法?是 Cloneable 还是 Object?java.lang.Cloneable ...

  • JAVA基础

    java基础 equals实现 object的方法 clone,equals,notify,notifyall,h...

  • Java基础-Object类

    Object是Java所有类的父类,其重要方法包括: 一、clone() clone()方法创建并返回该对象的一个...

  • java之深拷贝和浅拷贝

    一、Object类的clone方法 1、说明 Object类的clone方法是native方法 什么是Native...

  • Java复制

    概述 Java复制分为三类:直接赋值、浅拷贝和深拷贝。 Java复制是基于Object的clone()方法。 由此...

  • Java中Object类和String类的常用方法

    Object类的常用方法 - clone() ​ Object类中的clone()方法用来复制自定义类的实例对...

  • java的clone方法

    在阿里的java开发手册里面,有这样的一条建议,慎重的使用Object的Clone方法,这个方法是native方法...

  • java基础-Object

    Object是java中的顶级父类---也是java中唯一一个没有父类的类. 重要方法 clone()---克隆出...

  • 2018-05-28 对象clone()方法

    java 的基类Object中定义了clone()(克隆)方法,但该方法并不是每个类都能调用,虽然该方法在Obje...

网友评论

      本文标题:Java Object之clone()方法

      本文链接:https://www.haomeiwen.com/subject/obfqnxtx.html