电子商务网站推广的主要方式,爱牛网络,上海装修公司排名知乎,青岛网站建设与管理关于Clone
一般情况下#xff0c;如果使用clone()方法#xff0c;则需满足以下条件。 1、对任何对象o#xff0c;都有o.clone() ! o。换言之#xff0c;克隆对象与原型对象不是同一个对象。 2、对任何对象o#xff0c;都有o.clone().getClass() o.getClass()。换言之如果使用clone()方法则需满足以下条件。 1、对任何对象o都有o.clone() ! o。换言之克隆对象与原型对象不是同一个对象。 2、对任何对象o都有o.clone().getClass() o.getClass()。换言之克隆对象与原型对象的类型一样。 3、如果对象o的equals()方法定义恰当则o.clone().equals(o)应当成立。
我们在设计自定义类的clone()方法时应当遵守这3个条件。一般来说这3个条件中的前2个是必需的第3个是可选的。 浅拷贝
super.clone()方法直接从堆内存中以二进制流的方式进行复制重新分配一个内存块因此其效率很高。 由于super.clone()方法基于内存复制因此不会调用对象的构造函数也就是不需要经历初始化过程。 只有基本类型的参数会被拷贝一份非基本类型的对象不会被拷贝一份而是继续使用传递引用的方式原型对象与克隆对象的该属性只是指向同一对象的引用即浅拷贝。 Overridepublic Object clone() throws CloneNotSupportedException{Employees employees (Employees)super.clone();return employees;}深拷贝
在日常开发中使用super.clone()方法并不能满足所有需求。如类中存在引用对象属性。就要需要实现深拷贝必须要自己手动修改 clone 方法才行。 Overridepublic Object clone() throws CloneNotSupportedException{ListString temp new ArrayListString();for(String s : this.getEmpList()){temp.add(s);}return new Employees(temp);}使用序列化Serializable
不过如果当原型对象维护很多引用属性的时候手动分配会比较烦琐。因此在Java中如果想完成原型对象的深克隆则通常使用 序列化Serializable的方式。
public class Employees implements Cloneable,Serializable{private ListString empList;public Employees(){empList new ArrayListString();}public Employees(ListString list){this.empListlist;}public void loadData(){//read all employees from database and put into the listempList.add(Pankaj);empList.add(Raj);empList.add(David);empList.add(Lisa);}public ListString getEmpList() {return empList;}Overridepublic Object clone() throws CloneNotSupportedException{ListString temp new ArrayListString();for(String s : this.getEmpList()){temp.add(s);}return new Employees(temp);}public Object deepClone() throws CloneNotSupportedException{try {ByteArrayOutputStream bos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(bos);oos.writeObject(this);ByteArrayInputStream bis new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois new ObjectInputStream(bis);return (Employees)ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();return null;}}
}测试 public static void main(String[] args) throws CloneNotSupportedException {Employees emps new Employees();emps.loadData();Employees empsNew (Employees) emps.deepClone();Employees empsNew1 (Employees) emps.deepClone();ListString list empsNew.getEmpList();list.add(John);ListString list1 empsNew1.getEmpList();list1.remove(Pankaj);System.out.println(emps List: emps.getEmpList());System.out.println(empsNew List: list);System.out.println(empsNew1 List: list1);}emps List: [Pankaj, Raj, David, Lisa]
empsNew List: [Pankaj, Raj, David, Lisa, John]
empsNew1 List: [Raj, David, Lisa]还原克隆破坏单例的事故现场 假设有这样一个场景如果复制的目标对象恰好是单例对象那会不会使单例对象被破坏呢 当然我们在已知的情况下肯定不会这么干但如果发生了意外怎么办不妨来试一下
public class A11_EagerInitializedSingletonClone implements Cloneable {private static final A11_EagerInitializedSingletonClone instance new A11_EagerInitializedSingletonClone();// private constructor to avoid client applications to use constructorprivate A11_EagerInitializedSingletonClone() {}public static A11_EagerInitializedSingletonClone getInstance() {return instance;}Overridepublic A11_EagerInitializedSingletonClone clone() throws CloneNotSupportedException{A11_EagerInitializedSingletonClone employees (A11_EagerInitializedSingletonClone)super.clone();return employees;}
}A11_EagerInitializedSingletonClone instanceOne A11_EagerInitializedSingletonClone.getInstance();
A11_EagerInitializedSingletonClone instanceOne2 instanceOne.clone();
System.out.println(instanceOneinstanceOne2);结果为false确实创建了两个不同的对象。
实际上防止复制破坏单例对象的解决思路非常简单禁止复制便可。要么我们的单例类不实现Cloneable接口要么我们重写clone()方法在clone()方法中返回单例对象即可具体代码如下 Overridepublic A11_EagerInitializedSingletonClone clone() throws CloneNotSupportedException{return instance;}A11_EagerInitializedSingletonClone instanceOne A11_EagerInitializedSingletonClone.getInstance();
A11_EagerInitializedSingletonClone instanceOne2 instanceOne.clone();
System.out.println(instanceOneinstanceOne2);结果为true