• Java 对象克隆


    首先,我们需要知道的是,什么是对象克隆?对象克隆是当程序运行时,可能需要一个新对象,用来保存当前对象的状态,并且新的对象与当前对象没有任何关联,即我改变了新对象属性的值,而当前对象没有发生改变。而这新的对象,就是对当前对象的克隆,或者说拷贝。

    要完成对象克隆,有以下要求:

      1. 新的对象与当前对象值相同

         2. 新的对象与当前对象的引用地址不同

    要实现对象克隆,有以下步骤:

      1. 对要被对象克隆的对应类继承Cloneable接口,并重载clone方法,将访问权限改成public

         2. 将当前对象的clone方法赋值给新的对象,完成对象克隆。

    public class Test  implements Cloneable{
        public int a;
        public int b;
        private int c;
        private int d;
        public String aa;
        private String bb;
        public TestIn testIn = new TestIn();
        public TestIns testIns = new TestIns();
        
        @Override
        public Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            return super.clone();
        }
        
        public Test(){}
        public Test(int a,int b,int c,int d){
            this.a=a;
            this.b=b;
            this.c=c;
            this.d=d;
        }
        private Test(int c,int d){
            this.c=c;
            this.d=d;
        }
        
        public int getA() {
            return a;
        }
        public void setA(int a) {
            this.a = a;
        }
        public int getB() {
            return b;
        }
        public void setB(int b) {
            this.b = b;
        }
        public int getC() {
            return c;
        }
        public void setC(int c) {
            this.c = c;
        }
        public int getD() {
            return d;
        }
        public void setD(int d) {
            this.d = d;
        }
        private void A(){
            System.out.println("哈哈哈");
        }
        public void B(){
            System.out.println("fdsa");
        }
        
        public String getAa() {
            return aa;
        }
    
        public void setAa(String aa) {
            this.aa = aa;
        }
    
        public String getBb() {
            return bb;
        }
    
        public void setBb(String bb) {
            this.bb = bb;
        }
    
        @Override
        public String toString() {
            return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", aa=" + aa + ", bb=" + bb + "]";
        }
        
        class TestIn{
            public String test_a;
            public int test_b;
        }
        class TestIns{
            public String test_a;
            public int test_b;
        }
    }
    Test test_1 = new Test();
    Test test_2 = (Test) test_1.clone(); System.out.println(" ++++++++++拷贝(克隆)+++++++++++"); System.out.println("----------赋值前----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2); test_2.setA(4); System.out.println("----------赋值基本类型----------"); System.out.println("test_1:"+test_1); System.out.println("test_2:"+test_2);
    System.out.println("类是否引用同个地址:"+(test_1 == test_2));

     以上代码的运行结果为:

    ++++++++++拷贝(克隆)+++++++++++
    ----------赋值前----------
    test_1:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
    test_2:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
    ----------赋值基本类型----------
    test_1:Test [a=2, b=0, c=0, d=0, aa=null, bb=null]
    test_2:Test [a=4, b=0, c=0, d=0, aa=null, bb=null]
    类是否引用同个地址:false

    这样,我们就实现了对象的克隆,当然,仅仅只是针对当前对象基本类型的克隆,这种对象克隆我们称之为浅克隆。

    而如果要实现基本数据类型以及引用类型的克隆,就需要深克隆。

    在test类中,你们也可以看到,有两个类的对象,一个是TestIn类,一个是TestIns类,并且都初始化了,然而在浅克隆的情况下,他们指向的地址是一致的

    System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
    System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));

    其运行结果:

    类的引用类TestIn是否引用同个地址:true
    类的引用类TestIns是否引用同个地址:true

    如何实现深克隆呢,其实实现深克隆和实现浅克隆的原理差不多,步骤如下:

      1.被克隆的对象对应类要继承Cloneable接口,并重载clone方法

           2.若被克隆的对象里,有属性为被克隆的对象,则需要重写clone方法

           3. 将当前对象的clone方法赋值给新的对象,完成对象深克隆。

    以下代码我重写了Test的clone方法,并让对应类TestIns继承了Cloneable接口,重载clone方法

    public class Test  implements Cloneable{
        public int a;
        public int b;
        private int c;
        private int d;
        public String aa;
        private String bb;
        public TestIn testIn = new TestIn();
        public TestIns testIns = new TestIns();
        
        @Override
        public Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            Test test = (Test)super.clone();
            test.testIns =(TestIns) this.testIns.clone();
            return test;
        }
        
        public Test(){}
        public Test(int a,int b,int c,int d){
            this.a=a;
            this.b=b;
            this.c=c;
            this.d=d;
        }
        private Test(int c,int d){
            this.c=c;
            this.d=d;
        }
        
        public int getA() {
            return a;
        }
        public void setA(int a) {
            this.a = a;
        }
        public int getB() {
            return b;
        }
        public void setB(int b) {
            this.b = b;
        }
        public int getC() {
            return c;
        }
        public void setC(int c) {
            this.c = c;
        }
        public int getD() {
            return d;
        }
        public void setD(int d) {
            this.d = d;
        }
        private void A(){
            System.out.println("哈哈哈");
        }
        public void B(){
            System.out.println("fdsa");
        }
        
        public String getAa() {
            return aa;
        }
    
        public void setAa(String aa) {
            this.aa = aa;
        }
    
        public String getBb() {
            return bb;
        }
    
        public void setBb(String bb) {
            this.bb = bb;
        }
    
        @Override
        public String toString() {
            return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", aa=" + aa + ", bb=" + bb + "]";
        }
        
        class TestIn{
            public String test_a;
            public int test_b;
        }
        class TestIns implements Cloneable{
            public String test_a;
            public int test_b;
            
            @Override
            protected Object clone() throws CloneNotSupportedException {
                // TODO Auto-generated method stub
                return super.clone();
            }
        }
    }
    System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
    System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));

    运行效果如下:

    类的引用类TestIn是否引用同个地址:true
    类的引用类TestIns是否引用同个地址:false

    有兴趣的可以去了解一下,为什么克隆有浅克隆和深克隆的区别:https://www.jianshu.com/p/b597f3e8269a 

    总结:无论是浅克隆还是深克隆,都需要将对应类继承Cloneable接口,并重载或者重写clone方法;浅克隆,只能克隆类的基本类型,而深克隆则可以克隆基本基本类型以及引用类型。

    public class TestMain{
        public static void main(String[] args){
            Test test_1 = new Test();
            Test test_2 = test_1;
            System.out.println("++++++++++引用+++++++++++");
            System.out.println("----------赋值前----------");
            System.out.println("test_1:"+test_1);
            System.out.println("test_2:"+test_2);
            
            test_2.setA(2);
            System.out.println("----------赋值后----------");
            System.out.println("test_1:"+test_1);
            System.out.println("test_2:"+test_2);
            System.out.println("类是否引用同个地址:"+(test_1 == test_2));
            
            try {
                test_2 = (Test) test_1.clone();
                System.out.println("
    ++++++++++拷贝(克隆)+++++++++++");
                System.out.println("----------赋值前----------");
                System.out.println("test_1:"+test_1);
                System.out.println("test_2:"+test_2);
                
                test_2.setA(4);
                System.out.println("----------赋值基本类型----------");
                System.out.println("test_1:"+test_1);
                System.out.println("test_2:"+test_2);
                System.out.println("类是否引用同个地址:"+(test_1 == test_2));
                System.out.println("类的引用类TestIn是否引用同个地址:"+(test_1.testIn == test_2.testIn));
                System.out.println("类的引用类TestIns是否引用同个地址:"+(test_1.testIns == test_2.testIns));
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    View Code
  • 相关阅读:
    交流课件
    ARC127F ±AB
    CF1566F xor-quiz
    JOISC 2016 Day 1 棋盘游戏
    dev分支和release是什么
    drf 笔记
    drf 序列化的写法 总结
    Linux系统编程
    C/C++ 网络编程
    C++提高编程
  • 原文地址:https://www.cnblogs.com/hjlin/p/11368289.html
Copyright © 2020-2023  润新知