• Java clone方法(下)


    1.终于调用的是一个JNI方法,即java本地方法,加高速度

    2.使用clone方法,分为浅复制、深复制,这里直接使用网上抄来的案例来说明吧:

    说明:

      1)为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在执行时刻,Object中的clone()识别你要复制的是哪一个对象,然后为此对象分配空间。并进行对象的复制,将原始对象的内容一一拷贝到新对象的存储空间中。

      2)继承自java.lang.Object.clone()方法是浅层复制。一下代码能够证明之:


     1 public class Student implements Cloneable {
     2     private String name;
     3     private int age;
     4     private Professor pro;
     5     public Student(){}
     6     public Student(String name,int age,Professor pro){
     7         this.name=name;
     8         this.age=age;
     9         this.pro=pro;
    10     }
    11     public Object clone(){
    12         Object o=null;
    13         try {
    14             //Object中的clone()识别出你要复制的是哪一个对象。
    15             o=super.clone();
    16         } catch (CloneNotSupportedException e) {
    17             System.out.println(e.toString());
    18         }
    19         return o;
    20     }
    21     public String getName() {
    22         return name;
    23     }
    24     public void setName(String name) {
    25         this.name = name;
    26     }
    27     public int getAge() {
    28         return age;
    29     }
    30     public void setAge(int age) {
    31         this.age = age;
    32     }
    33     public Professor getPro() {
    34         return pro;
    35     }
    36     public void setPro(Professor pro) {
    37         this.pro = pro;
    38     }
    39 }
    40 class Professor{
    41     private String name;
    42     private int age;
    43     public Professor(){}
    44     public Professor(String name,int age){
    45         this.name=name;
    46         this.age=age;
    47     }
    48     public String getName() {
    49         return name;
    50     }
    51     public void setName(String name) {
    52         this.name = name;
    53     }
    54     public int getAge() {
    55         return age;
    56     }
    57     public void setAge(int age) {
    58         this.age = age;
    59     }
    60 }

     1 public class StudentTest {
     2     public static void main(String[] args) {
     3         Professor p=new Professor("wangwu",50);
     4         Student s1=new Student("zhangsan",18,p);
     5         Student s2=(Student)s1.clone();
     6         s2.getPro().setName("maer");
     7         s2.getPro().setAge(40);
     8         System.out.println("name="+s1.getPro().getName()
     9                 +",age="+s1.getPro().getAge());
    10         //name=maer,age=40
    11     }
    12 }

      那么我们怎样实现深层复制的克隆,即在改动s2.Professor时不影响s1.Professor?代码改进例如以下:


     1 public class Student implements Cloneable {
     2     private String name;
     3     private int age;
     4     Professor pro;
     5     public Student(){}
     6     public Student(String name,int age,Professor pro){
     7         this.name=name;
     8         this.age=age;
     9         this.pro=pro;
    10     }
    11     public Object clone(){
    12         Student o=null;
    13         try {
    14             //Object中的clone()识别出你要复制的是哪一个对象。

    15 o=(Student)super.clone(); 16 } catch (CloneNotSupportedException e) { 17 System.out.println(e.toString()); 18 } 19 o.pro=(Professor)pro.clone(); 20 return o; 21 } 22 public String getName() { 23 return name; 24 } 25 public void setName(String name) { 26 this.name = name; 27 } 28 public int getAge() { 29 return age; 30 } 31 public void setAge(int age) { 32 this.age = age; 33 } 34 public Professor getPro() { 35 return pro; 36 } 37 public void setPro(Professor pro) { 38 this.pro = pro; 39 } 40 } 41 class Professor implements Cloneable{ 42 private String name; 43 private int age; 44 public Professor(){} 45 public Professor(String name,int age){ 46 this.name=name; 47 this.age=age; 48 } 49 public Object clone(){ 50 Object o=null; 51 try { 52 o=super.clone(); 53 } catch (CloneNotSupportedException e) { 54 e.printStackTrace(); 55 } 56 return o; 57 } 58 public String getName() { 59 return name; 60 } 61 public void setName(String name) { 62 this.name = name; 63 } 64 public int getAge() { 65 return age; 66 } 67 public void setAge(int age) { 68 this.age = age; 69 } 70 }

    
    public class StudentTest {
        public static void main(String[] args) {
            Professor p=new Professor("wangwu",50);
            Student s1=new Student("zhangsan",18,p);
            Student s2=(Student)s1.clone();
            s2.getPro().setName("maer");
            s2.getPro().setAge(40);
            System.out.println("name="+s1.getPro().getName()
                    +",age="+s1.getPro().getAge());
            //name=wangwu,age=50
        }
    }

    也就是说浅复制仅仅复制了一些主要的属性,可是里面的引用的属性并没有真正的复制,所以假设想要达到深复制,还要在复写的代码中进行处理。将全部引用的对象也都调用它们的clone()方法。

    下面是摘抄的网友的三点小总结:

    clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
    ①对不论什么的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
    ②对不论什么的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
    ③假设对象x的equals()方法定义恰当。那么x.clone().equals(x)应该成立。


    以下重点说一下,为什么String相同是对象。可是却不用特殊处理;理由例如以下:

    String不是基本数据类型。可是在深复制的时候并没有进行单独的复制。也就是说违反了深复制,只复制了引用,而String没有实现cloneable接口,也就是说只能复制引用。

            那么在改动克隆之后的对象之后,会不会将原来的值也改变了?

            答案肯定是不会改变,由于String是在内存中不能够被改变的对象,就比方说在for大量循环中不推荐使用+的方式来拼凑字符串一样,每次使用+都会新分配一块内存,不在原来上改动,原来的没有指向它的引用,会被回收。所以克隆相当于1个String内存空间有两个引用,当改动当中的一个值的时候。会新分配一块内存用来保存新的值,这个引用指向新的内存空间,原来的String由于还存在指向他的引用,所以不会被回收,这样,尽管是复制的引用,可是改动值的时候,并没有改变被复制对象的值。

            所以在非常多情况下。我们能够把String在clone的时候和基本类型做同样的处理。仅仅是在equal时注意一些即可了。

  • 相关阅读:
    Android 4.1 for Developers
    Frame Animation 帧动画
    07事事精明,人人远离。
    Launcher 拖拽 流程小结『android 2.3 2.2』
    Android开发书籍推荐
    My first App EncryptWheel is in WAITING FOR REVIEW status
    ubuntu安装显卡驱动
    Shell脚本学习笔记(十)文件操作
    Shell脚本学习笔记(四)流程控制
    Shell脚本学习笔记(五)函数
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5385608.html
Copyright © 2020-2023  润新知