zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    专职DBA-MySQL体系结构与基本管理
    JSON
    MIME类型
    文件上传下载
    response常用的方法
    2020.11.27小记
    HTTP请求状态码
    1561. Maximum Number of Coins You Can Get
    1558. Minimum Numbers of Function Calls to Make Target Array
    1557. Minimum Number of Vertices to Reach All Nodes
  • 原文地址:https://www.cnblogs.com/hjlin/p/11368289.html
Copyright © 2011-2022 走看看