1. 为什么要使用克隆?
克隆可以基于原型实例,进行复制对象,并且不影响原型对象
优点 : 不需要new 实例对象,再逐一初始化参数。
(Java 中 clone 是 native 方法,克隆使用也非常快)
2. 如何实现对象克隆?
实现首先需要克隆的类 要实现 Cloneable,使用类对象 调用 Object#clone()
注意:
- 不实现 Cloneable,使用clone() 会抛出CloneNotSupportedException。
- 类重写clone(),需要调用super.clone()
- 所有数组(任何引用或原始类型的数组)都被认为实现了接口 Cloneable,并且数组类型 T[] 的克隆方法的返回类型是 T[]。
- clone()方法会创建此对象的类的新实例,并使用此对象的相应字段的内容来初始化新实例所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。
- clone()在Object类中是受限的,不能采用Object类调用clone(),如
Object o = new Student(); // 其中Student 实现了 Cloneable
o.clone(); // 编译不通过
克隆对象与原型对象会存在的关系:
- x.clone() != x
- x.clone().getClass() == x.getClass()
- x.clone().equals(x)
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
3. 深拷贝和浅拷贝区别是什么?
浅拷贝:
克隆实例的所有内容都是通过原型实例的内容赋值而得,
实现 : Object#clone 方法
深拷贝:
克隆实例的所有内容都是通过原型实例的内容 克隆 而得,
实现 : 重写clone 方法 ; 将原型实例 序列化与反序列化
序列化与反序列化
序列化:是指将对象实例转化为可存储或可传输的数据结构,如json、xml、二进制等。
反序列化:就是将可存储或可传输的数据结构 转换、重新生成一个对象实例
深浅拷贝代码对比:
ArrayList<String> arr = new ArrayList<>();
arr.add(new String("abd"));
// 使用克隆
ArrayList<String> clone = (ArrayList<String>)arr.clone();
// 使用json序列化
String s = JSONArray.toJSONString(arr);
List<String> jsonObject = JSONArray.parseArray(s, String.class);
System.out.println(arr.get(0) == clone.get(0)); // true
System.out.println(arr.get(0).equals(clone.get(0))); // true
System.out.println(arr.get(0) == jsonObject.get(0)); // false
System.out.println(arr.get(0).equals(jsonObject.get(0))); // true
Java实现序列化 ,使用类实现接口 Java.io.Serializable , 开启可序列化标识(序列化与反序列化为二进制)
在序列化和反序列化过程中需要特殊处理的类必须实现具有以下确切签名的特殊方法:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;