深入 JAVA对象的复制与比较

本文介绍了Java中对象的复制方法,包括浅复制与深复制的区别,clone()方法的使用及注意事项。同时探讨了如何通过equals方法进行对象实例的有效比较。

1.对象的复制

2.clone()的使用

3.对象实例的比较

////////////////////

//

/////////////////////

1.对象的复制

  1. Stringstr1="Thisisastring!"//这里是"对象引用"的复制
  2. Stringstr2=newString(str1);//这里是"对象实例"的复制

浅复制:只复制复合对象本身.

深复制:除了复制复合对象本身,还复制了复合对象的引用的对象实例.

例如:

  1. classPupil{
  2. publicPupil(Stringsno,Stringname,intage){
  3. this.sno=newString(sno);
  4. this.name=newString(name);
  5. this.age=age;
  6. }
  7. publicStringgetSno(){
  8. returnsno;
  9. }
  10. publicStringgetName(){
  11. returnname;
  12. }
  13. publicintgetAge(){
  14. returnage;
  15. }
  16. publicvoidsetAge(intage){
  17. this.age=age;
  18. }
  19. privateStringsno;
  20. privateStringname;
  21. privateintage;
  22. }
  23. publicclassCopyDemo{
  24. publicstaticPupil[]shallowCopy(Pupil[]aClass){
  25. Pupil[]newClass=newPupil[aClass.length];
  26. //此时newClass与aClass指向同一块内存
  27. for(inti=0;i<aClass.length;i++)
  28. newClass[i]=aClass[i];
  29. returnnewClass;
  30. }
  31. publicstaticPupil[]deepCopy(Pupil[]aClass){
  32. Pupil[]newClass=newPupil[aClass.length];
  33. //此时newClass与aClass的相应sno,name指向同一块内存
  34. for(inti=0;i<aClass.length;i++){
  35. Stringsno=aClass[i].getSno();
  36. Stringname=aClass[i].getName();
  37. intage=aClass[i].getAge();
  38. newClass[i]=newPupil(sno,name,age);
  39. }
  40. returnnewClass;
  41. }
  42. publicstaticPupil[]deeperCopy(Pupil[]aClass){
  43. Pupil[]newClass=newPupil[aClass.length];
  44. //完全的复制
  45. for(inti=0;i<aClass.length;i++){
  46. Stringsno=newString(aClass[i].getSno());
  47. Stringname=newString(aClass[i].getName());
  48. intage=aClass[i].getAge();
  49. newClass[i]=newPupil(sno,name,age);
  50. }
  51. returnnewClass;
  52. }
  53. }

2.clone()的使用

*Object.clone()

*Cloneable接口

*CloneNotSupportedException

a.使用Object.clone进行复制

两个必须条件:

1.一定要将重定义后的clone()方法定义为公有方法(在Object类中,它是受保护的成员,不能直接使用)

2.该后代类声明实现接口Cloneable接口(当类实现该接口,其任何子类也会继承该接口),该接口实际上没有任何

内容,只是一个标识,标志实现该接口的类提供clone()方法.(这是接口的一种非典型用法)

  1. publicclassFractionimplementsCloneable{
  2. publicObjectclone(){
  3. try{
  4. returnsuper.clone();//callprotectedmethod
  5. }catch(CloneNotSupportedExceptione){
  6. returnnull;
  7. }
  8. }
  9. //othermethods...
  10. }

b.重写Object.clone()

例如对privatechar[]cb;characterbuffer进行复制

  1. //addinclassCirbuf
  2. publicObjectclone(){
  3. try{
  4. Cirbufcopy=(Cirbuf)super.clone();
  5. copy.cb=(char[])cb.clone();
  6. returncopy;
  7. }catch(CloneNotSupportedExceptione){
  8. thrownewInternalError(e.toString());
  9. }
  10. }

c.复制数组

数组是在方法调用重以引用的形式传递的对象.下述情况下非常适合引用来传递数组:

*正在接收的方法不修改数组

*正在调用的方法不必关心是否修改数组

*正在调用的方法想要得到数组中的修改结果

否则,就应该在方法调用中传递数组对象的副本.只需调用arrObj.clone()方法即可完成数组arrObj的复制操作.随后将该数组副本强制转换为其正确类型:

(type[])arrObj.clone();

System.arraycopy方法提供一种用于在数组间复制多个元素的有效方式.

System.arraycopy(source,i,target,j,len)

3.对象实例的比较

例如:

  1. Pupilp1=newPupil("99184001","zhang3",18);
  2. Pupilp2=newPupil("99184001","zhang3",18);

a."=="

if(p1==p2)...

此次测试的是对象引用,其结果肯定是false,只要两个对象引用不是互为别名就不会相等.

b.浅比较false

  1. if(p1.getSno()==p2.getSno()&&p1.getName()==p2.getName()
  2. &&p1.getAge()==p2.getAge())...;

c.深比较true[/code]

if(p1.getSno().equals(p2.getSno())&&p1.getName().equals(p2.getName())

&&p1.getAge()==p2.getAge())...;[/code]

JAVAAPI的跟类Object也提供了equals()方法,但它只是比较两个对象引用,而非比较两个对象实例.

不管怎样,如果需要比较Pupil类的对象(例如要将它们放入对象容器),应该为Pupil类重定义equals()方法:

  1. publicbooleanequals(Objectotherobj){
  2. //检查otherobj是否为空
  3. if(otherobj==null)returnfalse;
  4. //检查otherobj是否就是当前对象
  5. if(otherobj==this)returntrue;
  6. //检查otherobj是否具有正确的类型,即检查是否可与当前对象比较
  7. if(!(otherobjinstanceofPupil))returnfalse;
  8. //将otherobj转换为Pupil类的对象引用
  9. PupiltmpObj=(Pupil)otherobj;
  10. //关于学生是否相等的逻辑检查
  11. if(sno.equals(tmpObj.sno)&&name.equals(tmpObj.name)
  12. &&age==tmpObj.age)returntrue;
  13. returnfalse;
  14. }

JAVAAPI所提供的每个类几乎都提供了采用深比较策略的equals()方法,例如String类equals()方法.一般来说,用户自己定义的类也应当提供合适的equals()方法,特别是当程序要将其对象放入JAVAAPI所提供的对象容器类的时候.

按照约定,任何类所提供的equals()方法所实现的相等比较应该是等价关系,即满足自反性,对称性和传递性.另外一个类重定义了equals()方法,也应该重定义相应hashCode()方法,否则将这个类的对象放入映射对象容器时也会发生以外.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值