首页编程java编程java什么是克隆?java代码 clone()函数的作用是什么

java什么是克隆?java代码 clone()函数的作用是什么

编程之家 2023-10-14 123次浏览

大家好,今天给各位分享java什么是克隆的一些知识,其中也会对java代码 clone()函数的作用是什么进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!

java什么是克隆?java代码 clone()函数的作用是什么

简述java中引用和克隆的区别

深克隆与浅克隆

大家知道,对象是互相引用的,即对象中可能包含了另一个对象的引用,举例如:有一个Order对象,Order对象中又包含了LineItems对象,然后LineItems对象又包含了Item对象。

好了,现在我有一个Order对象order1,它包含了一个LineItems对象items,这表示的是有一个订单order1,订单的内容是items。

java什么是克隆?java代码 clone()函数的作用是什么

好的,现在有另一个客户想要一份订单,内容跟order1完全一样,那么在系统的逻辑层我们怎么做呢?很简单,order2=order1.clone().我们知道clone方法是在内存中生成一个新的对象,而不是只得到原对象的引用。这时候,有人说话了:“哦,明白了我们对order2的成员变量进行修改,是不会影响order1的。”很可惜,这句话只对了一半。

假设order类有一个成员变量name,当然改变order2.name不会影响order1.name,因为他们在不同的内存区域。但是如果改变 order1.items呢?很遗憾,简单地使用order1.clone,是会影响到order2.items的。原因很简单,就是因为clone方法默认的是浅克隆,即不会克隆对象引用的对象,而只是简单地复制这个引用。所以在上例中,items对象在内存中只有一个,order1和order2都指向它,任何一个对象对它的修改都会影响另一个对象。

那相对浅克隆,深克隆自然就是会克隆对象引用的对象了。也就是说,在上例中,改变order1.items并不会影响order2.items了。因为内存中有两个一样的items。

java什么是克隆?java代码 clone()函数的作用是什么

如果实现深克隆?

一个方法自然是重写clone方法,添加如order.items=(LineItems)items.clone()的语句,也就是人为地添加对引用对象的复制。这个方法的缺点是如果引用对象有很多,或者说引用套引用很多重,那么太麻烦了。业界常用的方法是使用串行化然后反串行化的方法来实现深克隆。由于串行化后,对象写到流中,所有引用的对象都包含进来了,所以反串行化后,对等于生成了一个完全克隆的对象。绝!

这个方法的要求是对象(包括被引用对象)必须事先了Serializable接口,否则就要用transient关键字将其排除在复制过程中。

详细讲述Java中的克隆

经常听到有人说java中没有指针事实如此吗?no java是有指针的只不过换了个名字而已也就是我们经常提到的引用我们知道在java中一切都是对象那么我们如何操控对象?如何在成千上万的对象中找到我们所需的那个对象呢?又是如何让对象按照我们的意思来完成任务的呢?

Object o= new Object()

这是java中最常见的语句了在这句话中做了三件事首先声明一个Object类型的变量o在内存中为对象划分一块地址new Object()将声明的变量指向内存中的对象如此一来我们就可以通过o来操纵对象了就好像孩子们玩的遥控飞机在空中飞行的是飞机而使它做出优美动作的却是孩子们手中的摇控器

克隆是如今听到的较多的词汇听说已经将某只羊克隆了好几份了但愿这种技术不要在人身上实验 java中也有克隆与现实世界的克隆一样将一个实际存在的对象拷贝几份如下

//倒霉的羊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 Main{public static void main(String[] args) throws CloneNotSupportedException{Sheep sheep= new Sheep();//先得到那只羊的实例sheep setName(我是真的);//给它做个记号System out println( sheep getName()=+ sheep getName());Sheep sheepClone=(Sheep)sheep clone();//开始克隆System out println( sheepClone getName()=+ sheepClone getName());}}

运行程序结果为

sheep getName()=我是真的

sheepClone getName()=我是真的

两只羊是一模一样的(哪怕那只羊瘸腿)让我们来看看代码首先要注意的是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 fold=(Sheepfold)fold clone();System out println( fold name=+ fold name);System out println( fold sheep getName()=+ fold sheep getName());fold name=大羊圈;fold sheep setName(大羊);System out println(=====================================);System out println( fold name=+ fold name);System out println(* fold sheep getName()=+ fold sheep getName());System out println( fold name=+ fold name);System out println(* fold sheep getName()=+ fold sheep getName());System out println(=====================================);}}

