17、对象的克隆

学习目标:

1、了解对象克隆的概念

2、掌握重写clone实现对象的克隆

3、掌握深度克隆和浅克隆的概念

学习过程:

一、对象克隆简介

1、什么是对象的克隆

在java面向对象的编程当中,要复制引用类型的对象,就必须克隆这些对象。克隆对象,就是为新的对象分配空间,并进行对象的复制,并将原始对象的内容一一复制到新的对象空间去。

我们在编码过程经常会碰到将一个对象传递给另一个对象,java中对于基本型变量采用的是值传递,而对于对象比如JavaBean传递时采用的是引用传递,而很多时候对于对象传递我们也希望能够象值传递一样,使得传递之前和之后有不同的内存空间,这就是对象的克隆:一个新的对象和一个新的对象数据空间。

2、赋值不能实现克隆。

实现克隆需要通过调用可用的clone方法。如果是值类型的实例,那么“=”赋值运算符就可以将源对象的状态逐字节地复制到目标对象中。但是对象是对象空间的引用,所以赋值“=”方式只能是复制对象引用,是不会复制对象空间的。我们看看下面的代码:

(1)先构造一个Father类,实现代码如下;

1

2

3

4

5

6

7

8

9

10

11

12

  public class Father  {

 

    private String name;

     

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

 

}

(2)新建一个Run类,构造一个father1对象,并为其属性name赋值“刘邦”,然后把father1对象赋值给另外一个对象father2,打印father2的name属性,和father1一样,但是如果我们修改father2对象的name属性,这时候father1对象的name属性也会发生改变,也就是father1对象和father2对象指向的对象空间是同一个,并没有克隆。实现代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class Run {

 

    public static void main(String[] args) {

 

        Father father1 = new Father();

        father1.setName("刘邦");

 

        Father father2 = father1;

 

        System.out.println("father2的name="+father2.getName());

        //修改father2的name属性

        father2.setName("李世民");

        System.out.println("====修改后====");

        System.out.println("father2的name="+father2.getName());

        //father1的name属性 也改变了。

        System.out.println("father1的name="+father1.getName());

 

    }

 

}

运行结果如下:

attcontent/f4172a5f-db53-4d4a-b162-274c83aa1afa.png

也就是说赋值仅仅只是对象引用的复制,不是空间的复制,图示如下:

attcontent/eff9fb18-4bf8-413b-9e62-8a8c83f46880.png

也就是说对象克隆失败了。那如何才能真正做到对象的克隆呢?

二、对象的克隆的基本步骤

要实现对象的克隆我们需要完成按照以下几个步骤,然后调用clone()方法实现克隆。

1、可以利用Object类的clone()方法。实现Cloneable接口。

2、在派生类中覆盖基类的clone(),最好修改访问修饰符为public。

2、在派生类的clone()方法中,调用super.clone()。

示例代码如下:

1、让Father类实现Cloneable接口,并重写clone()方法。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

//1、实现Cloneable  接口

public class Father implements Cloneable {

 

