当前位置:   article > 正文

java实现简单的克隆(调用Object的clone方法和浅拷贝,深拷贝)_java clone

java clone

目录

浅拷贝

浅拷贝过程和问题解析:

浅拷贝完整代码

结果:

浅拷贝与深拷贝区别详解

实现深拷贝

深拷贝完整代码:


浅拷贝

目标:通过调用object的clone方法将对象student1的内容拷贝到student2中去

省流总结:浅拷贝的常见问题:

1:Object的clone方法是protected修饰需要在克隆类中重写

2:编译时异常/受查异常

3:向下转型时需要强制类型转换

4:克隆类需要设置标记接口

浅拷贝过程和问题解析:

首先我们有一个Student对象并给他实例化

  1. package csda克隆代码示范;
  2. class Student{
  3. public int age;
  4. public Student(int age) {
  5. this.age = age;
  6. }
  7. }
  8. public class Test {
  9. public static void main(String[] args) {
  10. Student student1 = new Student(30);//待拷贝内容
  11. }
  12. }

因为Java中所有的类都会默认继承Object父类,所以我们最简单直接的想法是直接通过student1调用Object的clone方法并用student2接收

 不幸的是,student1无法调用clone方法——————————。。。。。。。。。。。。

为什么呢?

我们查看来查看object的clone方法的原码(双击shift键搜索object然后回车,在左侧Structure中找打clone方法)

 clone方法如下:

 真相大白!!!!

Object中clone方法是用protected修饰的!!!所以无法通过不同包的非子类来调用;

同时我们发现clone方法确实会返回一个满足我们拷贝需求的对象,并且是Object类型的(后面要用)。

那怎么解决这个问题呢?

答案是在我们的Student类中重写一个clone方法并在这个方法中用super调用Object类的clone方法、

快捷方法:右键+generate+Override Methdos+clone

 结果:

  1. @Override
  2. protected Object clone() throws CloneNotSupportedException {
  3. return super.clone();
  4. }

 同时,student1中可以点出clone方法

 但是,这是我们发现clone方法还是错的。。。。。。。

这里的错误是受查异常/编译时异常,解决方法:鼠标放在clone上,同时alt+回车

 选择第一个选项。

令人悲伤的:

 红线变长了。。。。。

又一个错误出现。

我们回忆一下,刚刚clone方法的原码。。。。。

Object的clone方法会返回一个Object类型的对象给student中重写的clone方法,然后我们用student2来给这个对象实例化。

总结一下:我们将父类的Object类交给了子类Student。这是一个什么过程?——向下转型

向下转型需要将我们的父类强制类型转换成子类类型:

     Student studen2 = (Student)student1.clone();

然后运行。你以为这就结束了?

。。。。。。。。。。。。。。。。

别急,还有最后一个问题需要解决(真的是最后一个)

上面的报错是:不支持克隆

我们需要在Student类继承一个克隆接口

  1. class Student implements Cloneable{
  2. }

 这个接口是一个空接口也叫标记接口,证明当前类是可以被克隆的。

浅拷贝完整代码

  1. package csda克隆代码示范;
  2. class Student implements Cloneable{
  3. public int age;//需要克隆的成员变量
  4. //构造函数
  5. public Student(int age) {
  6. this.age = age;
  7. }
  8. @Override//重写的clone方法
  9. protected Object clone() throws CloneNotSupportedException {
  10. return super.clone();//调用Object的clone方法
  11. }
  12. }
  13. public class Test {
  14. public static void main(String[] args) throws CloneNotSupportedException {
  15. Student student1 = new Student(30);
  16. Student student2 = (Student)student1.clone();
  17. System.out.println(student1.age);
  18. System.out.println(student2.age);
  19. }
  20. }

结果:

浅拷贝与深拷贝区别详解

我们现在写一个Number类,给Student类中设置一个Number类型的成员变量,并在Student的构造方法中给其实例化。

接下来在Test类中先输出student1和student2的值,然后修改student2的m的num值,发现student1中的m的num值也随之改变

  1. package csda克隆代码示范;
  2. //
  3. class Number{
  4. int num;
  5. }
  6. class Student implements Cloneable{
  7. public int age;
  8. public Number m;//在原来的代码的基础上添加一个Number类型的成员变量,名称为m
  9. public Student(int age) {
  10. this.age = age;
  11. this.m = new Number();//实例化
  12. }
  13. @Override
  14. protected Object clone() throws CloneNotSupportedException {
  15. return super.clone();
  16. }
  17. }
  18. public class Test {
  19. public static void main(String[] args) throws CloneNotSupportedException {
  20. Student student1 = new Student(30);
  21. Student student2 = (Student)student1.clone();
  22. System.out.println(student1.m.num);
  23. System.out.println(student2.m.num);
  24. student1.m.num = 1;//更改student2的m的num的值
  25. System.out.println(student1.m.num);
  26. System.out.println(student2.m.num);
  27. }
  28. }

结果:

 为什么我们更改了student2的m的num值,student1的m的num值也改变了?

浅拷贝图解:

 当我们在student类中实例化一个m类后:

 我们的super.clone克隆了student1中的内容,所以我们在student2中也实例化了一个Number类型的m对象,它们都引用了类Number,所以我们在通过student2更改m的值之后,student1的m的num值也会改变。

用上述代码我们在克隆一个对象(这个对象里还有一个对象)时,对象里的对象并不满足拷贝,这种情况我们就称作浅拷贝。

那怎么改成深拷贝呢?

实现深拷贝

1:在克隆对象里的对象对应的类重写克隆方法并添加标记接口(本文中时Number类)

  1. class Number implements Cloneable{
  2. int num;
  3. @Override
  4. protected Object clone() throws CloneNotSupportedException {
  5. return super.clone();
  6. }
  7. }

2:设置一个过渡的类接收clone返回的克隆对象并返回tmp

  1. protected Object clone() throws CloneNotSupportedException {
  2. Student tmp = (Student)super.clone();
  3. tmp.m = (Number)this.m.clone();
  4. return tmp;
  5. }

深拷贝完整代码:

  1. package csda克隆代码示范;
  2. class Number implements Cloneable{
  3. int num;
  4. @Override
  5. protected Object clone() throws CloneNotSupportedException {
  6. return super.clone();
  7. }
  8. }
  9. class Student implements Cloneable{
  10. public int age;
  11. public Number m;
  12. public Student(int age) {
  13. this.age = age;
  14. this.m = new Number();
  15. }
  16. @Override
  17. protected Object clone() throws CloneNotSupportedException {
  18. Student tmp = (Student)super.clone();
  19. tmp.m = (Number)this.m.clone();
  20. return tmp;
  21. }
  22. }
  23. public class Test {
  24. public static void main(String[] args) throws CloneNotSupportedException {
  25. Student student1 = new Student(30);
  26. Student student2 = (Student)student1.clone();
  27. System.out.println(student1.m.num);
  28. System.out.println(student2.m.num);
  29. student2.m.num = 1;
  30. System.out.println(student1.m.num);
  31. System.out.println(student2.m.num);
  32. }
  33. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/616637
推荐阅读
相关标签
  

闽ICP备14008679号