精华内容
下载资源
问答
  • 主要介绍了Java对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下
  • 主要介绍了java 对象的克隆的相关资料,这里对浅克隆和深克隆进行了实例分析需要的朋友可以参考下
  • Java实现对象深度克隆

    2021-03-07 15:44:56
    实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io....

    两种方式:
      1). 实现Cloneable接口并重写Object类中的clone()方法;
      2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class MyUtil {
    
        private MyUtil() {
            throw new AssertionError();
        }
    
        @SuppressWarnings("unchecked")
        public static <T extends Serializable> T clone(T obj) throws Exception {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bout);
            oos.writeObject(obj);
    
            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bin);
            return (T) ois.readObject();
    
            // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
            // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
        }
    }
    class Student implements Cloneable{
        private String name;
        private int age;
        private StudentClass studentClass;
        private List<String> list = new ArrayList<>();
        
        public Student() {
            // TODO Auto-generated constructor stub
            System.out.println("构造方法被调用");
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public StudentClass getStudentClass() {
            return studentClass;
        }
     
     
        public void setStudentClass(StudentClass studentClass) {
            this.studentClass = studentClass;
        }
        
        public void add(String aa){
            this.list.add(aa);
        }
     
     
        @Override
        public Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            Student stu = (Student) super.clone();
            
            return stu;
        }
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + ",class"+studentClass.getStudentClass()+",list"+list+"]";
        }
        
    }

     

    展开全文
  • 在本篇文章中我们给大家分享了关于java对象中浅克隆和深克隆的相关知识点和相关代码内容,有兴趣的朋友们学习下。
  • java中实现对象的深度克隆

    千次阅读 2018-08-03 10:08:25
    python中有深度拷贝(也可以叫深度克隆)和浅拷贝,同样在java中很多时候需要深度拷贝对象,所谓的深度拷贝对象指的就是对于对象的所用数据及其全部进行copy一份,变成两个完全不相关的对象,而浅拷贝不拷贝对象...

    1.什么是深度拷贝和浅拷贝       

           python中有深度拷贝(也可以叫深度克隆)和浅拷贝,同样在java中很多时候需要深度拷贝对象,所谓的深度拷贝对象指的就是对于对象的所用数据及其全部进行copy一份,变成两个完全不相关的对象,而浅拷贝不拷贝对象所用的数据资源等,虽是两个不同的参数标识符,但是用的是同一个数据对象,也就是用‘==’,这是浅拷贝。也就是C语言中形容的指针指向的物理存储区域对象其实是一个。

          带来的问题:浅拷贝无论你通过任何浅拷贝的对象修改其值,最后的其他的对象都会被改变,相信我,这是一个很常见的坑。

    2.java对象的深度拷贝

            其实java中的很多对象已经实现了深度拷贝,比如说map中的putAll(),但是需要实现自己创建的对象的深度拷贝呢,山不转水转,总会碰到的。

           下面来说明一下java中的深度拷贝,其最佳的方式就是实现Serializable接口,用序列化和反序列化来实现对象的深度拷贝,所谓的序列化和反序列化简单说明下,序列化指的就是把对象直接转化成文件或者其他持久层数据(二进制文件,字节码文件),反序列化指的就是读出该数据,重新建立对象的过程。因为java中的JVM虚拟机是有生命周期的,所以说任何对象的生命周期不会超过当前的JVM虚拟机的生命周期,所以需要序列化和反序列化,解决办法就是给其Serializable中有一个ID值,是不是原来一看到别人写的Serializable就不知道东南西北了,这个表示的就是版本号,防止错乱嘛。下面来介绍一下java对象的深度克隆。

    3.java中的实现及其原理分析

           java中的对象的深度克隆主要的原理就是实现对象的字节流转换,然后在把当前的字节流对象输出,得到新的对象。代码:

    public Object deepClone() {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();//字节流对象
                    ObjectOutputStream oos = new ObjectOutputStream(bos);//开始转换该对象
                    oos.writeObject(this);//写到当前类,当然也可以写入文件
                    ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());//字节输出流
                    ObjectInputStream ois = new ObjectInputStream(bais);//输出该对象
                    return (Object) ois.readObject();//读出对象,实现新对象的生成
                } catch (Exception e) {
                    System.out.println("克隆出错"+e.getStackTrace());
                    return null;
                }
            }
        }

    4.测试结果代码

    原理实际上非常的简单,下面来测试一下,完整的代码:

    package java_test;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;


    public class study implements Serializable{
        private static final long serialVersionUID = 1L;
        public static  int arr[] = {1,2};
        
        public static class class1 {//内部类,也是我们克隆的对象

            public Object deepClone() {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(bos);
                    oos.writeObject(this);
                    ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    return (Object) ois.readObject();
                } catch (Exception e) {
                    System.out.println("克隆出错"+e.getStackTrace());
                    return null;
                }
            }
        }
        
        public static void main(String[] args) {//验证一下克隆前和克隆后是不是一个对象
            class1 c = new class1();
            Object c2 = c;
            if (c == c2){
                System.out.println("克隆前c和出c2相等,也就是c和c2其实是一个对象!");
            }else{
                System.out.println("克隆前c和出c2不相等,出现理论不符合逻辑错误!");
            }
            c2 = c.deepClone();
            
            if (c == c2){
                System.out.println("深度克隆失败");
            }else{
                System.out.println("深度克隆成功");
            }
        }
    }

    结果:

    测试程序,本文观点来自个人理解,有不足之处请之处,希望不吝赐教。

    展开全文
  • 本篇文章是对JAVA对象深度克隆进行了详细的分析介绍,需要的朋友参考下
  • 要实现对象克隆,必须满足一下两个条件:1、实现Cloneable接口;2、重新定义clone方法,并指定public访问修饰符。class Vehicle implements Cloneable //浅克隆{ public Vehicle clone() throws ...

    要实现对象的克隆,必须满足一下两个条件:

    1、实现Cloneable接口;

    2、重新定义clone方法,并指定public访问修饰符。

    class Vehicle implements Cloneable  //浅克隆

    {

        public Vehicle clone() throws CloneNotSupportedException

        {

            return (Vehicle) super.clone();

        }

    }

    当为一个引用了对象的变量建立副本时,原变量和副本都是同一个对象的引用,这说明,任何一个变量改变都会影响另一个变量。

    Vehicle original = new Vehicle();

    Vehicle copy = original;

    copy.engine(11) //当设置copy的engine属性的时候,original变量的engine属性也会随着改变。


    如果希望copy是一个新的对象,它的初始状态和original相同,但之后各自会有不同的状态,这种情况下就可以使用clone方法。

    Vehicle original = new Vehicle();

    Vehicle copy = original.clone();

    copy.engine(11)//当设置copy的engine属性的时候,original变量的engine属性不会改变。


    此种克隆模式为浅克隆,如果对象中的所有数据域都是数值或其他基本类型,拷贝这些域是没有任何问题,但如果对象包含子对象的引用,拷贝域就会得到相同子对象的另一个引用,这样原对象和克隆对象仍然会共享一些信息。即在现有Vehicle对象添加一个新的数据域public Driver driver,再使用浅克隆时,driver变量还是会引用同一个对象。


    那么此时,如果想让数据域不共享信息,就要用到深克隆

    class Vehicle implements Cloneable

    {

        public int engine;

        public Driver driver;   //对象;

        public Vehicle clone() throws CloneNotSupportedException

        {

            Vehicle cloned = (Vehicle) super.clone();

            cloned.driver = (Driver) driver.clone();

            return cloned;

        }

    }


    此文是小编参考《Java核心技术 卷 I》第六章第二节对象克隆 整理而成。

    展开全文
  • Java对象克隆——浅克隆和深克隆的区别

    万次阅读 多人点赞 2017-08-06 00:51:35
    Java对象的克隆有深克隆和浅克隆之分。有这种区分的原因是Java中分为基本数据类型和引用数据类型,对于不同的数据类型在内存中的存储的区域是不同的。基本数据类型存储在栈中,引用数据类型存储在堆中。 ...

    Java中对象的克隆有深克隆和浅克隆之分。有这种区分的原因是Java中分为基本数据类型和引用数据类型,对于不同的数据类型在内存中的存储的区域是不同的。基本数据类型存储在栈中,引用数据类型存储在堆中。

    什么是克隆

    克隆就是依据已经有的数据,创造一份新的完全一样的数据拷贝。

    实现克隆有多种方式,可以手工的new出一个新的对象,然后将原来的对象信息一个一个的set到新的对象中。还有就是使用clone方法。使用clone方法必须满足:

    1. 实现Cloneable接口

    2. 使用public访问修饰符重新定义clone方法。

    在不使用克隆方法时,将类A的实例A1直接赋给类A的新实例A2时会出现这样的情况,修改A2的属性,A1的属性也发生了改变。这是因为赋值操作之后,A1A2指向同一个对象,就像是使用不同的显示器操作同一个服务器一样,两个显示器显示的都是一个服务器上的内容。

    1. 浅克隆

    对于一个只含有基本数据类型的类来说使用clone方法,是完全没有问题的,用图表来表示该情形的clone操作:

    Customer  customer2=customer1.clone();

    customer1

    ID

    123

    age

    23

    customer2

    ID

    123

    age

    23

    customer2.setAge(32);

    customer1

    ID

    123

    age

    23

    customer2

    ID

    123

    age

    32

    clonecustomer1customer2之间数据互不影响。

    但是如果在Customer类中有一个引用类型的属性Address呢?

    [java]  view plain  copy
     print ?
    1. public static void main(String[] args) throws CloneNotSupportedException {  
    2.         Address address = new Address("CH" , "SD" , "QD");  
    3.         Customer customer1 = new Customer(1 , 23 , address);  
    4.         Customer customer2 = customer1.clone();  
    5.         customer2.getAddress().setCity("JN");  
    6.         customer2.setID(2);  
    7.         System.out.println("customer1:"+customer1.toString());  
    8.         System.out.println("customer2:"+customer2.toString());  
    9.     }  
    10. }  
    11. class Customer implements Cloneable{  
    12.     public int ID;  
    13.     public int age;  
    14.     public Address address;  
    15.     public int getID() {  
    16.         return ID;  
    17.     }  
    18.     public void setID(int iD) {  
    19.         ID = iD;  
    20.     }  
    21.     public int getAge() {  
    22.         return age;  
    23.     }  
    24.     public void setAge(int age) {  
    25.         this.age = age;  
    26.     }  
    27.     public Address getAddress() {  
    28.         return address;  
    29.     }  
    30.     public void setAddress(Address address) {  
    31.         this.address = address;  
    32.     }  
    33.     public Customer(int iD, int age, Address address) {  
    34.         super();  
    35.         ID = iD;  
    36.         this.age = age;  
    37.         this.address = address;  
    38.     }  
    39.     @Override  
    40.     public String toString() {  
    41.         return "Customer [ID=" + ID + ", age=" + age + ", address=" + address  
    42.                 + "]";  
    43.     }  
    44.     @Override  
    45.     public Customer clone() throws CloneNotSupportedException {  
    46.         return (Customer) super.clone();  
    47.     }  
    48. }  
    49. class Address{  
    50.     private String country;  
    51.     private String province;  
    52.     private String city;  
    53.     public String getCountry() {  
    54.         return country;  
    55.     }  
    56.     public void setCountry(String country) {  
    57.         this.country = country;  
    58.     }  
    59.     public String getProvince() {  
    60.         return province;  
    61.     }  
    62.     public void setProvince(String province) {  
    63.         this.province = province;  
    64.     }  
    65.     public String getCity() {  
    66.         return city;  
    67.     }  
    68.     public void setCity(String city) {  
    69.         this.city = city;  
    70.     }  
    71.     @Override  
    72.     public String toString() {  
    73.         return "Address [country=" + country + ", province=" + province  
    74.                 + ", city=" + city + "]";  
    75.     }  
    76.     public Address(String country, String province, String city) {  
    77.         super();  
    78.         this.country = country;  
    79.         this.province = province;  
    80.         this.city = city;  
    81.     }  
    82. }  
    83. //输出的结果是:  
    84. //customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=JN]]  
    85. //customer2:Customer [ID=2, age=23, address=Address [country=CH, province=SD, city=JN]]  

    上面分析得到,clone后新旧对象互不影响,customer2修改了id后没有影响到customer1,但是修改了customer2address属性的city值为JN后,发现customer1address值也发生了改变。这样就没有达到完全复制、相互之间完全没有影响的目的。这样就需要进行深克隆。

    2.深克隆

    深克隆与浅克隆的区别就是,浅克隆不会克隆原对象中的引用类型,仅仅拷贝了引用类型的指向。深克隆则拷贝了所有。也就是说深克隆能够做到原对象和新对象之间完全没有影响。

    而深克隆的实现就是在引用类型所在的类实现Cloneable接口,并使用public访问修饰符重写clone方法。

    上面的代码做以下修改:

    1Address类实现Cloneable接口,重写clone方法;

    [java]  view plain  copy
     print ?
    1. @Override  
    2. public Address clone() throws CloneNotSupportedException {  
    3.     return (Address) super.clone();  
    4. }  

    2.Customer类的clone方法中调用Address类的clone方法。

    [java]  view plain  copy
     print ?
    1. @Override  
    2. public Customer clone() throws CloneNotSupportedException {  
    3.     Customer customer = (Customer) super.clone();  
    4.     customer.address = address.clone();  
    5.     return customer;  
    6. }  

    修改后测试代码的输出结果:

    customer1:Customer[ID=1, age=23, address=Address [country=CH, province=SD, city=QD]]

    customer2:Customer[ID=2, age=23, address=Address [country=CH, province=SD, city=JN]]

    发现customer2无论如何修改,customer1都没有受到影响。

    实现深克隆的另一种方法就是使用序列化,将对象写入到流中,这样对象的内容就变成了字节流,也就不存在什么引用了。然后读取字节流反序列化为对象就完成了完全的复制操作了。

    [java]  view plain  copy
     print ?
    1.         Address address = new Address("CH" , "SD" , "QD");  
    2.         Customer customer1 = new Customer(1 , 23 , address);  
    3.         Customer customer2 = (Customer) cloneObject(customer1);  
    4.         customer2.getAddress().setCity("JN");  
    5.         customer2.setID(2);  
    6.         System.out.println("customer1:"+customer1.toString());  
    7.         System.out.println("customer2:"+customer2.toString());  
    8. //customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=QD]]  
    9. //customer2:Customer [ID=2, age=23, address=Address [country=CH, province=SD, city=JN]]  

    cloneObject方法的定义:

    [java]  view plain  copy
     print ?
    1. public static Object cloneObject(Object obj) throws IOException, ClassNotFoundException{  
    2.     ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
    3.     ObjectOutputStream out = new ObjectOutputStream(byteOut);  
    4.     out.writeObject(obj);   
    5.     ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
    6.     ObjectInputStream in =new ObjectInputStream(byteIn);  
    7.     return in.readObject();  
    8. }  

    个人的理解是Java中定义的clone没有深浅之分,都是统一的调用Objectclone方法。为什么会有深克隆的概念?是由于我们在实现的过程中刻意的嵌套了clone方法的调用。也就是说深克隆就是在需要克隆的对象类型的类中全部实现克隆方法。就像是toString方法一样,假如上面的Customer类中重写了toString方法,而Address类没有进行重写,就会出现这样的输出语句:

    customer1:Customer[ID=1, age=23, address=com.gos.java.standard.Address@38d8fb2b]

    只有在Address类也重写了toString方法才会打印出完全的信息:

    customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=QD]]

    只不过在打印的操作中就默认的调用了对象的toString方法,而clone方法需要在代码中显式的调用。

    总结:

    1.浅克隆:只复制基本类型的数据,引用类型的数据只复制了引用的地址,引用的对象并没有复制,在新的对象中修改引用类型的数据会影响原对象中的引用。
    2.深克隆:是在引用类型的类中也实现了clone,是clone的嵌套,复制后的对象与原对象之间完全不会影响。
    3.使用序列化也能完成深复制的功能:对象序列化后写入流中,此时也就不存在引用什么的概念了,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。
    4.使用clone实现的深克隆其实是浅克隆中嵌套了浅克隆,与toString方法类似

    展开全文
  • 复制:内存复制,两种方法: 1. 自己写代码,以前就这么干的。。 public static <T> T deepCopy(T src) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteOut = new ...
  • java对象复制克隆

    2013-10-28 08:52:09
    深度复制Java对象实例,复制后对象属性值改变不影响被复制对象,有注释
  • 彻底理解Java深克隆和浅克隆的原理及实现 Java 面试:对象克隆 如何拷贝对象 ...Java对象克隆——浅克隆和深克隆的区别 Java深克隆和浅克隆的原理及实现 为什么要对象克隆? 克隆的对象可能包含一...
  • 本文详细介绍了Java中的浅克隆和深克隆的概念,及案例演示如何实现深克隆
  • Java 浅/深克隆、克隆数组

    千次阅读 2019-05-30 13:55:10
    Java 浅/深克隆、克隆数组。及,示例代码演示。
  • Java实现深克隆的三种方式

    千次阅读 2019-11-15 17:14:13
    大家都知道,Java中的克隆有深克隆和浅克隆,今天我们谈谈深克隆的几种实现方式。 首先,我们先谈谈浅克隆的实现 一、浅克隆 Java中实现浅克隆主要就是要实现Cloneable接口,然后返回克隆对象。 假设,现在我们...
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址; 异同点: 深浅克隆都会在堆中新分配一块区域; 区别在于对象属性引用的对象是否需要进行克隆(递归性的)。 示例 pos:...
  • 主要介绍了Java编程实现对象克隆(复制)代码详解,涉及了克隆的原因,如何实现克隆,克隆的一般步骤,深克隆与浅克隆的介绍等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
  • Java语言里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与拷贝。浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。而拷贝则是拷贝了源对象的所有值,所以即使源...
  • Java如何实现对象克隆

    千次阅读 2019-03-24 11:16:30
    Java中的对象克隆
  • 对象克隆库。 支持可扩展的浅层和深层对象克隆策略。 用法 下面是一个关于如何使用库的示例 // Example TestObject clone = new ObjectCloner().deepClone(originalTestObject); 有关更多示例,请参阅 junit 测试...
  • 通常子对象是可变的,必须重新定义clone方法来建立一个拷贝,同时克隆所有的子对象。在这个例子中,hireDay域是一个Date,这时可变的,所以他也需要克隆。(处于这个原因,这个例子使用Date类型的域而不是...
  • java序列化深克隆 开发人员经常依靠3d方库来避免重新发明轮子,尤其是在Java世界中,Apache和Spring这样的项目如此盛行。 在处理这些框架时,我们通常很少或根本无法控制其类的行为。 这有时会导致问题。 例如,...
  • Java对象深克隆与浅克隆详解.zip
  • Java对象深克隆和浅克隆

    千次阅读 2019-06-03 10:57:13
    克隆: 只copy对象引用,不copy对象本身。即对象地址不变,仍然只存在一个对象。 例如: User user1 = new User; User user2 = user1; 这里引用类型对象地址不变,只是将user2的引用指向user1的地址。 浅...
  • 因为我最近无意间看到了一些项目的代码,不管是曾经编码的人还是新接手的人, 在想完全克隆复制一个已经存在的对象,做为后续的使用,竟然都是采取了重写new一个,然后一个个属性字段值get出来再set回去,这种代码段...
  • 使用复制构造函数和防御性复制方法进行的Java对象克隆当然具有某些优势,但是我们必须显式编写一些代码才能在所有这些方法中实现深度克隆。 而且,仍然有可能我们会错过某些东西并且不会得到深克隆的对象。 正如...
  • 实现Cloneable接口实现深克隆和浅克隆3.1 浅克隆实现3.2 深克隆实现4.实现Serializable接口,实现深克隆5.org.apache.commons中BeanUtils和PropertyUtils工具类实现深克隆 如何实现对象克隆? 1.答案: 答:有两种...
  • 首先导入依赖 <!--fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version>...pub
  • Java实现对象克隆的方法

    千次阅读 2019-06-20 17:27:26
    本文首发于cartoon的博客      转载请注明出处:...当时只说了拷贝以及浅拷贝,面试...
  • JAVA clone方法-深复制(深克隆)&浅复制(浅克隆)

    万次阅读 多人点赞 2018-08-02 18:09:10
    在对某个对象更新保存数据操作,对象关联某个文件需要将对象更新到数据库后再判断文件是否更新(文件存储到专门的文件系统中,对象保持文件的访问路径),如果文件更新了,那么就需要上传对象原来的文件,因此需要...
  • 遇到一个需求,进入界面以后,从服务器得到数据,定义成一个类,在点击提交按钮之前,对类的数据...在提交之前,需要用新类与本地类进行对比,看是否已变化不应该使用=赋值,因为对象使用=赋值,两个对象指向同一个地址

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,679
精华内容 9,471
关键字:

java对象的深克隆

java 订阅