加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java 对象克隆

发布时间:2020-12-15 08:01:57 所属栏目: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("r++++++++++拷贝(克隆)+++++++++++"); 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,bb=null]
----------赋值基本类型----------
test_1:Test [a=2,bb=null]
test_2:Test [a=4,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,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("r++++++++++拷贝(克隆)+++++++++++");
            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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读