1 重点关注
1.1 使用场景
除非拷贝数组,或者做系统镜像相关,有些专家级的程序员从来不去覆盖clone方法,也从来不去调用它。
1.2 参考原型模式
https://www.cnblogs.com/1446358788-qq/p/11456714.html
1.3 奇怪
深拷贝的递归方法的使用
2 课程目的
3 代码演练
3.1 克隆覆盖_如果每个域中包含一个基本类型的值,或者指向一个不可变对象的引用。
package com.ddwei.test.core.chapter11.demo1; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @Slf4j public class PhoneNumber implements Cloneable{ @Override public PhoneNumber clone(){ try { return (PhoneNumber) super.clone(); } catch (CloneNotSupportedException e) { //打印堆栈信息 log.error(JSON.toJSONString(e)); throw new Error(); } } }
3.2 克隆覆盖_对象包含域中引入了可变对象
package com.ddwei.test.core.chapter11.demo2; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import java.util.Arrays; import java.util.EmptyStackException; @Slf4j public class Stack3 implements Cloneable{ private Object[] elements; private static final int DEFALUT_INITIAL_CAPACITY = 16; private int size = 0; public Stack3(){ elements = new Object[DEFALUT_INITIAL_CAPACITY ]; } /** * 栈移入元素 * @author weidoudou * @date 2022/6/27 12:52 * @param obj 请添加参数描述 * @return void **/ public void push(Object obj){ // ensurCapacity(); elements[size++] = obj; } /** * 栈移除元素 * @author weidoudou * @date 2022/6/27 12:51 * @param * @return java.lang.Object **/ public Object pop(){ if(size == 0){ throw new EmptyStackException(); } Object result = elements[--size]; elements[size] = null; return result; } /** * 预先设置数组的大小,每次数组元素不够的时候,进行扩充两倍 * @author weidoudou * @date 2022/6/27 12:49 * @param * @return void **/ public void ensurCapacity(){ if(elements.length == size){ elements = Arrays.copyOf(elements,2*size+1); } } /** * 克隆方法就是另一个构造器,你必须确保它不伤害到原始对象,并确保正确的创建被克隆对象中的约束条件。 * 为了使Stack类中的clone方法正常工作,必须要拷贝栈的内部信息,最容易的做法是,在elements数组中递归的调用clone * @author weidoudou * @date 2022/9/5 13:15 * @param * @return com.ddwei.test.core.chapter11.demo2.Stack3 **/ @Override public Stack3 clone(){ try { Stack3 stack3 = (Stack3)super.clone(); stack3.elements = elements.clone(); return stack3; } catch (CloneNotSupportedException e) { log.error(JSON.toJSONString(e)); throw new Error(); } } }
3.3 克隆覆盖_避免浅拷贝 出现修改克隆对象,源对象受到影像
package com.ddwei.test.core.chapter11.demo3; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; @Slf4j public class HashTable implements Cloneable{ private Entry[] buckets; private static class Entry{ final Object key; Object value; Entry next; Entry(Object key,Object value,Entry next){ this.key = key; this.value = value; this.next = next; } Entry deepCopy(){ return new Entry(key,value,next==null?null:next.deepCopy()); } } @Override public HashTable clone(){ try { HashTable result = (HashTable) super.clone(); result.buckets = new Entry[buckets.length]; for(int i = 0;i< buckets.length;i++){ if(buckets[i]!=null){ result.buckets[i] = buckets[i].deepCopy(); } } return result; } catch (CloneNotSupportedException e) { log.error(JSON.toJSONString(e)); throw new Error(); } } }
3.4 克隆覆盖_避免递归调用容易造成的堆栈溢出等问题,直接使用迭代调用深拷贝
package com.ddwei.test.core.chapter11.demo4; import com.alibaba.fastjson.JSON; import com.ddwei.test.core.chapter11.demo3.HashTable; import lombok.extern.slf4j.Slf4j; @Slf4j public class HashTable2 { private Entry[] buckets; private static class Entry{ final Object key; Object value; Entry next; Entry(Object key, Object value, Entry next){ this.key = key; this.value = value; this.next = next; } Entry deepCopy(){ Entry result = new Entry(key,value,next); for(Entry p=result; p.next!=null ;p=p.next){ p.next = new Entry(p.next.key,p.next.value,p.next.next); } return result; } } @Override public HashTable2 clone(){ try { HashTable2 result = (HashTable2) super.clone(); result.buckets = new Entry[buckets.length]; for(int i = 0;i< buckets.length;i++){ if(buckets[i]!=null){ result.buckets[i] = buckets[i].deepCopy(); } } return result; } catch (CloneNotSupportedException e) { log.error(JSON.toJSONString(e)); throw new Error(); } } }
诸葛