61.为什么要使用克隆?
首先要思考一个问题,为什么需要克隆对象?直接new一个对象不行吗?
克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性还是初始化的值,所以当需要一个新的对象来保存当前对象的状态,就需要用到Object类下的clone()方法,它是native关键字修饰的本地方法,底层由C语言实现,执行效率高。
62.如何实现对象克隆?
首先需要将被克隆的类实现Cloneable接口(如果不实现会抛出CloneNotSupportedException异常),该接口未标记接口,不含方法。然后重写clone()方法,访问修饰符为public,方法中调用super.clone()方法得到需要克隆的对象。
63.深拷贝和浅拷贝区别是什么?
深拷贝和浅拷贝的区别在于是否支持引用数据类型的成员变量的克隆。
深拷贝:无论原型对象的成员变量是普通类型还是引用类型,都将赋值一份给克隆对象,深拷贝将原型对象的所有引用对象也都克隆一份。
浅拷贝:如果原型对象的成员变量为普通类型,将克隆一份给克隆对象,如果原型对象的成员变量中有引用类型,则将引用类型的地址克隆给克隆对象,此时原型对象和克隆对象中的引用类型的成员变量指向相同的内存地址,也就是说二者的引用类型的成员变量是一个。
浅拷贝可以通过重写Object类中的clone()方法实现,但需要注意的是引用类型的成员变量问题。
深拷贝既可以通过重写Object类中的clone()方法,还可以通过对象的序列化和反序列化来实现。(使用clone()相对麻烦,建议使用序列化),序列化需要实现Serializable接口。
注意: 基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。