• 关于浅克隆和深克隆入门理解


    浅克隆:需要类实现Cloneable,并重写clone()方法

    一般在重写clone()方法时,将返回值类型强转为自己类,避免每次克隆之后需要强转

    1. public class Test {
    2. public static void main(String[] args) throws CloneNotSupportedException {
    3. A a1=new A();
    4. A a2 = a1.clone();
    5. //克隆之后 a1和a2是两个不同对象 内容相同
    6. System.out.println(a1==a2);//false
    7. //true 注意这里也是true 如果a1和a2是new出来的 这里肯定是false
    8. System.out.println(a1.getC()==a2.getC());//true
    9. //注意 这里并非常量池里取,而是指向同一个对象 再把对象放入常量池
    10. System.out.println(a1.getE()==a2.getE());//true
    11. System.out.println(a1);//A{a=1, b=2, c='3', d=D{name='1'}, e='4'}
    12. System.out.println(a2);//A{a=1, b=2, c='3', d=D{name='1'}, e='4'}
    13. System.out.println("--------------------------------------");
    14. //浅克隆之后,对String类型和8种基本类型(包装类)的改变不会影响另外一个对象的属性内容
    15. a1.setA(5);
    16. a1.setB(6);
    17. a1.setC("7");
    18. a1.setE("8");
    19. System.out.println(a1);//A{a=5, b=6, c='7', d=D{name='1'}, e='8'}
    20. System.out.println(a2);//A{a=1, b=2, c='3', d=D{name='1'}, e='4'}
    21. System.out.println("--------------------------------------");
    22. //但是浅克隆对自定义类型的成员变量的改变,会影响另外一个对象 说明自定义对象在a1和a2中的引用地址指向了同一个对象
    23. a1.getD().setName("改了");
    24. System.out.println(a1);//A{a=5, b=6, c='7', d=D{name='改了'}, e='8'}
    25. System.out.println(a2);//A{a=1, b=2, c='3', d=D{name='改了'}, e='4'}
    26. a2.getD().setName("又改了");
    27. System.out.println(a1);//A{a=5, b=6, c='7', d=D{name='又改了'}, e='8'}
    28. System.out.println(a2);//A{a=1, b=2, c='3', d=D{name='又改了'}, e='4'}
    29. }
    30. }
    31. class A implements Cloneable{
    32. int a=1;
    33. Integer b=2;
    34. String c=new String("3");
    35. D d=new D();
    36. String e="4";
    37. @Override
    38. public String toString() {
    39. return "A{" +
    40. "a=" + a +
    41. ", b=" + b +
    42. ", c='" + c + '\'' +
    43. ", d=" + d +
    44. ", e='" + e + '\'' +
    45. '}';
    46. }
    47. public D getD() {
    48. return d;
    49. }
    50. public void setD(D d) {
    51. this.d = d;
    52. }
    53. public String getE() {
    54. return e;
    55. }
    56. public void setE(String e) {
    57. this.e = e;
    58. }
    59. public int getA() {
    60. return a;
    61. }
    62. public void setA(int a) {
    63. this.a = a;
    64. }
    65. public Integer getB() {
    66. return b;
    67. }
    68. public void setB(Integer b) {
    69. this.b = b;
    70. }
    71. public String getC() {
    72. return c;
    73. }
    74. public void setC(String c) {
    75. this.c = c;
    76. }
    77. @Override
    78. protected A clone() throws CloneNotSupportedException {
    79. return (A)super.clone();
    80. }
    81. }
    82. class D{
    83. String name="1";
    84. public String getName() {
    85. return name;
    86. }
    87. public void setName(String name) {
    88. this.name = name;
    89. }
    90. @Override
    91. public String toString() {
    92. return "D{" +
    93. "name='" + name + '\'' +
    94. '}';
    95. }
    96. }

    画张图表示

    如果两个对象是NEW的

    1. public class Test1 {
    2. public static void main(String[] args) {
    3. E e1=new E();
    4. E e2=new E();
    5. System.out.println(e1.str1==e2.str1);//true
    6. System.out.println(e1.str2==e2.str2);//false
    7. System.out.println(e1.i1==e2.i1);//true
    8. System.out.println(e1.i2==e2.i2);//false
    9. System.out.println(e1.i3==e2.i3);//true
    10. }
    11. }
    12. class E{
    13. String str1="123";//常量池里取 没有就new 然后放入常量池
    14. String str2=new String("123");//new必定创建新对象
    15. Integer i1=1;//常量池里取 没有就new 然后放入常量池
    16. Integer i2=new Integer(1);//new必定创建新对象
    17. Integer i3=Integer.valueOf(1);//常量池里取 没有就new 然后放入常量池
    18. }

    下面是深克隆的一种写法

    让自定义类也实现克隆,并重写clone方法

    然后在对象类的克隆方法改写成下面

    这样再运行上面代码,  D就是不同的对象了,克隆之后,无论谁改变d的属性,都只影响自己

    以集成工具默认重写equals和hashcode不影响执行结果

    深克隆还有其他写法

  • 相关阅读:
    springboot整合mybatis(配置模式+注解模式)
    五、Spring Boot 整合持久层技术(4)
    RT-Thread学习笔记(一):认识RT-Thread系统
    OpenCV-视频读写(java版)
    From 表单临时存储
    No151.精选前端面试题,享受每天的挑战和学习
    瑞芯微RK3588开发板:虚拟机yolov5模型转化、开发板上python脚本调用npu并部署 全流程
    Android进阶宝典 -- 手写RecyclerView分页组件
    Docker使用Calico网络模式配置及问题处理
    基于python的家政管理系统毕业设计源码071111
  • 原文地址:https://blog.csdn.net/tiantiantbtb/article/details/132892031