    private String name;

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public Father clone() {

 

        try {

            Object object = super.clone();

            Father father = (Father) object;

            return father;

        catch (CloneNotSupportedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        return null;

    }

 

}

2、修改原来的Run类的main方法,通过调用clone()方法完成克隆。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class Run {

 

    public static void main(String[] args) {

 

        Father father1 = new Father();

        father1.setName("刘邦");

 

        Father father2 = father1.clone();//通过调用clone()方法

 

        System.out.println("father2的name="+father2.getName());

        //修改father2的name属性

        father2.setName("李世民");

        System.out.println("====修改后====");

        System.out.println("father2的name="+father2.getName());

        //father1的name属性 也改变了。

        System.out.println("father1的name="+father1.getName());

 

    }

 

}

唯一修改的代码就是把赋值改成调用clone()方法,这时候再次运行就会修改了father2对象的name属性,不会对father1的name属性有任何影响,因为现在有两个对象引用,指向两个不同的对象空间。运行结果如下:

attcontent/69604af7-c7fe-483d-ab6a-cbb68f1eaeb9.png

三、深度克隆

如果Father类的属性是一个对象,那么该对象并不会克隆的,如果你想要也克隆一份,那么该对象属性的实现类也需要实现克隆,我们称为深度克隆。

1、测试Father的属性是对象能否克隆成功。

比如我们添加一个Child类。实现代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

public class Child {

 

    private String name;

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

}

把这个Child类作为Father类的一个属性。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

//1、实现Cloneable  接口

public class Father implements Cloneable {

 

    private String name;

    private Child child;

     

    public Child getChild() {

        return child;

    }

 

    public void setChild(Child child) {

        this.child = child;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public Father clone() {

 

        try {

            Object object = super.clone();

            Father father = (Father) object;

            return father;

        catch (CloneNotSupportedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        return null;

    }

 

}

修改Run方法,测试Child有没有克隆。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

public class Run {

 

    public static void main(String[] args) {

 

        Father father1 = new Father();

        father1.setName("刘邦");

         

        //设置Child属性。

        Child child=new Child();

        child.setName("刘三儿");

        father1.setChild(child);

 

        Father father2 = father1.clone();//通过调用clone()方法

 

        System.out.println("father2的name="+father2.getName());

        System.out.println("father2的child的name="+father2.getChild().getName());

        //修改father2的name属性

        father2.setName("李世民");

        System.out.println("====修改后====");

        System.out.println("father2的name="+father2.getName());

        System.out.println("father1的name="+father1.getName());

         

        System.out.println("=====Child======");

        father2.getChild().setName("李四");

        System.out.println("father2的child的name="+father2.getChild().getName());

        System.out.println("father1的child的name="+father1.getChild().getName());

 

    }

 

}

运行结果如下:

attcontent/22c01bf8-0215-4eeb-8337-6a6d40e94a12.png

也就是说Child并没有克隆。

2、实现深度克隆。

让Child也可克隆:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

public class Child implements Cloneable {

 

    private String name;

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public Child clone() {

 

        try {

            Object object = super.clone();

            Child child = (Child) object;

            return child;

        catch (CloneNotSupportedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

 

        return null;

    }

 

}

修改Father类的clone()方法,在克隆Father的时候同时把Child也克隆一份:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Override

    public Father clone() {

 

        try {

            Object object = super.clone();

            Father father = (Father) object;

             

            //同时克隆Child对象

            Child child=father.getChild().clone();

            father.setChild(child);

             

            return father;

        catch (CloneNotSupportedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        return null;

    }

再次运行Run类,结果如下:

attcontent/c168ff90-6755-4f70-92a7-123e0530ca27.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的对象克隆工具类是指能够帮助我们实现对象克隆操作的工具类。 在Java中,对象克隆是指创建一个与原始对象具有相同属性和值的新对象。这个新对象可以是原始对象的完全副本,即改变新对象不会影响原始对象。为了实现对象克隆,Java提供了Cloneable接口和clone()方法。 下面是一个简单的Java对象克隆工具类的示例代码: ``` public class CloneUtil { public static <T> T clone(T source) { try { // 判断对象是否实现了Cloneable接口 if (source instanceof Cloneable) { // 通过调用clone()方法进行对象克隆 Method cloneMethod = source.getClass().getMethod("clone"); return (T) cloneMethod.invoke(source); } } catch (Exception e) { e.printStackTrace(); } return null; } } ``` 在上面的代码中,我们定义了一个泛型方法clone(),它接受一个参数source,表示要克隆的原始对象。然后我们首先使用instanceof运算符来判断source是否实现了Cloneable接口,如果是,则通过反射获取clone()方法,并调用它来进行对象克隆。最后返回克隆后的新对象。 使用该工具类进行对象克隆的示例代码如下: ``` public class Main { public static void main(String[] args) { Person person1 = new Person("Alice", 25); // 使用克隆工具类进行对象克隆 Person person2 = CloneUtil.clone(person1); System.out.println(person1); System.out.println(person2); System.out.println(person1 == person2); } } ``` 在上面的示例代码中,我们创建了一个Person对象person1,并将其克隆到person2中。然后分别打印person1、person2以及判断person1和person2是否为同一个对象。 通过上述Java对象克隆工具类的实现,我们可以方便地实现对象克隆操作,提高代码的可复用性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值