两只羊是一模一样的(哪怕那只羊瘸腿)。让我们来看看代码。首先要注意的是Sheep类实现了Cloneable接口(该接口属于java.lang包,默认已经导入了),该接口中并没有定义要实现的方法,是个空接口,起标志作用。也就是说,实现了这个接口的羊就不再是只普通的羊,它是一只可以被克隆的羊。再往下看,有个clone方法,返回Object类型的对象,并抛出CloneNotSupportedException异常。
该方法覆写了父类(Object)的clone方法,并在最后调用了super.clone(),这也意味着无论clone类继承结构是什么样的,super.clone()都会直接或间接调用Object类的clone()方法。看看jdk帮助文档会发现,Object类的clone()是一个native方法,我们知道,native方法的效率一般来说都是远高于java中的非native方法。这也说明了new一个对象,然后将原对象中的数据导入到新创建的对象中去的做法是多么愚蠢。必须说明的是Object中的clone方法是protected的,所以要使用clone就必须继承Object类(默认)。并且为了可以使其它类调用该方法,必须将其作用域设置为public。
以上只是一个简单clone的实现。下面说说"影子clone"和"深度clone"。
何为影子clone?先看一下例子。
//倒霉的羊 public class Sheep implements Cloneable{ private String name; public void setName(String arg) { name = arg; } public String getName() { return name; } public Object clone() throws CloneNotSupportedException { return super.clone(); } } //羊圈 public class Sheepfold implements Cloneable { public Sheep sheep; public String name; public Sheepfold() { sheep = new Sheep(); } public Object clone() throws CloneNotSupportedException { return super.clone(); } } //克隆 public class Main { public static void main(String[] args) throws Exception { Sheepfold fold = new Sheepfold(); fold.name = "小羊圈"; fold.sheep.setName("小羊"); Sheepfold fold2 = (Sheepfold)fold.clone(); System.out.println(" fold2.name = " + fold2.name); System.out.println(" fold2.sheep.getName() = " + fold2.sheep.getName()); fold2.name = "大羊圈"; fold2.sheep.setName("大羊"); System.out.println("====================================="); System.out.println(" fold2.name = " + fold2.name); System.out.println("* fold2.sheep.getName() = " + fold2.sheep.getName()); System.out.println(" fold.name = " + fold.name); System.out.println("* fold.sheep.getName() = " + fold.sheep.getName()); System.out.println("====================================="); } }
|