java的clone()、浅拷贝与深拷贝
2017-03-21 17:32
323 查看
clone()方法是Object的native方法。protected native Object clone() throws CloneNotSupportedException; 声明为protected,表明子类必须重新实现该方法,除非是与Obeject类在一个包里,后者是不可能的。而实际上,作为native方法clone()已经有一份field to field的浅拷贝实现,实际上是不需要一定重写的。这种情况下,需要的做法就是覆写clone()方法,在方法里通过super.clone()调用Object的clone()。
而Cloneable是标记型接口,实现了Cloneable才可以实现clone()方法。否则使用clone()方法会报错。
下面是ArrayList的clone()
这里为何不是简单的super.clone()浅拷贝呢?因为成员变量是复杂类型时(涉及成员变量为对象的引用),就需要深拷贝。
下面做个小实验,先使用浅拷贝,验证普通的成员变量是ok的:
先设置ct0的v_a对象为66,然后ct1对象是ct0的拷贝,打印ct1的v_a,也为66,说明拷贝成功。 之后重新设置ct0的值为88,ct1的值没变还是66。
上面这个例子就体现出了浅拷贝的弱点,输出为66 88。
ct1是浅拷贝的ct0,此时ct0的v_a(成员变量,A对象)的v值为66。拷贝后,ct1的v_a(A对象的v)输出也是66。然后重设ct0的v_a(A对象的v)为88,再输出ct1的v_a(A对象的v),竟然也是88。说明二者的引用指向的是同样的堆内存。
浅拷贝情况下,两个对象的成员变量(A对象)引用的是同一个堆内存,并没有完全实现拷贝后内存独立。
这种情况就需要深拷贝。
例如文章最开始提到的ArrayList的clone()的写法。
而Cloneable是标记型接口,实现了Cloneable才可以实现clone()方法。否则使用clone()方法会报错。
下面是ArrayList的clone()
/** * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The * elements themselves are not copied.) * * @return a clone of this <tt>ArrayList</tt> instance */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } }
这里为何不是简单的super.clone()浅拷贝呢?因为成员变量是复杂类型时(涉及成员变量为对象的引用),就需要深拷贝。
下面做个小实验,先使用浅拷贝,验证普通的成员变量是ok的:
package a; public class CloneTest implements Cloneable { private int v_a; public void setV_a(int v) { v_a = v; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public void print_v_a() { System.out.println(v_a); } public static void main(String[] args) throws CloneNotSupportedException { CloneTest ct0 = new CloneTest(); ct0.setV_a(66); CloneTest ct1 = (CloneTest)ct0.clone(); ct1.print_v_a(); ct0.setV_a(88); ct1.print_v_a(); ct0.print_v_a(); } }
先设置ct0的v_a对象为66,然后ct1对象是ct0的拷贝,打印ct1的v_a,也为66,说明拷贝成功。 之后重新设置ct0的值为88,ct1的值没变还是66。
package a; import java.util.Arrays; class A { private int v; public void setV(int v) { this.v = v; } public void p_v() { System.out.println(v); } } public class CloneTest implements Cloneable { private A v_a; public void setV_a(A v) { v_a = v; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public void print_v_a() { v_a.p_v(); } public static void main(String[] args) throws CloneNotSupportedException { CloneTest ct0 = new CloneTest(); A a = new A(); a.setV(66); ct0.setV_a(a); CloneTest ct1 = (CloneTest)ct0.clone(); ct1.print_v_a(); a.setV(88); ct0.setV_a(a); ct1.print_v_a(); } }
上面这个例子就体现出了浅拷贝的弱点,输出为66 88。
ct1是浅拷贝的ct0,此时ct0的v_a(成员变量,A对象)的v值为66。拷贝后,ct1的v_a(A对象的v)输出也是66。然后重设ct0的v_a(A对象的v)为88,再输出ct1的v_a(A对象的v),竟然也是88。说明二者的引用指向的是同样的堆内存。
浅拷贝情况下,两个对象的成员变量(A对象)引用的是同一个堆内存,并没有完全实现拷贝后内存独立。
这种情况就需要深拷贝。
例如文章最开始提到的ArrayList的clone()的写法。
相关文章推荐
- java中的Clone(深拷贝,浅拷贝)
- java 深浅拷贝 clone
- java数组的拷贝四种方法:for、clone、System.arraycopy、arrays.copyof
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
- Java的一个高性能快速深拷贝方法。Cloneable?
- java基础之对象的clone(浅拷贝)
- 再谈java clone 以及 浅/深拷贝
- java问题探讨之clone浅拷贝与深拷贝
- java.util.ArrayList.clone()是浅层拷贝
- 浅拷贝和深拷贝(谈谈java中的clone)
- java 深浅拷贝 clone
- Java深拷贝除了通过实现Cloneable接口,另外还可以通过序列化实现对象的拷贝。
- Java的一个高性能快速深拷贝方法。Cloneable?
- java中的Clone(深拷贝,浅拷贝)
- Java中的clone() 深拷贝 浅拷贝
- Java中深拷贝(Deep Clone)与浅拷贝(Shallow Clone)
- Java的clone方法--深拷贝和浅拷贝
- Java&&Clone之浅拷贝和深拷贝
- Java 深拷贝、浅拷贝及Cloneable接口
- 五星-原型模式常使用于以下场景--而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