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时注意一些就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值