现在先来看一下jdk给出的Object.clone源码和注释
/** * Creates and returns a copy of this object. The precise meaning * of "copy" may depend on the class of the object. The general * intent is that, for any object {@code x}, the expression: * <blockquote> * <pre> * x.clone() != x</pre></blockquote> * will be true, and that the expression: * <blockquote> * <pre> * x.clone().getClass() == x.getClass()</pre></blockquote> * will be {@code true}, but these are not absolute requirements. * While it is typically the case that: * <blockquote> * <pre> * x.clone().equals(x)</pre></blockquote> * will be {@code true}, this is not an absolute requirement. * <p> * By convention, the returned object should be obtained by calling * {@code super.clone}. If a class and all of its superclasses (except * {@code Object}) obey this convention, it will be the case that * {@code x.clone().getClass() == x.getClass()}. * <p> * By convention, the object returned by this method should be independent * of this object (which is being cloned). To achieve this independence, * it may be necessary to modify one or more fields of the object returned * by {@code super.clone} before returning it. Typically, this means * copying any mutable objects that comprise the internal "deep structure" * of the object being cloned and replacing the references to these * objects with references to the copies. If a class contains only * primitive fields or references to immutable objects, then it is usually * the case that no fields in the object returned by {@code super.clone} * need to be modified. * <p> * The method {@code clone} for class {@code Object} performs a * specific cloning operation. First, if the class of this object does * not implement the interface {@code Cloneable}, then a * {@code CloneNotSupportedException} is thrown. Note that all arrays * are considered to implement the interface {@code Cloneable} and that * the return type of the {@code clone} method of an array type {@code T[]} * is {@code T[]} where T is any reference or primitive type. * Otherwise, this method creates a new instance of the class of this * object and initializes all its fields with exactly the contents of * the corresponding fields of this object, as if by assignment; the * contents of the fields are not themselves cloned. Thus, this method * performs a "shallow copy" of this object, not a "deep copy" operation. * <p> * The class {@code Object} does not itself implement the interface * {@code Cloneable}, so calling the {@code clone} method on an object * whose class is {@code Object} will result in throwing an * exception at run time. * * @return a clone of this instance. * @throws CloneNotSupportedException if the object's class does not * support the {@code Cloneable} interface. Subclasses * that override the {@code clone} method can also * throw this exception to indicate that an instance cannot * be cloned. * @see java.lang.Cloneable */ protected native Object clone() throws CloneNotSupportedException;
克隆对象需要继承Cloneable接口并重写Object.clone()方法,看一下bean的代码
public class TestBean implements Cloneable{ private Long id; private String code; private String msg; private TestCloneBean testCloneBean = new TestCloneBean(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public TestCloneBean getTestCloneBean() { return testCloneBean; } public void setTestCloneBean(TestCloneBean testCloneBean) { this.testCloneBean = testCloneBean; } @Override protected TestBean clone() throws CloneNotSupportedException { return (TestBean)super.clone(); } }
克隆一个全新的对象,接下来看一下原本对象和新的克隆对象有什么区别
public static void main(String[] args) { try { TestBean bean = new TestBean(); TestBean copyBean = bean.clone(); System.out.println("==判断:" + (bean == copyBean)); System.out.println("class判断:" + (bean.getClass() == copyBean.getClass())); System.out.println("hasCode判断:" + (bean.hashCode() == copyBean.hashCode())); System.out.println("equals判断:" + (bean.equals(copyBean))); } catch (CloneNotSupportedException e) { e.printStackTrace(); } }
看一下结果
除了.getClass()相等,其余皆是不一样的,是一个全新的对象。
-----------------------------------------------------------分割线-----------------------------------------------------------
那克隆对象里面包含对象呢?我们来看一下
public class Test { public static void main(String[] args) { try { TestBean bean = new TestBean(); TestCloneBean testCloneBean = new TestCloneBean(1L,"1","测试"); bean.setTestCloneBean(testCloneBean); TestBean copyBean = (TestBean) bean.clone(); System.out.println("==判断:" + (bean.getTestCloneBean() == copyBean.getTestCloneBean())); System.out.println("class判断:" + (bean.getTestCloneBean().getClass() == copyBean.getTestCloneBean().getClass())); System.out.println("hasCode判断:" + (bean.getTestCloneBean().hashCode() == copyBean.getTestCloneBean().hashCode())); System.out.println("equals判断:" + (bean.getTestCloneBean().equals(copyBean.getTestCloneBean()))); System.out.println("bean:{"+bean.getTestCloneBean().toString()+"}"); System.out.println("bean:{"+copyBean.getTestCloneBean().toString()+"}"); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
#1 属性testCloneBean未重写clone方法,结果是
#2 当对象属性也重写了clone方法后
@Override public TestCloneBean clone() throws CloneNotSupportedException { return (TestCloneBean) super.clone(); }
结果是
很诧异,还是原来的地址,说明对象属性是没有被克隆的,那是不是对象没有序列化呢?等我加上序列化试一下
额~事实证明,序列化还是一样的,被克隆的对象属性是一样的!