请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

猿媛之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 5942|回复: 0

Java面试必考-clone方法有什么作用?

[复制链接]

554

主题

556

帖子

1938

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1938
发表于 2016-2-28 22:41:21 | 显示全部楼层 |阅读模式
由于指针的存在不仅会给开发人员带来不便,同时也是造成程序不稳定的根源,为了消除C/C++语言的这些缺点,Java语言取消了指针的概念,但这只是在Java语言中没有明确提供指针的概念与用法,而实质上每个new语句返回的都是一个指针的引用,只不过在大部分情况下开发人员不需要关心如何去操作这个指针而已。
由于Java取消了指针的概念,所以开发人员在编程中往往忽略了对象和引用的区别。如下例所示:
class  Obj{
         public void setStr(String str) {
                   this.str = str;
         }
         private String str = "default  value";
         public String toString(){
                   return str;
}
}
public  class TestRef{
         private Obj aObj = new Obj();
         private int aInt = 0;
         public Obj getAObj() {
                   return aObj;
         }
         public int getAInt() {
                   return aInt;
         }
         public void changeObj(Obj inObj){
                   inObj.setStr( "changed  value");
         }
         public void changeInt(int inInt){
                   inInt = 1;
         }
         public static void main(String[]  args)
         {
                   TestRef oRef = new  TestRef();
         
                   System.out.println("*******************引用类型*******************");
                   System.out.println("调用changeObj(): "  + oRef.getAObj());
                   oRef.changeObj(oRef.getAObj());  
                   System.out.println("调用 changeObj(): "  + oRef.getAObj());
                  
                   System.out.println("*******************基本数据类型*******************");
                   System.out.println("调用 changeInt(): "  + oRef.getAInt());
                   oRef.changeInt(oRef.getAInt());  
                   System.out.println("调用changeInt(): "  + oRef.getAInt());
         }
}
上述代码的输出结果为:
*******************引用类型*******************
调用changeObj():  default value
调用 changeObj():  changed value
*******************基本数据类型*******************
调用 changeInt(): 0
调用changeInt(): 0
上面两个看似类似的方法却有着不同的运行结果,主要原因是Java在处理基本数据类型(例如int、char、double等)的时候,都是采用按值传递(传递的是输入参数的拷贝)的方式,除此之外的其它类型都是按引用传递(传递的是对象的一个引用)的方式执行。对象除了在函数调用的时候是引用传递,在使用“=”赋值的时候也采用引用传递,示例代码如下。
class  Obj {
         private int aInt=0;

         public int getAInt() {
                   return aInt;
         }
         public void setAInt(int int1) {
                   aInt = int1;
         }
         public void changeInt(){
                   this.aInt=1;
         }
}
public  class TestRef{
         
         public static void main(String[]  args)
         {
                   Obj a=new Obj();
                   b=a;
                   b.changeInt();
                   System.out.println("a:"+a.getAInt());
                   System.out.println("b:"+b.getAInt());
         }
}
上述代码的运行结果为:
a:1
b:1
       在实际的编程中,经常会遇到从某个已有的对象A创建出另外一个与A具有相同状态的对象B,并且对B的修改不会影响到A的情况,例如Prototype原型)模式中,就需要clone一个对象实例。在Java语言中,仅仅通过简单的赋值操作显然无法达到这个目的,而Java提供了一个简单且有效的clone方法能够满足这个需求。
       Java中所有的类默认都继承自Object类,而Object类中提供了一个clone方法。这个方法的作用是返回一个Object对象的拷贝。这个拷贝函数返回的是一个新的对象而不是一个引用。那么怎样使用这个方法呢?以下是使用clone方法的步骤。
  • 实现clone的类首先需要继承Cloneable接口。Cloneable接口实质上是一个标识接口,没有任何接口方法。
  • 在类中重写Object类中的clone方法。
  • 在clone方法中调用super.clone()。无论clone类的继承结构是什么,super.clone()都会直接或间接调用java.lang.Object类的clone()方法。
  • 把浅拷贝的引用指向原型对象新的克隆体。

       对上面的例子引入clone方法如下:
