• ArrayList之Cloneable 标记性接口


    前言

    ArrayList集合介绍

    动态数组:可调整大小的数组实现

    数组结构介绍

    增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置。

    查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的方式快速获取对应位置上的元素。

    Cloneable 标记性接口

    介绍

    一个类实现cloneable接口来指示object.clone()方法,该方法对于该类的实例进行字段的复制是合法的。在不实现cloneable接口的实例上调用对象的克隆方法会导致CloneNotSupportedException被抛出。

    简言之:克隆就是依据已经有的数据,创造一份新的完全一样的数据拷贝

    Cloneable 源码分析

    克隆的前提条件
    被克隆对象所在的类必须实现 Cloneable
    接口必须重写 clone 方法
    clone的基本使用
    1. public class ArrayList_Clone {
    2. public static void main(String[] args) {
    3. ArrayList list = new ArrayList();
    4. list.add("人生就是旅途");
    5. list.add("也许终点和起点会重合");
    6. list.add("但是一开始就站在起点等待终点");
    7. list.add("那么其中就没有美丽的沿途风景和令人难忘的过往");
    8. //调用方法进行克隆
    9. Object o = list.clone();
    10. System.out.println(o == list);
    11. System.out.println(o);
    12. System.out.println(list);
    13. }
    14. }
    源码分析
    1. public class ArrayList {
    2. public Object clone() {
    3. try {
    4. ArrayList v = (ArrayList) super.clone();
    5. v.elementData = Arrays.copyOf(elementData, size);
    6. v.modCount = 0;
    7. return v;
    8. } catch (CloneNotSupportedException e) {
    9. throw new InternalError(e);
    10. }
    11. }
    12. }

    案例:已知 A 对象的姓名为赵云,年龄30 。由于项目特殊要求需要将该对象的数据复制另外一个对象 B 中,并且此后 A 和 B 两个对象的数据不会相互影响 案例:已知 A 对象的姓名为关羽,年龄30,技能为大刀斩华雄(技能为一个引用数据类型 Skill ),由于项目 特殊要求需要将该对象的数据复制另外一个对象 B 中,并且此后 A 和 B 两个对象的数据不会相互影响

    方式一:创建两个对象模拟
    1. 准备学生类
    1. public class Student implements Cloneable{
    2. //姓名
    3. private String name;
    4. //年龄
    5. private Integer age;
    6. public Student() {
    7. }
    8. public Student(String name, Integer age) {
    9. this.name = name;
    10. this.age = age;
    11. }
    12. public String getName() {
    13. return name;
    14. }
    15. public void setName(String name) {
    16. this.name = name;
    17. }
    18. public Integer getAge() {
    19. return age;
    20. }
    21. public void setAge(Integer age) {
    22. this.age = age;
    23. }
    24. @Override
    25. public String toString() {
    26. return "Student{" +
    27. "name='" + name + '\'' +
    28. ", age=" + age +
    29. '}';
    30. }
    31. }
    2. 准备测试类
    1. public class Test01 {
    2. public static void main(String[] args) throws CloneNotSupportedException {
    3. //创建学生对象
    4. Student stu1 = new Student("关羽", 29);
    5. //再次创建一个新的学生对象
    6. Student stu2 = new Student();
    7. //把stu1对象name的值取出来赋值给stu2对象的name
    8. stu2.setName(stu1.getName());
    9. //把stu1对象age的值取出来赋值给stu2对象的age
    10. stu2.setAge(stu1.getAge());
    11. System.out.println(stu1 == stu2);
    12. System.out.println(stu1);
    13. System.out.println(stu2);
    14. System.out.println("----此时不管修改哪个对象的内容,stu1和stu2都不会受到影响----");
    15. stu1.setName("扈三娘");
    16. System.out.println(stu1);
    17. System.out.println(stu2);
    18. }
    19. }
    3. 控制台效果
    false Student{name=' 关羽', age=29} Student{name='关羽 '', age=29} ----此时不管修改哪
    个对象的内容 ,stu1 stu2 都不会受到影响 ---- Student{name=' 赵云 ', age=29} Student{name='关羽 ', age=29}
    方式二:使用克隆

    浅克隆
    1. 定义 Javabean
    学生技能类
    1. //学生的技能类
    2. public class Skill implements Cloneable{
    3. private String skillName;
    4. public Skill() {
    5. }
    6. public Skill(String skillName) {
    7. this.skillName = skillName;
    8. }
    9. public String getSkillName() {
    10. return skillName;
    11. }
    12. public void setSkillName(String skillName) {
    13. this.skillName = skillName;
    14. }
    15. @Override
    16. public String toString() {
    17. return "Skill{" +
    18. "skillName='" + skillName + '\'' +
    19. '}';
    20. }
    21. }
    学生类
    1. public class Student implements Cloneable{
    2. //姓名
    3. private String name;
    4. //年龄
    5. private Integer age;
    6. //技能
    7. private Skill skill;
    8. public Student() {
    9. }
    10. public Student(String name, Integer age, Skill skill) {
    11. this.name = name;
    12. this.age = age;
    13. this.skill = skill;
    14. }
    15. public String getName() {
    16. return name;
    17. }
    18. public void setName(String name) {
    19. this.name = name;
    20. }
    21. public Integer getAge() {
    22. return age;
    23. }
    24. public void setAge(Integer age) {
    25. this.age = age;
    26. }
    27. public Skill getSkill() {
    28. return skill;
    29. }
    30. public void setSkill(Skill skill) {
    31. this.skill = skill;
    32. }
    33. @Override
    34. public String toString() {
    35. return "Student{" +
    36. "name='" + name + '\'' +
    37. ", age=" + age +
    38. ", skill=" + skill +
    39. '}';
    40. }
    41. //浅克隆
    42. @Override
    43. public Student clone() throws CloneNotSupportedException {
    44. return (Student) super.clone();
    45. }
    46. }
    2. 定义测试类
    1. public class Test01 {
    2. public static void main(String[] args) throws CloneNotSupportedException {
    3. //用自定义对象演示 深浅拷贝
    4. Skill skill = new Skill("大刀斩华雄");
    5. Student s = new Student("关羽",31,skill);
    6. //调用clone方法进行克隆
    7. Student obj = s.clone();
    8. //比较地址
    9. System.out.println(s == obj);
    10. System.out.println("被克隆对象: "+s);
    11. System.out.println("克隆出来的对象: "+obj);
    12. System.out.println("----华丽的分割线----");
    13. //克隆之后,更改skill中的数据
    14. skill.setSkillName("浑身是胆");
    15. //更改克隆后对象的数据
    16. obj.setName("赵云");
    17. obj.setAge(19);
    18. System.out.println("被克隆对象: "+s);
    19. System.out.println("克隆出来的对象: "+obj);
    20. }
    21. }
    控制台效果
    存在的问题 : 基本数据类型可以达到完全复制,引用数据类型则不可以
    原因 : 在学生对象 s 被克隆的时候,其属性 skill( 引用数据类型 ) 仅仅是拷贝了一份引用,因此当 skill 的值发生改 变时,被克隆对象s 的属性 skill 也将跟随改变
    深克隆
    1. 定义 Javabean
    学生技能类
    1. /**
    2. * @author itheima
    3. * @since JDK 1.8
    4. */
    5. public class Skill implements Cloneable{
    6. private String skillName;
    7. public Skill() {
    8. }
    9. public Skill(String skillName) {
    10. this.skillName = skillName;
    11. }
    12. public String getSkillName() {
    13. return skillName;
    14. }
    15. public void setSkillName(String skillName) {
    16. this.skillName = skillName;
    17. }
    18. @Override
    19. public String toString() {
    20. return "Skill{" +
    21. "skillName='" + skillName + '\'' +
    22. '}';
    23. }
    24. //重写克隆方法,将权限修饰符改成public
    25. @Override
    26. public Skill clone() throws CloneNotSupportedException {
    27. return (Skill) super.clone();
    28. }
    29. }
    学生类
    1. /**
    2. * @author itheima
    3. * @since JDK 1.8
    4. */
    5. public class Student implements Cloneable{
    6. //姓名
    7. private String name;
    8. //年龄
    9. private Integer age;
    10. //技能
    11. private Skill skill;
    12. public Student() {
    13. }
    14. public Student(String name, Integer age, Skill skill) {
    15. this.name = name;
    16. this.age = age;
    17. this.skill = skill;
    18. }
    19. public String getName() {
    20. return name;
    21. }
    22. public void setName(String name) {
    23. this.name = name;
    24. }
    25. public Integer getAge() {
    26. return age;
    27. }
    28. public void setAge(Integer age) {
    29. this.age = age;
    30. }
    31. public Skill getSkill() {
    32. return skill;
    33. }
    34. public void setSkill(Skill skill) {
    35. this.skill = skill;
    36. }
    37. @Override
    38. public String toString() {
    39. return "Student{" +
    40. "name='" + name + '\'' +
    41. ", age=" + age +
    42. ", skill=" + skill +
    43. '}';
    44. }
    45. //深克隆
    46. @Override
    47. public Student clone() throws CloneNotSupportedException {
    48. //调用超类Object中方法clone进行对象克隆,得到一个新的学生对象
    49. Student newStu = (Student) super.clone();
    50. //调用学生类其属性skill的clone方法,对属性进行克隆
    51. Skill s = this.skill.clone();
    52. //再将克隆的Skill设置给克隆出来的学生对象
    53. newStu.setSkill(s);
    54. //返回克隆出来的学生对象
    55. return newStu;
    56. }
    57. }
    2. 定义测试类
    测试类
    1. public class Test01 {
    2. public static void main(String[] args) throws CloneNotSupportedException {
    3. //用自定义对象演示 深浅拷贝
    4. Skill skill = new Skill("倒拔垂杨柳");
    5. Student s = new Student("鲁智深", 31, skill);
    6. //调用clone方法进行克隆
    7. Student obj = s.clone();
    8. //比较地址
    9. System.out.println(s == obj);
    10. System.out.println("被克隆对象: " + s);
    11. System.out.println("克隆出来的对象: " + obj);
    12. System.out.println("----华丽的分割线----");
    13. //克隆之后,更改skill中的数据
    14. skill.setSkillName("荷花酒");
    15. //更改克隆后对象的数据
    16. obj.setName("扈三娘");
    17. obj.setAge(19);
    18. System.out.println("被克隆对象: " + s);
    19. System.out.println("克隆出来的对象: " + obj);
    20. }
    21. }

  • 相关阅读:
    如何获取ABAP的程序事件顺序的调用堆栈
    医疗IT系统安科瑞隔离电源装置在医院的应用
    Pytoch随笔(光速入门篇)
    C#读写Excel
    mongo基础操作总结
    从GPT-4到GPT-4o:人工智能的进化与革命
    力扣 1422. 分割字符串的最大得分
    什么是分支和合并(阁瑞钛伦特软件-九耶实训)
    tesseract-ocr-w64-setup-5.3.3.20231005.exe 百度网盘下载
    含文档+PPT+源码等]精品基于Uniapp实现的鲜花商城App[包运行成功]
  • 原文地址:https://blog.csdn.net/qq_31536117/article/details/134445252