clone()可以对对象进行clone,通常我们会想要使用它去克隆一个对象,并且希望改变一个对象所以用的对象,不会对他的克隆体产生影响。
首先看一下clone的源码:
public class Object {
···
protected native Object clone() throws CloneNotSupportedException;
···
}
从中可以看到三个问题:
第一:Object类的clone()方法是一个native方法,native方法的效率一般来说都是远高于Java中的非native方法。
第二:Object中的clone()方法被protected修饰符修饰,这意味着子类只能调用受保护的clone方法克隆他自己,而无法在一个类里面克隆另一个类。而且,直接调用Object的clone实现的仅仅是浅克隆,为此,必须在子类中重新定义clone方法,并将它声明为public,这样可以就可以在任何地方实现满足我们需求的(深克隆或者浅克隆)对象的克隆。
第三:Object的clone()返回的是一个Object对象。
第四:Object在这里没有提供任何基础实现,同时看Cloneable接口,java规定如果没有实现该接口,那么我们试图调用clone方法会抛出 java.lang.CloneNotSupportedException错误,所以我们可以看出clone是个特殊的方法。。他的基础克隆是怎么实现的,我们并不知道,只知道super.clone()方法返回的是一个原对象的浅克隆Object。
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 {
}
关于浅克隆与深克隆:
浅克隆:浅克隆是指仅仅按值进行克隆,对于对象,相当于被克隆者与克隆者有着相同的引用。
深克隆:所有变量有着与原来对象相同的值,对于引用其他对象的变量将会指向一个新的被复制的对象。
关于第二点中的protected修饰符:
protected修饰符的访问权限有些微妙,是本包和它的子类,但是有一点需要注意的是如果有两个类都是另一个类的子类,那么其中一个子类是不能在另一个子类中直接访问父类中的protected方法的
解决三个问题我们需要:
1.在子类中实现Cloneable接口
2.在子类中重载clone,并将他声明为public
3.在子类中调用super.clone(),然后根据需求,自定义子类的clone方法。
Core java中的clone()方法示例:
@Override
public Employee clone() throws CloneNotSupportedException {
Employee e1 = (Employee) super.clone();
e1.hireDay = (Date) hireDay.clone();
return e1;
}
测试结果:
public static void main(String[] args) throws CloneNotSupportedException {
Employee e1 = new Employee("Tom", 2000, 1996, 5, 2);
Employee e2 = (Employee) e1.clone();
System.out.println(e2.getName());
e2.setName("Ted");
System.out.println(e1.getName());
System.out.println(e2.getName());
System.out.println(e1.getHireDay()); //Thu May 02 00:00:00 CST 1996
System.out.println(e2.getHireDay()); //Thu May 02 00:00:00 CST 1996
e1.getHireDay().setMonth(10);
System.out.println(e1.getHireDay()); //Sat Nov 02 00:00:00 CST 1996
System.out.println(e2.getHireDay()); //Thu May 02 00:00:00 CST 1996
}
网友评论