class Obj implements Cloneable{
       private int aInt=0;
       public int getAInt() {
              return aInt;
       }
       public void  setAInt(int int1) {
              aInt = int1;
       }
       public void  changeInt(){
              this.aInt=1;
       }
       public Object clone()  {
              Object o=null;
              try {
                     o =  (Obj)super.clone();
              } catch  (CloneNotSupportedException e) {
                     e.printStackTrace();
              }
              return o;
       }
}
public class TestRef{
       public static void  main(String[] args)
       {
              Obj a=new  Obj();
              Obj  b=(Obj)a.clone();
              b.changeInt();
              System.out.println("a:"+a.getAInt());
              System.out.println("b:"+b.getAInt());
       }
}
程序运行结果为:
a:0
b:1
C++语言中,当开发人员自定义拷贝构造函数的时候,会存在浅拷贝与深拷贝之分。Java在重载clone方法的时候也存在同样的问题,当类中只有一些基本的数据类型的时候,采用上述方法就可以了,但是当类中包含了一些对象的时候,就需要用到深拷贝了,实现方法是对对象调用clone方法完成拷贝后,接着对对象中的非基本类型的属性也调用clone方法完成深拷贝。如下例所示:
import java.util.Date;

class Obj implements Cloneable{
       private Date birth=new  Date() ;

       public Date getBirth()  {
              return birth;
       }
       public void  setBirth(Date birth) {
              this.birth =  birth;
       }
       public void changeDate(){
              this.birth.setMonth(4);
       }
       public Object clone(){
              Obj o=null;
              try {
                     o =  (Obj)super.clone();
              } catch  (CloneNotSupportedException e) {
                     e.printStackTrace();
              }
        //实现深拷贝
              o.birth=(Date)this.getBirth().clone();
              return o;
       }
}
public class TestRef{     
       public static void  main(String[] args)
       {
              Obj a=new  Obj();
              Obj  b=(Obj)a.clone();
              b.changeDate();
              System.out.println("a="+a.getBirth());
              System.out.println("b="+b.getBirth());
       }
}
运行结果为:
a=Sat  Jul 13 23:58:56 CST 2013
b=Mon May 13 23:58:56 CST 2013
那么在编程的时候如何选择使用哪种拷贝方式呢?首先,检查类有无非基本类型(即对象)的数据成员。如果没有,则返回 super.clone() 即可,如果有,确保类中包含的所有非基本类型的成员变量都实现了深拷贝。
Objecto = super.clone(); // 先执行浅拷贝
对于每一个对象attr
o.attr = this.getAttr().clone();
最后返回 o
引申:
  • 浅拷贝和深拷贝的区别是什么?
    浅拷贝(ShallowClone):被复制对象的所有变量都含有与原来对象相同的值,而所有的对其它对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
    深拷贝(DeepClone):被复制对象的所有变量都含有与原来对象相同的值,除去那些引用其它对象的变量。那些引用其它对象的变量将指向被复制的新对象,而不再是原有的那些被引用的对象。换言之,深复制把复制的对象所引用的对象都复制了一遍。

    ​clone()方法的保护机制在Objectclone()是被声明为protected的。以User类为例,通过声明为protected,就可以保证只有User类里面才能“克隆”User对象,原理可以参考前面关于publicprotectedprivate的讲解。
年薪30万?????
赢取白富美,当上CEO??????
嫁给高富帅,成为阔太太?????
房子、车子、女子、孩子??????
恭喜你,只要你立志成为一名程序猿/媛,这些都不是梦。
那么问题来了,如何进入一家靠谱的IT企业呢?
我需要各大IT名企历年笔试面试真题与答案,怎么办?
我需要与顶级面试官与IT名企过来人心与心的交流,怎么办?
我需要学习offer达人的成功经验,怎么办?
都不是问题,猿媛之家来帮你。
猿媛之家程序员最可信赖的求职帮手这里有真题库、面经、一对一辅导、企业内推、招聘信息、行业发展、程序猿/媛恋爱、程序猿/媛段子等等,只要你需要,这里什么都有
更多信息请访问猿媛之家官方网站:www.yuanyuanzhijia.com


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|猿媛之家    

GMT+8, 2020-5-29 23:49 , Processed in 0.198255 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表