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时注意一些即可了。

原文地址:https://www.cnblogs.com/lcchuguo/p/5385608.html