在这个例子中有三个类 Sheep和Sheepflod都实现了Cloneable接口并且覆写了Object类的clone方法说明这两个类是具有克隆能力的注意一点在Sheepflod中持有一个Sheep的实例并在Main类中对其进行克隆结果如下

fold<fp class='bchome-45f2-1182-8ea3-df5a fp-3p43k'></fp><fp class='bchome-1182-8ea3-df5a-8611 fp-6kh1w'></fp>name=小羊圈fold<fp class='bchome-8ea3-df5a-8611-8db2 fp-3p43k'></fp><fp class='bchome-df5a-8611-8db2-c24a fp-szkq0'></fp>sheep<fp class='bchome-8611-8db2-c24a-a572 fp-6kh1w'></fp>getName()=小羊=====================================fold<fp class='bchome-1108-0236-0351-1ce7 fp-4kby3'></fp><fp class='bchome-0236-0351-1ce7-957a fp-5w0yq'></fp>name=大羊圈* fold<fp class='bchome-0351-1ce7-957a-2d0d fp-3p43k'></fp><fp class='bchome-1ce7-957a-2d0d-b093 fp-5w0yq'></fp>sheep<fp class='bchome-957a-2d0d-b093-8456 fp-y11o7'></fp>getName()=大羊fold<fp class='bchome-2d0d-b093-8456-e2ed fp-5w0yq'></fp>name=小羊圈* fold<fp class='bchome-b093-8456-e2ed-968b fp-y11o7'></fp>sheep<fp class='bchome-8456-e2ed-968b-45f2 fp-5w0yq'></fp>getName()=大羊=====================================

请注意一下结果中带有*号的两条结果语句 fold sheep和fold sheep的name都变为了大羊很奇怪是吗?在此之前我们只对fold sheep的name赋过值为什么fold sheep的name也变为了大羊呢?原因很简单因为它们是指向同一个对象的不同引用从中可以看出调用Object类中clone()方法时首先在内存中划分一块同原对象相同的空间然后将原对象的内容原样拷贝至新对象我们知道 java中有基本数据类型对于基本数据类型这样的操作是没有问题的但对非基本类型变量它们保存的仅仅是对象的引用这也是为什么clone后非基本类型变量和原对象中的变量指向同一个对象的原因可能你已经注意到程序中用到了String类型即对象为什么没有出现引用指向同一地址的情况?这是因为String是一个不可更改的类(immutable class)每次给它赋值时都会产生一个新的String对象如 String str= a str+= b在这两句代码中当执行str+= b时实际上是重新成生了一个值为 ab的 String对象即重新分配了一块内存空间以上clone方法通常被称为影子clone影子clone给我们留下了一个问题即多个引用指向同一个对象如何解决该问题呢?答案为深度clone把上面的例子改成深度clone很简单只需将Sheepfold的clone()方法改为如下即可很简单只需将Sheepfold的clone()方法改为如下即可

public Object clone() throws CloneNotSupportedException{Sheepfold fold=(Sheepfold)super clone();sheep=(Sheep)fold sheep clone();return fold;}

lishixinzhi/Article/program/Java/gj/201311/27342

java代码 clone()函数的作用是什么

从楼主对回答的追问上发现,楼主的连JAVA基本的语法都很差啊。=号是赋值运算符,不是比较。

double[] vectorValue;

vectorValue= vectorValue.clone();

这个段代码执行肯定报错了。但他还的意思还是很明确的。

首先:double[] vectorValue;这个是定义了一个double类型的数组变量vectorValue。

其次:vectorValue= vectorValue.clone();//这个是将vectorValue克隆一份,赋值给自己。也就是说vectorValue变量指向了新的一块内存区域。

举个例子可能更能说明问题。

publicclassTestMainimplementsCloneable{

privateinti;

publicTestMain(inti){

this.i=i;

}

@Override

protectedObjectclone(){

//TODOAuto-generatedmethodstub

returnnewTestMain(this.getI()+1);

}

publicintgetI(){

returni;

}

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

//TODOAuto-generatedmethodstub

TestMaintm1=newTestMain(1);

TestMaintm2=tm1;

tm1=(TestMain)tm1.clone();

System.out.println(tm1.getI());//tm1指向的是通过clone()方法创建的新的对象的地址,i的值已经是2了。

System.out.println(tm2.getI());//tm2指向的还是tm1创建时的地址,i的值为1

}

}

好了,文章到此结束,希望可以帮助到大家。

手机javascript是什么意思 手机里的启用JavaScript是什么意思,不启用会怎样 学习java需要安装什么?学JAVA编程都要下什么软件