注:玩的是JDK1.7版本java
一:Cloneable.java 接口也是标记接口,因此,它没有任何方法和属性,实现此接口表示的意思是:能够调用 Object.java 类的 clone() 方法,进行简单的属性到属性之间的克隆,若是没有实现此接口的话调用 Object.java 类的 clone() 方法会抛出 java.lang.CloneNotSupportedException 异常。express
另外,若是实现了 Cloneabel.java 接口,一般会复写 Object.java 的 clone() 方法,由于,在 Object.java 中 clone() 方法是受保护的,因此,须要提供一个public的 clone() 方法。app
package java.lang; /** * A class implements the <code>Cloneable</code> interface to * indicate to the {@link java.lang.Object#clone()} method that it * is legal for that method to make a * field-for-field copy of instances of that class. * <p> * Invoking Object's clone method on an instance that does not implement the * <code>Cloneable</code> interface results in the exception * <code>CloneNotSupportedException</code> being thrown. * <p> * By convention, classes that implement this interface should override * <tt>Object.clone</tt> (which is protected) with a public method. * See {@link java.lang.Object#clone()} for details on overriding this * method. * <p> * Note that this interface does <i>not</i> contain the <tt>clone</tt> method. * Therefore, it is not possible to clone an object merely by virtue of the * fact that it implements this interface. Even if the clone method is invoked * reflectively, there is no guarantee that it will succeed. * * @author unascribed * @see java.lang.CloneNotSupportedException * @see java.lang.Object#clone() * @since JDK1.0 */ public interface Cloneable { }
二:验证上述结论ide
1)定义一个简单的类,特地不实现 Cloneabel.java 接口,以下所示:测试
/** * @description:人类 * @author:godtrue * @create:2018-09-09 */ public class Person{/** 请注意这里,没有实现 Cloneable 接口 **/ /** * 身份证号 */ private int id; /** * 姓名 */ private String name; /** * 性别 */ private boolean sex; /** * 年龄 */ private int age; /** * *@description: 复写 Object.java 的克隆方法 *@param *@return: java.lang.Object *@author: godtrue *@createTime: 2018-09-18 *@version: v1.0 */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isSex() { return sex; } public void setSex(boolean sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Person{"); sb.append("id=").append(id); sb.append(", name='").append(name).append('\''); sb.append(", sex=").append(sex==true?"男":"女"); sb.append(", age=").append(age); sb.append('}'); return sb.toString(); } }
2)定义一个测试入口类,以下所示:ui
/** * @description:玩一把Cloneable * @author:godtrue * @create:2018-09-18 */ public class PlayCloneable { /** * *@description: 测试入口,主方法 *@param args *@return: void *@author: godtrue *@createTime: 2018-09-18 *@version: v1.0 */ public static void main(String[] args) throws CloneNotSupportedException{ Person person = genPerson(); System.out.println("person is "+person); Person personTemp = (Person) person.clone(); personTemp.setId(618); personTemp.setName("六一八"); System.out.println("personTemp is "+personTemp); } /** * *@description: 生成 Person 对象信息 *@param *@return: com.godtrue.Person *@author: godtrue *@createTime: 2018-09-18 *@version: v1.0 */ private static Person genPerson(){ Person person = new Person(); person.setId(1111); person.setSex(true); person.setName("双十一"); person.setAge(2); return person; } }
3)测试的结果以下所示(果真,抛出了对应的异常,侧面反映出咱们的结论了:没实现Cloneable.java接口时,调用 Object.java 类的 clone() 方法会抛出 java.lang.CloneNotSupportedException 异常):this
4)调整 Person.java 类 使其实现 Cloneable.java 接口,而后再实验下,看看什么效果,调整的类以下所示:spa
/** * @description:人类 * @author:godtrue * @create:2018-09-09 */ public class Person implements Cloneable{/** 请注意这里,实现了 Cloneable 接口 **/ /** * 身份证号 */ private int id; /** * 姓名 */ private String name; /** * 性别 */ private boolean sex; /** * 年龄 */ private int age; /** * *@description: 复写 Object.java 的克隆方法 *@param *@return: java.lang.Object *@author: godtrue *@createTime: 2018-09-18 *@version: v1.0 */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isSex() { return sex; } public void setSex(boolean sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Person{"); sb.append("id=").append(id); sb.append(", name='").append(name).append('\''); sb.append(", sex=").append(sex==true?"男":"女"); sb.append(", age=").append(age); sb.append('}'); return sb.toString(); } }
5)运行结果以下所示(正面反映出了咱们的结论:当实现Cloneable.java接口时,可以正常调用 Object.java 类的 clone() 方法):code
三:为何会这样呢?orm
1)先看以下的变种例子,注意 clone() 方法的实现,以下所示
/** * @description:人类 * @author:godtrue * @create:2018-09-09 */ public class Person{/** 请注意这里,没有实现 Cloneable 接口 **/ /** * 身份证号 */ private int id; /** * 姓名 */ private String name; /** * 性别 */ private boolean sex; /** * 年龄 */ private int age; /** * *@description: 复写 Object.java 的克隆方法 *@param *@return: java.lang.Object *@author: godtrue *@createTime: 2018-09-18 *@version: v1.0 */ @Override public Object clone(){ Person copy = new Person(); copy.id = this.id; copy.name = this.name; copy.sex = this.sex; copy.age = this.age; return copy; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isSex() { return sex; } public void setSex(boolean sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Person{"); sb.append("id=").append(id); sb.append(", name='").append(name).append('\''); sb.append(", sex=").append(sex==true?"男":"女"); sb.append(", age=").append(age); sb.append('}'); return sb.toString(); } }
2)运行结果以下所示,注意,不用处理 java.lang.CloneNotSupportedException 由于,咱们的 Person.java 的 clone() 方法没用使用 Object.java 的 clone() 方法
3)看一下 Object.java 的 clone() 方法,从注释中咱们能够得出以下关键信息
3-1)Object.java 的 clone() 方法是一个 native 方法
3-2)经过 Object.java 的 clone() 方法获取的新对象是一个浅克隆的对象,打个比方:有点相似两个连体双胞胎的关系(这个回头再细说)
3-3)针对没有实现 Cloneable.java 接口的类,若是复写了 Object.java 类的 clone() 方法,且经过 Object.java 类的 clone() 方法实现了对象的浅克隆的话,在调用复写的 clone() 方法的时候,就会抛出 java.lang.CloneNotSupportedException 异常,由于,Object.java 类的 clone() 方法抛出了此异常,因此,对应的应该有捕获或者再抛出的措施才行,(Object.java 类的 clone() 方法的本地实现我还没看,猜想,他会先检查对应的类是否实现了Cloneabe.java接口,若是没有,则会抛出 java.lang.CloneNotSupportedException 异常,若是实现了,则会进行对对象的浅克隆操做)
3-4)复写 Object.java 的 clone() 方法,和是否实现 Cloneable.java 接口没有什么必然关系,复写的 clone() 方法的实现,能够有多种选择,可是一旦选择使用 Object.java 类的 clone() 方法来快速实现一个对象的浅克隆的话,就必须实现 Cloneable.java 接口,不然就会抛出 java.lang.CloneNotSupportedException 异常
3-5)至此,咱们也清楚了,Cloneable.java 接口的核心做用在于,可经过 Object.java 类的 clone() 方法进行对象的快速浅克隆,具体实现步骤以下所示:
第一步:实现Cloneable.java接口
第二步:复写Object.java类的clone()方法,使方法处处可用(public的访问权限),调用Object.java类的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. * @exception 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;
4)看一下 java.lang.CloneNotSupportedException.java 的存在本意,不实现 Cloneable.java 接口,可是调用了 Object.java 类的 clone() 方法就会抛出此异常了
/** * Thrown to indicate that the <code>clone</code> method in class * <code>Object</code> has been called to clone an object, but that * the object's class does not implement the <code>Cloneable</code> * interface. * <p> * Applications that override the <code>clone</code> method can also * throw this exception to indicate that an object could not or * should not be cloned. * * @author unascribed * @see java.lang.Cloneable * @see java.lang.Object#clone() * @since JDK1.0 */ public class CloneNotSupportedException extends Exception { private static final long serialVersionUID = 5195511250079656443L; /** * Constructs a <code>CloneNotSupportedException</code> with no * detail message. */ public CloneNotSupportedException() { super(); } /** * Constructs a <code>CloneNotSupportedException</code> with the * specified detail message. * * @param s the detail message. */ public CloneNotSupportedException(String s) { super(s); } }