精华内容
下载资源
问答
  • 许久没有更新过,最近因为这个问题引发线上bug,特再次整理汇总!...Java语言中对象拷贝分为深拷贝和浅拷贝以及对象简单的引用拷贝(也就是通常使用的对象赋值)。 1.1 引用拷贝 引用拷贝即对象的赋值操作,就

    许久没有更新过,最近因为这个问题引发线上bug,特再次整理汇总!!!

    1. 对象拷贝

    Java语言中对象拷贝分为深拷贝和浅拷贝以及对象简单的引用拷贝(也就是通常使用的对象赋值)。

    1.1 引用拷贝

    引用拷贝即对象的赋值操作,就是通常使用的 obj = new Object() 操作,这种方式不会重新在堆内存开辟一个空间去创建这个对象,只是在栈中新增加了一个引用指向原本的对象。

    1.2 浅拷贝

    浅拷贝则会在堆内存中重新创建一个对象,但是它内部的属性不会重新去创建,而是直接引用原对象属性的地址。Java语言Object的克隆方法默认是浅拷贝。下面的Student类有个特殊的地方就是它的属性类型都是不可变的,即class类通过final进行了修饰,即使对studentB进行属性的修改,也不会对studentA有什么影响,因为不可变对象每进行修改都是重新创建了一个对象(常量池没有创建只是会进行引用的重新指向)。但是若有个Date类型的属性,那么对studentB Date属性进行修改时就会对原有对象studentA的属性值改变。

    // 需要实现Cloneable接口
    public class Student implements Cloneable {
    
        private Long id;
        private String name;
        private Integer age;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    public class CopyDemo {
        public static void main(String[] args) throws CloneNotSupportedException {
            Student studentA = new Student();
            studentA.setId(1L);
            studentA.setName("tom");
            studentA.setAge(14);
            Student studentB = (Student) studentA.clone();
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H49NFYcx-1618066137512)(./img/1.png)]

    1.3 深拷贝

    深拷贝和浅拷贝一样都会重新创建一个对象,和浅拷贝不同的是对象的属性也都是重新去创建的,没有引用原对象属性的地址。要通过clone方法的方式去实现深拷贝必须手动去实现,非不可变对象一定要进行对象的重新创建

    package com.tianqb.object.copy;
    
    import java.util.Date;
    
    public class Student implements Cloneable {
    
        private Long id;
        private String name;
        private Integer age;
        private Date created;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Student target = (Student) super.clone();
            if (null != this.created) {
                target.setCreated((Date) this.created.clone());
            }
            return target;
        }
    }
    

    2. 对象拷贝中常用的工具类

    2.1 Apache BeanUtils#copyProperties

    特点:

    • 浅拷贝,属性还是指向原本对象的引用
    • 字段名称相同,类型不同无法进行赋值
    • 基本类型字段和引用对象可以映射

    2.2 SpringUtils#copyProperties

    特点:

    • 特性同Apache,效率比Apache高
    • 参数位置同Apache不同

    2.3 序列化(JSON)

    特点:

    • 性能较低,耗时(序列化-反序列化)
    • 深拷贝
    • 基本类型字段和引用对象可以映射
    • 字段名称相同,类型不同可以赋值(如Long -> String)

    2.4 MapStruct(推荐)

    特点:

    • 灵活(可自主配置字段映射关系)
    • 可以配置多对一映射关系
    • 效率高,准确(编译器代码生成,源码就是get、set方法)
    • 深拷贝

    使用:

    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.3.1.Final</version>
    </dependency>
    
    @Mapper
    public interface StudentMapper {
     
        StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
      
        @Mapping(source = "no", target = "number")
        @Mapping(source = "createDate", target = "createDate", dateFormat = "yyyy-MM-dd")
        StudentDO dtoToDo(StudentDTO studentDTO);
    }
    
    
    
    StudentDO studentDO = StudentMapper.INSTANCE.dtoToDo(studentDTO);
    

    注意点:
    由于是编译期间生成get、set代码,假如项目中使用了lombok工具,就会出现编译失败找不到具体的get、set方法的问题,原因是lombok也是编译期间进行代码的生成,但是在mapstruct编译的时候lombok还没有进行代码的生成,因此编译出错,解决的方式如下,需要在maven配置文件中添加两个插件,即lombok和maspstruct。

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
            <source>1.8</source> <!-- depending on your project -->
            <target>1.8</target> <!-- depending on your project -->
            <annotationProcessorPaths>
                <path>
                    <groupId>org.mapstruct</groupId>
                    <artifactId>mapstruct-processor</artifactId>
                    <version>1.3.1.Final</version>
                </path>
                <!-- other annotation processors -->
            </annotationProcessorPaths>
        </configuration>
    </plugin>
    
    展开全文
  • Java Object 对象拷贝

    2019-09-24 07:44:33
    Java Object 对象拷贝 @author ixenos JAVA 对象拷贝 Java里的clone分为:   1.浅拷贝:浅复制仅仅复制所考虑的对象,而不复制它所引用的对象,Object类里的clone方法是浅拷贝   2.深拷贝:深复制...

    Java Object 对象拷贝

    @author ixenos

     

     

     

    JAVA 对象拷贝


    Java里的clone分为:   

      1.浅拷贝:浅复制仅仅复制所考虑的对象,而不复制它所引用的对象,Object类里的clone方法是浅拷贝   

      2.深拷贝:深复制把要复制的对象及其所引用的对象都复制了一遍

      3.序列化深拷贝:把对象写到流里的过程是序列化(Serilization)过程,而把对象从流中读出来的过程则叫做反序列化(Deserialization)过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,利用这个特性,可以做深拷贝

     

    深拷贝时必须要遵循下面三点:
      1.在派生类中覆盖基类的clone()方法,并声明为public(Object类中的clone()方法为protected的)
      2.在派生类的clone()方法中,调用super.clone()
      3.在派生类中实现Cloneable接口

     

     

    示例


    浅拷贝的例子: 

    public class CloneTest  
    {  
      
        public static void main(String[] args) throws Exception  
        {  
            // teacher对象将被clone出来的Student对象共享.  
            Teacher teacher = new Teacher();  
            teacher.setAge(40);  
            teacher.setName("Teacher zhang");  
      
            Student student1 = new Student();  
            student1.setAge(20);  
            student1.setName("zhangsan");  
            student1.setTeacher(teacher);  
      
            // 复制出来一个对象student2  
            Student student2 = (Student) student1.clone();  
            System.out.println(student2.getAge());  
            System.out.println(student2.getName());  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
      
            // 修改student2的引用对象  
            student2.getTeacher().setAge(50);  
            student2.getTeacher().setName("Teacher Li");  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
        }  
    }  
      
    class Teacher  
    {  
        public int age;  
        public String name;  
      
        public int getAge()  
        {  
            return age;  
        }  
      
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
      
        public String getName()  
        {  
            return name;  
        }  
      
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
    }  
      
    class Student implements Cloneable  
    {  
      
        public int age;  
        public String name;  
        public Teacher teacher;  
      
        public int getAge()  
        {  
            return age;  
        }  
      
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
      
        public String getName()  
        {  
            return name;  
        }  
      
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
        public Teacher getTeacher()  
        {  
            return teacher;  
        }  
      
        public void setTeacher(Teacher teacher)  
        {  
            this.teacher = teacher;  
        }  
      
        @Override  
        public Object clone() throws CloneNotSupportedException  
        {  
            return super.clone();  
        }  
    }  
    输出结果为:  
    20  
    zhangsan  
    ~~~~~~~~~~~~~~~~~~~~~~  
    40  
    Teacher zhang  
    ~~~~~~~~~~~~~~~~~~~~~~  
    50  
    Teacher Li  
    View Code

     

    深拷贝例子:

    public class DeepCloneTest  
    {  
      
        public static void main(String[] args) throws Exception  
        {  
            // teacher对象将不被clone出来的Student对象共享.  
            Teacher teacher = new Teacher();  
            teacher.setAge(40);  
            teacher.setName("Teacher zhang");  
      
            Student student1 = new Student();  
            student1.setAge(20);  
            student1.setName("zhangsan");  
            student1.setTeacher(teacher);  
      
            // 复制出来一个对象student2  
            Student student2 = (Student) student1.clone();  
            System.out.println(student2.getAge());  
            System.out.println(student2.getName());  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
      
            // 修改student2的引用对象  
            student2.getTeacher().setAge(50);  
            student2.getTeacher().setName("Teacher Li");  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
        }  
    }  
      
    class Teacher implements Cloneable  
    {  
        public int age;  
        public String name;  
      
        public int getAge()  
        {  
            return age;  
        }  
      
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
      
        public String getName()  
        {  
            return name;  
        }  
      
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
        @Override  
        public Object clone() throws CloneNotSupportedException  
        {  
            return super.clone();  
        }  
      
    }  
      
    class Student implements Cloneable  
    {  
      
        public int age;  
        public String name;  
        public Teacher teacher;  
      
        public int getAge()  
        {  
            return age;  
        }  
      
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
      
        public String getName()  
        {  
            return name;  
        }  
      
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
        public Teacher getTeacher()  
        {  
            return teacher;  
        }  
      
        public void setTeacher(Teacher teacher)  
        {  
            this.teacher = teacher;  
        }  
      
        @Override  
        public Object clone() throws CloneNotSupportedException  
        {  
            Student student = (Student) super.clone();  
            // 将引用的对象teacher也clone下  
            student.setTeacher((Teacher) (student.getTeacher().clone()));          // student.getTeacher().clone()
            return student;  
        }  
    }  
      
    输出结果为:  
    20  
    zhangsan  
    ~~~~~~~~~~~~~~~~~~~~~~  
    40  
    Teacher zhang  
    ~~~~~~~~~~~~~~~~~~~~~~  
    40  
    Teacher zhang  
    View Code

     

    序列化深拷贝例子:

    import java.io.ByteArrayInputStream;  
    import java.io.ByteArrayOutputStream;  
    import java.io.ObjectInputStream;  
    import java.io.ObjectOutputStream;  
    import java.io.Serializable;  
    //利用序列化来做深复制  
    //深clone  
      
    public class DeepCloneTest  
    {  
      
        public static void main(String[] args) throws Exception  
        {  
            // teacher对象将不被clone出来的Student对象共享.  
            Teacher teacher = new Teacher();  
            teacher.setAge(40);  
            teacher.setName("Teacher zhang");  
      
            Student student1 = new Student();  
            student1.setAge(20);  
            student1.setName("zhangsan");  
            student1.setTeacher(teacher);  
      
            // 复制出来一个对象student2  
            Student student2 = (Student) student1.deepCopy();  
            System.out.println(student2.getAge());  
            System.out.println(student2.getName());  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
      
            // 修改student2的引用对象  
            student2.getTeacher().setAge(50);  
            student2.getTeacher().setName("Teacher Li");  
      
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~");  
            System.out.println(student1.getTeacher().getAge());  
            System.out.println(student1.getTeacher().getName());  
        }  
    }  
      
    class Teacher implements Serializable  
    {  
      
        private static final long serialVersionUID = -8834559347461591191L;  
      
        public int age;  
        public String name;  
      
        public int getAge()  
        {  
            return age;  
        }  
      
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
      
        public String getName()  
        {  
            return name;  
        }  
      
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
    }  
      
    class Student implements Serializable  
    {  
      
        // serialVersionUID  
        // 如果你的对象序列化后存到硬盘上面后,可是后来你却更改了类的field(增加或减少或改名),当你反序列化时,就会出现Exception的,这样就会造成不兼容性的问题。  
        // 但当serialVersionUID相同时,它就会将不一样的field以type的缺省值赋值(如int型的是0,String型的是null等),这个可以避开不兼容性的问题。所以最好给serialVersionUID赋值  
        private static final long serialVersionUID = 7991552226614088458L;  
      
        public int age;  
        public String name;  
        public Teacher teacher;  
        public int getAge()  
        {  
            return age;  
        }  
        public void setAge(int age)  
        {  
            this.age = age;  
        }  
        public String getName()  
        {  
            return name;  
        }  
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
        public Teacher getTeacher()  
        {  
            return teacher;  
        }  
      
        public void setTeacher(Teacher teacher)  
        {  
            this.teacher = teacher;  
        }  
        /**
         *    因为对象序列化会自然地对对象深拷贝,再利用“序列化-反序列化”读出
         */
        public Object deepCopy() throws Exception  
        {  
            // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝  
            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
      
            ObjectOutputStream oos = new ObjectOutputStream(bos);  
          //this很关键,引用当前对象,当然,这是值传递
            oos.writeObject(this);  
      
            // 将流序列化成对象  
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
      
            ObjectInputStream ois = new ObjectInputStream(bis);  
      
            return ois.readObject();  
        }  
    }  
      
    输出结果为:  
    20  
    zhangsan  
    ~~~~~~~~~~~~~~~~~~~~~~  
    40  
    Teacher zhang  
    ~~~~~~~~~~~~~~~~~~~~~~  
    40  
    Teacher zhang  
    View Code

     

     

    转载于:https://www.cnblogs.com/ixenos/p/5663965.html

    展开全文
  • java对象拷贝

    2011-12-18 22:43:28
    JAVA 对象拷贝 为什么需要有对象拷贝对象拷贝相对的自然是引用拷贝。java初学者经常会问,我这个方法要改变一个对象的属性,可以把参数传进去了,为什么没有改变了? ——基本数据类型传值,而对象传引用或...
    
    

    JAVA 对象拷贝

    为什么需要有对象拷贝?

    对象拷贝相对的自然是引用拷贝。java初学者经常会问,我这个方法要改变一个对象的属性,可以把参数传进去了,为什么没有改变了?

    ——基本数据类型传值,而对象传引用或引用的拷贝。

    而有时候我们要获取到一个当前状态的对象复制品,他们是两个独立对象。不再是引用或者引用拷贝(实质都是指向对象本身)。就是说a是b的拷贝,b发生变化的时候,不要影响a。


    对象拷贝有浅拷贝和深度拷贝两种。

    1)浅拷贝

    浅拷贝是指对象中基本数据类型得到拷贝,而引用数据类型并未拷贝。
    提到拷贝自然和clone联系起来了,所有具有clone功能的类都有一个特性,那就是它直接或间接地实现了Cloneable接口。
    否则,我们在尝试调用clone()方法时,将会触发CloneNotSupportedException异常。
    eg:

    1 public class DOG implements Cloneable
    2 {
    3 public DOG(String name, int age)
    4 {
    5 this .name = name;
    6 this .age = age;
    7 }

    8
    9 public String getName()
    10 {
    11 return this .name;
    12 }

    13
    14 public int getAge()
    15 {
    16 return this .age;
    17 }

    18
    19 public Object clone()
    20 {
    21 try
    22 {
    23 return super .clone();
    24
    25 }
    catch (CloneNotSupportedException e)
    26 {
    27 return null ;
    28 }

    29 }

    30
    31 public String name;
    32
    33 private int age;
    34
    35 // test
    36 public static void main(String[] args)
    37 {
    38 DOG dog1 = new DOG( " xiaogou " , 2 );
    39 DOG dog2 = (DOG) dog1.clone();
    40 dog1.name = " dagou " ;
    41 System.out.println(dog2.getName());
    42 System.out.println(dog2.getAge());
    43 System.out.println(dog1.getName());
    44 System.out.println(dog1.getAge());
    45
    46 }

    47
    48 }

    49



    运行结果:

    xiaogou
    2
    dagou
    2

    2)深度拷贝

    相对浅拷贝。实现对象中基本数据类型和引用数据类型的拷贝。

    请先看下面代码:

     

    1 class AAA
    2 {
    3 public AAA(String name)
    4 {
    5 this .name = name;
    6 }

    7
    8 public String name;
    9 }

    10
    11 class DOG implements Cloneable
    12 {
    13 public DOG(String name, int age, AAA birthday)
    14 {
    15 this .name = name;
    16 this .age = age;
    17 this .birthday = birthday;
    18 }

    19
    20 public String getName()
    21 {
    22 return name;
    23 }

    24
    25 public int getAge()
    26 {
    27 return age;
    28 }

    29
    30 public AAA getBirthday()
    31 {
    32 return birthday;
    33 }

    34
    35 public String getBirth(AAA a)
    36 {
    37 return a.name;
    38 }

    39
    40 public String name;
    41
    42 private int age;
    43
    44 public AAA birthday;
    45
    46 public Object clone()
    47 {
    48 try
    49 {
    50 super .clone();
    51 return super .clone();
    52 }
    catch (Exception e)
    53 {
    54 return null ;
    55 }

    56 }

    57 }

    58
    59 public class TestClone
    60 {
    61 public static void main(String[] args)
    62 {
    63 AAA Day = new AAA( " test " );
    64 DOG dog1 = new DOG( " xiaogou " , 2 , Day);
    65 DOG dog2 = (DOG) dog1.clone();
    66 // dog2.birthday = (AAA) dog1.birthday.clone();
    67 dog1.birthday.name = " 333 " ;
    68 System.out.println(dog1.getBirth(dog1.birthday));
    69 System.out.println(dog2.getBirth(dog2.birthday));
    70 }

    71 }

    72


    运行结果是:
    333
    333
    而真正要实现拷贝还的加点代码,如下请对比上面和下面代码的异同之处:

    1 class AAA implements Cloneable
    2 {
    3 public AAA(String name)
    4 {
    5 this .name = name;
    6 }

    7
    8 public Object clone()
    9 {
    10 try
    11 {
    12 super .clone();
    13 return super .clone();
    14 }
    catch (Exception e)
    15 {
    16 return null ;
    17 }

    18 }

    19
    20 public String name;
    21 }

    22
    23 class DOG implements Cloneable
    24 {
    25 public DOG(String name, int age, AAA birthday)
    26 {
    27 this .name = name;
    28 this .age = age;
    29 this .birthday = birthday;
    30 }

    31
    32 public String getName()
    33 {
    34 return name;
    35 }

    36
    37 public int getAge()
    38 {
    39 return age;
    40 }

    41
    42 public AAA getBirthday()
    43 {
    44 return birthday;
    45 }

    46
    47 public String getBirth(AAA a)
    48 {
    49 return a.name;
    50 }

    51
    52 public String name;
    53
    54 private int age;
    55
    56 public AAA birthday;
    57
    58 public Object clone()
    59 {
    60 try
    61 {
    62 super .clone();
    63 return super .clone();
    64 }
    catch (Exception e)
    65 {
    66 return null ;
    67 }

    68 }

    69 }

    70
    71 public class TestClone
    72 {
    73 public static void main(String[] args)
    74 {
    75 AAA Day = new AAA( " test " );
    76 DOG dog1 = new DOG( " xiaogou " , 2 , Day);
    77 DOG dog2 = (DOG) dog1.clone();
    78 dog2.birthday = (AAA) dog1.birthday.clone(); // 特别注意这里
    79 dog1.birthday.name = " 333 " ;
    80 System.out.println(dog1.getBirth(dog1.birthday));
    81 System.out.println(dog2.getBirth(dog2.birthday));
    82 }

    83 }

    84


    运行结果:
    333
    test
    这样基本就达到了我们当初的母的。


    但是明显的这种方法还是有许多不足,人们总是希望一个clone就是对象直接克隆。而上面还要对对象中的对象递归使用clone。下面提供一种更高级点的做法:

     

    1 import java.io. * ;
    2
    3 class AAA implements Serializable
    4 {
    5 public AAA(String name)
    6 {
    7 this .name = name;
    8 }

    9
    10 public String name;
    11 }

    12
    13 class DOG extends SerialCloneable
    14 {
    15 public DOG(String name, int age, AAA birthday)
    16 {
    17 this .name = name;
    18 this .age = age;
    19 this .birthday = birthday;
    20 }

    21
    22 public String getName()
    23 {
    24 return name;
    25 }

    26
    27 public int getAge()
    28 {
    29 return age;
    30 }

    31
    32 public AAA getBirthday()
    33 {
    34 return birthday;
    35 }

    36
    37 public String getBirth(AAA a)
    38 {
    39 return a.name;
    40 }

    41
    42 public String name;
    43
    44 private int age;
    45
    46 public AAA birthday;
    47
    48 public Object clone()
    49 {
    50 try
    51 {
    52 super .clone();
    53 return super .clone();
    54 }
    catch (Exception e)
    55 {
    56 return null ;
    57 }

    58 }

    59 }

    60
    61 public class TestClone
    62 {
    63 public static void main(String[] args)
    64 {
    65 AAA Day = new AAA( " test " );
    66 DOG dog1 = new DOG( " xiaogou " , 2 , Day);
    67 DOG dog2 = (DOG) dog1.clone();
    68 // dog2.birthday = (AAA) dog1.birthday.clone();
    69 dog1.birthday.name = " 333 " ;
    70 System.out.println(dog1.getBirth(dog1.birthday));
    71 System.out.println(dog2.getBirth(dog2.birthday));
    72 }

    73 }

    74
    75 class SerialCloneable implements Cloneable, Serializable
    76 {
    77 public Object clone()
    78 {
    79 try
    80 {
    81 ByteArrayOutputStream bout = new ByteArrayOutputStream();
    82 ObjectOutputStream out = new ObjectOutputStream(bout);
    83 out.writeObject( this );
    84 out.close();
    85 ByteArrayInputStream bin = new ByteArrayInputStream(bout
    86 .toByteArray());
    87 ObjectInputStream in = new ObjectInputStream(bin);
    88 Object ret = in.readObject();
    89 in.close();
    90 return ret;
    91 }
    catch (Exception e)
    92 {
    93 return null ;
    94 }

    95 }

    96 }

    97


    输出:
    333
    test

    上面的代码用序列化与反序列化实现了对象拷贝。比较通用。但是得注意的是其中的类得implements Serializable。

     

    展开全文
  • Java 对象拷贝

    2016-08-25 12:24:51
    2.利用Object的clone进行对象拷贝分为两种 a.浅拷贝:仅仅拷贝所考虑的对象,不拷贝引用的对象 b.深拷贝:不仅拷贝所考虑的对象,而且拷贝引用的对象 3.利用Object的clone进行对象拷贝,需要满足三个条件 a.类...

    1.java拷贝对象有两种方式
    a.使用java.lang.Object类中clone方法进行对象的拷贝
    b.利用序列化进行对象的拷贝
    2.利用Object的clone进行对象拷贝分为两种
    a.浅拷贝:仅仅拷贝所考虑的对象,不拷贝引用的对象
    b.深拷贝:不仅拷贝所考虑的对象,而且拷贝引用的对象
    3.利用Object的clone进行对象拷贝,需要满足三个条件
    a.类必须实现java.lang.Cloneable接口(否则拷贝对象时会抛出CloneNotSupportedException异常,不支持拷贝)
    b.类必须重写clone方法,并声明为public(否则非子类不能调用clone方法进行拷贝)
    c.类中clone方法中必须调用super.clone()
    4.利用Object的clone方法进行深拷贝

    //实现Cloneable接口
    class Student implements Cloneable {
        String studentName;
        Teacher teacher;
    
        public Student(String studentName, Teacher teacher) {
            this.studentName = studentName;
            this.teacher = teacher;
        }
    
        // 重写Object的clone方法,并在方法中使用super.clone()
        @Override
        public Object clone() {
            // 拷贝Student类
            Student student = null;
            try {
                student = (Student) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return student;
        }
    }
    
    // 实现Cloneable接口
    class Teacher implements Cloneable {
        String teacherName;
    
        public Teacher(String teacherName) {
            this.teacherName = teacherName;
        }
    
        // 重写Object的clone方法,并在方法中使用super.clone()
        @Override
        public Object clone() {
            Teacher teacher = null;
            try {
                teacher = (Teacher) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return teacher;
        }
    }
    
    public class CloneTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            // 创建一个老师
            Teacher teacher = new Teacher("老师");
            // 创建一个学生,并且引用老师
            Student student1 = new Student("学生", teacher);
            // 拷贝一个学生
            Student student2 = (Student) student1.clone();
            // 检查学生是否同一个对象
            System.out.println("检查两个学生对象:" + (student1 == student2));
            // 检查老师是否同一个对象
            System.out.println("检查两个老师对象:" + (student2.teacher== teacher));
        }
    }

    打印结果为:
    检查两个学生对象:false
    检查两个老师对象:true
    说明:只有学生对象被拷贝了,老师对象没有被拷贝,此拷贝方法为浅拷贝
    5.利用Object的clone方法进行深拷贝

    //实现Cloneable接口
    class Student implements Cloneable {
        String studentName;
        Teacher teacher;
    
        public Student(String studentName, Teacher teacher) {
            this.studentName = studentName;
            this.teacher = teacher;
        }
    
        // 重写Object的clone方法,并在方法中使用super.clone()
        @Override
        public Object clone() {
            // 拷贝Student类
            Student student = null;
            try {
                student = (Student) super.clone();
                // 获取Student类中的Teacher类进行进行拷贝
                student.teacher =(Teacher) student.teacher.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return student;
        }
    }
    
    // 实现Cloneable接口
    class Teacher implements Cloneable {
        String teacherName;
    
        public Teacher(String teacherName) {
            this.teacherName = teacherName;
        }
    
        // 重写Object的clone方法,并在方法中使用super.clone()
        @Override
        public Object clone() {
            Teacher teacher = null;
            try {
                teacher = (Teacher) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return teacher;
        }
    }
    
    public class CloneTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            // 创建一个老师
            Teacher teacher = new Teacher("老师");
            // 创建一个学生,并且引用老师
            Student student1 = new Student("学生", teacher);
            // 拷贝一个学生
            Student student2 = (Student) student1.clone();
            // 检查学生是否同一个对象
            System.out.println("检查两个学生对象:" + (student1 == student2));
            // 检查老师是否同一个对象
            System.out.println("检查两个老师对象:" + (student2.teacher== teacher));
        }
    }

    打印结果为:
    检查两个学生对象:false
    检查两个老师对象:false
    说明:学生和老师对象都被拷贝了,此拷贝方法为深拷贝
    6.利用序列化(Serializable)实现拷贝对象
    a.如需对序列化详细了解,请点击传送门
    b.使用序列化拷贝对象

    class Student implements Serializable {
        private static final long serialVersionUID = -5734927474270419167L;
        String studentName;
        Teacher teacher;
    
        public Student(String studentName, Teacher teacher) {
            this.studentName = studentName;
            this.teacher = teacher;
        }
    
    }
    
    // 实现Serializable接口
    class Teacher implements Serializable {
        private static final long serialVersionUID = -8357235700226262125L;
        String teacherName;
    
        public Teacher(String teacherName) {
            this.teacherName = teacherName;
        }
    }
    
    public class CloneTest {
        public static void main(String[] args) throws Exception {
            // 创建一个老师
            Teacher teacher = new Teacher("老师");
            // 创建一个学生,并且引用老师
            Student student1 = new Student("学生", teacher);
            // 序列化
            FileOutputStream fos = new FileOutputStream("Student.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(student1);
            // 反序列化
            FileInputStream fis = new FileInputStream("Student.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Student student2 = (Student) ois.readObject();
            // 检查学生是否同一个对象
            System.out.println("检查两个学生对象:" + (student1 == student2));
            // 检查老师是否同一个对象
            System.out.println("检查两个老师对象:" + (student2.teacher == teacher));
            oos.close();
            ois.close();
        }
    }

    打印结果为:
    检查两个学生对象:false
    检查两个老师对象:false
    说明:使用序列化学生和老师对象都被拷贝了,此拷贝方法为深拷贝

    展开全文
  • Java对象拷贝

    2019-02-21 21:35:00
    Java对象拷贝分为浅拷贝(shadow copy )和深拷贝(deep copy)。 浅拷贝:被复制对象的任何变量都含有和原来的对象相同的值,而任何的对其他对象的引用仍然指向原来的对象。对拷贝后的引用的修改,还能影响原来的对象。...
  • JAVA对象拷贝

    2011-08-30 21:12:44
    JAVA 对象拷贝 为什么需要有对象拷贝对象拷贝相对的自然是引用拷贝。java初学者经常会问,我这个方法要改变一个对象的属性,可以把参数传进去了,为什么没有改变了? ——基本数据类型传值,而对象传引用或...
  • java对象拷贝,对象数组拷贝封装

    千次阅读 2020-12-06 09:57:12
    通过BeanUtils功能,手动封装一下,实现多对象拷贝 继承BeanUtils package com.example.start.common.utils.beancopyutil; import org.springframework.beans.BeanUtils; import java.util.ArrayList; import ...
  • JAVA 对象拷贝

    2017-02-26 22:44:40
    1.Java里的clone分为:  ...Java对象的克隆,为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。必须要遵循下面三点  1.在派生类中覆盖基类的clone()方法,并声明为public【Object类中的cl
  • 其中record的被转化的对象 CourseChapterPeriodPicVO是转化成的对象 就是把record转化为CourseChapterPeriodPicVO BeanUtil.copyProperties(schoolFileInfos, SchoolFileInfoDTO.class); 这是list之间的转

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,308
精华内容 2,923
关键字:

对象拷贝java

java 订阅