精华内容
下载资源
问答
  • 主要介绍了Java编程实现对象克隆复制)代码详解,涉及了克隆的原因,如何实现克隆,克隆的一般步骤,深克隆与浅克隆的介绍等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
  • 本文实例讲述了php实现对象克隆的方法。分享给大家供大家参考。具体如下: <?php //定义类staff,其中包括属性id和name class staff { private $id; private $name; function setID($id) { $this->id = ...
  • Java如何实现对象克隆

    千次阅读 2019-03-24 11:16:30
    Java中的对象克隆

    将A对象的值分别通过set方法加入B对象中

    Student stu1 = new Student();  
    stu1.setNumber(12345);  
    Student stu2 = new Student();  
    stu2.setNumber(stu1.getNumber());
    

    实现Cloneable接口并重写Object类中的clone()方法

    浅克隆:当对象被复制时,只复制对象本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

    public class Student implements Cloneable {
    
      private int number;
    
      public int getNumber() {
        return number;
      }
    
      public void setNumber(int number) {
        this.number = number;
      }
    
      //实现clone接口
      @Override
      public Object clone() {
        Student stu = null;
        try {
          //浅克隆
          stu = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
          e.printStackTrace();
        }
    
        return stu;
      }
    
      //测试克隆
      public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.setNumber(12345);
        Student stu2 = (Student) stu1.clone();
        System.out.println("学生1:  "+stu1.getNumber());
        System.out.println("学生2:  "+stu2.getNumber());
    
        stu2.setNumber(54321);
        System.out.println("学生1:  "+stu1.getNumber());
        System.out.println("学生2:  "+stu2.getNumber());
      }
    }
    

    结果:

    学生1: 12345

    学生2: 12345

    学生1: 12345

    学生2: 54321

    深克隆:将原型对象的所有引用对象也复制一份给克隆对象。

    public class Student implements Cloneable {
    
      private int number;
      private Address add;
    
      //get、set方法
    
      @Override
      public Object clone() {
        Student stu = null;
        try {
          //浅复制
          stu = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
          e.printStackTrace();
        }
        //深度复制
        stu.add = (Address) add.clone();
    
        return stu;
      }
    
      public static void main(String[] args) {
        Address add = new Address();
        add.setAdd("北京市");
        Student stu1 = new Student();
        stu1.setNumber(12345);
        stu1.setAdd(add);
    
        Student stu2 = (Student) stu1.clone();
        System.out.println("学生1:  " + stu1.getNumber() + ",地址:  " + stu1.getAdd().getAdd());
        System.out.println("学生2:  " + stu2.getNumber() + ",地址:  " + stu2.getAdd().getAdd());
    
        add.setAdd("杭州市");
        System.out.println("学生1:  " + stu1.getNumber() + ",地址:  " + stu1.getAdd().getAdd());
        System.out.println("学生2:  " + stu2.getNumber() + ",地址:  " + stu2.getAdd().getAdd());
    
      }
    }
    
    class Address implements Cloneable {
      private String add;
    
      //get、set方法
    
      @Override
      protected Object clone() {
        Address add = null;
        try {
          add = (Address) super.clone();
        } catch (CloneNotSupportedException e) {
          e.printStackTrace();
        }
        return add;
      }
    }
    

    实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

    import java.io.Serializable;
    
    public class Car implements Serializable {
    
      private static final long serialVersionUID = 6880783148707693267L;
    
      //品牌
      private String brand;
      //最高时速
      private int maxSpeed;
    
      public Car(String brand, int maxSpeed) {
        this.brand = brand;
        this.maxSpeed = maxSpeed;
      }
    
      //get、set方法
        //重写toString方法  
    }
    
    import java.io.Serializable;
    
    public class Person implements Serializable {
    
      private static final long serialVersionUID = 7592930394427200495L;
    
      //姓名
      private String name;
      //年龄
      private int age;
      //座驾
      private Car car;
    
      public Person(String name, int age, Car car) {
        this.name = name;
        this.age = age;
        this.car = car;
      }
    
      //get、set方法
      //重写toString方法
    }
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class CloneUtil {
    
      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();
      }
    }
    

    调用ByteArrayOutputStreamByteArrayInputStream对象的close方法没有任何意义。这两个基于内存的流只要垃圾收集器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放。

    public class CloneTest {
    
      public static void main(String[] args) throws Exception {
        Person person = new Person("lisi", 18, new Car("BMW", 300));
        Person person1 = CloneUtil.clone(person);
        person1.getCar().setBrand("BYD");
      }
    }
    

    修改克隆的Person对象person1关联的汽车对象的品牌属性,原来的Person对象person关联的汽车不会受到任何影响,因为在克隆Person对象时其关联的汽车对象也被克隆了。

    基于序列化和反序列化实现的克隆不仅仅时深度克隆,更重要的是通过范型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译期完成的,不是在运行时抛出异常,这种方案明显优于使用Object类的clone方法克隆对象。

    通过org.apache.commons中的工具类BeanUtilsPropertyUtils进行对象复制

    try {
      Student stu1 = new Student();
      stu1.setNumber(12345);
      Student stu2 = new Student();
      BeanUtils.copyProperties(stu2, stu1);
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    
    try {
      Student stu1 = new Student();
      stu1.setNumber(12345);
      Student stu2 = new Student();
      PropertyUtils.copyProperties(stu2, stu1);
      catch (NoSuchMethodException e) {
        e.printStackTrace();
      }
    

    BeanUtils提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而PropertyUtils不支持这个功能,但是速度会更快一些。在实际开发中,BeanUtils使用更普遍一点,犯错的风险更低一点。

    展开全文
  • 如何实现对象克隆

    千次阅读 2019-06-04 11:08:41
    情景:在我们实际的开发过程中,一个对象A中已经包含了一些有用的信息,现在我需要复制A的内容到B。...1.实现Cloneable接口,并重写object类中的clone方法,可以实现克隆,也可以实现深度克隆。 2.实现...

    情景:在我们实际的开发过程中,一个对象A中已经包含了一些有用的信息,现在我需要复制A的内容到B。使得A和B对象是完全两个不同的内存地址,修改一个对象的值,不会影响到另外一个。

    在java中如果单单采用复制的方式是不行的,只会让A和B同时指向一个内存地址,互相影响。

    解决:

    1.实现Cloneable接口,并重写object类中的clone方法,可以实现浅克隆,也可以实现深度克隆。

    2.实现Serializable,通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆。

    3.利用BeanUtils,apache和spring都提供了这个bean工具。只是他也是浅克隆。

    具体的会列出文章,展开讨论,这里就不做过多的描述了。

    展开全文
  • Java实现对象克隆的方法

    千次阅读 2019-06-20 17:27:26
    JAVA对象克隆共有两种形式,三种方法 浅克隆 调用clone方法 深克隆 递归调用clone方法 序列化对象 三种方法之间互有优缺点,具体采用要根据实际情况。

    本文首发于cartoon的博客     
    转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/java%E5%AE%9E%E7%8E%B0%E5%85%8B%E9%9A%86%E7%9A%84%E6%96%B9%E6%B3%95/

    前言

    这也是昨天的面试题。

    当时只说了深拷贝以及浅拷贝,面试官问了两遍还有吗,我很肯定的说就这两种了,面试结束之后查了一下,啪啪打脸。

    正文

    JAVA实现克隆有两种形式

    • 浅克隆

    • 深克隆

    浅克隆与深克隆的区别

    JAVA将数据类型分为基本数据类型以及引用数据类型,我认为浅克隆与深克隆的区别主要在于对引用类型的成员属性的操作。深度克隆应该递归克隆引用类型的成员属性。

    浅克隆实现
    • 实现Cloneable接口

    • 重写clone方法,调用父类的clone方法

    代码

    public class Text implements Cloneable{
     ​
      private int age;
     ​
      private Name name;
     ​
      public int getAge() {
      return age;
      }
     ​
      public void setAge(int age) {
      this.age = age;
      }
     ​
      public Name getName() {
      return name;
      }
     ​
      public void setName(Name name) {
      this.name = name;
      }
     ​
      @Override
      protected Object clone(){
      try {
      return super.clone();
      } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      }
      return null;
      }
     }
     ​
     class Name{
      private String name;
     ​
      public String getName() {
      return name;
      }
     ​
      public void setName(String name) {
      this.name = name;
      }
     }
     ​
     public class Main {
     ​
      public static void main(String[] args){
      Name name1=new Name();
      name1.setName("name1");
      Text t1=new Text();
      t1.setAge(12);
      t1.setName(name1);
      Text t2=(Text) t1.clone();
      System.out.println(t2.getName().getName());
      name1.setName("name2");
      System.out.println(t2.getName().getName());
     ​
      }
     ​
     }
    

    输出

    name1
    name2
    

    结果分析

    因为只是直接调用父类的clone方法,没有对成员属性进行处理,所以在修改t1属性name的值时,t2属性name的值也会随之改变。

    优点

    简单易实现

    缺点

    无法真正克隆对象

    深克隆实现
    通过递归克隆实现

    代码

     public class Text implements Cloneable{
     ​
      private int age;
     ​
      private Name name;
     ​
      public int getAge() {
      return age;
      }
     ​
      public void setAge(int age) {
      this.age = age;
      }
     ​
      public Name getName() {
      return name;
      }
     ​
      public void setName(Name name) {
      this.name = name;
      }
     ​
      @Override
      protected Object clone(){
      Text text=null;
      try {
      text=(Text) super.clone();
      } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      }
      text.setName((Name) text.getName().clone());
      return text;
      }
     }
     ​
     class Name implements Cloneable{
      private String name;
     ​
      public String getName() {
      return name;
      }
     ​
      public void setName(String name) {
      this.name = name;
      }
     ​
      @Override
      protected Object clone() {
      try {
      return super.clone();
      } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      }
      return null;
      }
     }
    

    输出

    name1
    name1
    
    通过序列化实现

    代码

     public class Text implements Serializable{
     ​
      private static final long serialVersionUID = 8723901148964L;
     ​
      private int age;
     ​
      private Name name;
     ​
      public int getAge() {
      return age;
      }
     ​
      public void setAge(int age) {
      this.age = age;
      }
     ​
      public Name getName() {
      return name;
      }
     ​
      public void setName(Name name) {
      this.name = name;
      }
     ​
      public Object myClone(){
      Text text=null;
      ByteArrayOutputStream bos=new ByteArrayOutputStream();
      try {
      ObjectOutputStream oos=new ObjectOutputStream(bos);
      oos.writeObject(this);
      ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
      ObjectInputStream ois=new ObjectInputStream(bis);
      text=(Text)ois.readObject();
      } catch (IOException e) {
      e.printStackTrace();
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      }
      return text;
      }
     }
     ​
     class Name implements Serializable {
     ​
      private static final long serialVersionUID = 872390113109L;
     ​
      private String name;
     ​
      public String getName() {
      return name;
      }
     ​
      public void setName(String name) {
      this.name = name;
      }
     ​
      @Override
      public String toString() {
      return name;
      }
     }
    

    输出

     name1
     name1
    

    结果分析

    采用深克隆能有效隔离源对象与克隆对象的联系。

    从实现过程来说,递归克隆存在克隆过程多且复杂的缺点,所以建议采用序列化的方式进行

    深克隆。

    总结

    JAVA对象克隆共有两种形式,三种方法

    • 浅克隆

      • 调用clone方法
    • 深克隆

      • 递归调用clone方法

      • 序列化对象

    三种方法之间互有优缺点,具体采用要根据实际情况。

    展开全文
  • 如何实现对象克隆

    千次阅读 2018-06-03 18:46:40
    实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下:package com.javadu.cloneTest;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutp...

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

    package com.javadu.cloneTest;


    import java.io.ByteArrayInputStream;

    import java.io.ByteArrayOutputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;


    public class MyUtil {

        private MyUtil() {

            throw new AssertionError();

        }


        public static <T> 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方法没有任何意义

            // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放

        }

    }

    下面是测试代码:
    首先是Person类,

    
    

    package com.javadu.cloneTest;


    import java.io.Serializable;


    public class Person implements Serializable {

        private static final long serialVersionUID = -9102017020286042305L;

        private String name;    // 姓名

        private int age;        // 年龄

        private Car car;        // 座驾


        public Person(String name, int age, Car car) {

            this.name = name;

            this.age = age;

            this.car = car;

        }


        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 Car getCar() {

            return car;

        }


        public void setCar(Car car) {

            this.car = car;

        }


        @Override

        public String toString() {

            return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";

        }

    }

    然后是Car类:

    package com.javadu.cloneTest;


    import java.io.Serializable;


    public class Car implements Serializable {

        private static final long serialVersionUID = -5713945027627603702L;


        private String brand;       // 品牌

        private int maxSpeed;       // 最高时速


        public Car(String brand, int maxSpeed) {

            this.brand = brand;

            this.maxSpeed = maxSpeed;

        }


        public String getBrand() {

            return brand;

        }


        public void setBrand(String brand) {

            this.brand = brand;

        }


        public int getMaxSpeed() {

            return maxSpeed;

        }


        public void setMaxSpeed(int maxSpeed) {

            this.maxSpeed = maxSpeed;

        }


        @Override

        public String toString() {

            return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";

        }

    }

    然后是一个测试用例:

    
    

    package com.javadu.cloneTest;


    public class CloneTest {

        public static void main(String[] args) {

            try {

                Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300));

                Person p2 = MyUtil.clone(p1);   // 深度克隆

                p2.getCar().setBrand("BYD");


                // 修改克隆的Person对象p2关联的汽车对象的品牌属性

                // 原来的Person对象p1关联的汽车不会受到任何影响

                // 因为在克隆Person对象时其关联的汽车对象也被克隆了

                System.out.println(p1);

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

    注意: 基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。

    展开全文
  • 实现对象克隆的两种方式

    千次阅读 2019-03-07 14:55:36
    2、实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆实现代码如下: import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Objec....
  • java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)
  • Java - 如何实现对象克隆

    万次阅读 2019-03-12 11:51:23
    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的... 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。 package chimomo.le...
  • 文章目录如何实现对象克隆?1.答案:2.浅克隆和深克隆的区别3.实现Cloneable接口实现深克隆和浅克隆3.1 浅克隆实现3.2 深克隆实现4.实现Serializable接口,实现深克隆5.org.apache.commons中BeanUtils和...
  • Cloneable实现对象克隆

    2019-06-04 13:46:25
    本篇文章主要是对Cloneable接口如何实现对象克隆展开。 首先需要声明下,对象有分为浅克隆和深克隆。 浅克隆 浅克隆是对要克隆的对象,其中的基本类型复制一份新的产生给对象。但是对于非基本类型的数据类型,...
  • java实现对象拷贝的两种方法

    千次阅读 2020-06-06 20:25:01
    拷贝分为浅拷贝和深度拷贝,浅拷贝是实现对象引用的传递,拷贝之后的两个对象指向同一引用,这样的缺点就是修改一个对象的值之后,另一个对象的值也随之改变,但节省内存。深度拷贝是重新开辟空间存放对象的内容,...
  • 实现对象克隆

    2015-07-25 16:09:15
    有两种方式:   1). 实现Cloneable接口并重写Object类中的clone()方法;   2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
  • jq的extend()方法能很方便的实现扩展对象方法,这里要实现的是:原生js实现复制对象,扩展对象,类似jq中的extend()方法,需要的朋友可以参考下
  • 浅拷贝:创建了一个对象,但是这个对象的某些内容(比如A)依然是被拷贝对象的,即通过这两个对象中任意一个修改A,两个对象的A都会受到影响 深拷贝:相当于创建了一个新的对象,只是这个对象的所有内容,都和被拷贝的...
  • Cloneable可以实现对象克隆复制,Serializable主要是对象序列化的接口定义。很多时候我们涉及到对象的复制,我们不可能都去使用setter去实现,这样编写代码的效率太低。JDK提供的Cloneable接口正是为了解决对象...
  • 对一个对象进行深层次的复制,得到一个与原来一模一样的新的对象,主要使用对象流ObjectOutputStream()和objectInputStream()来实现
  • 1、为什么要使用克隆 对象的拷贝需要使用克隆,如果想对一...(2)实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。 代码举例 public class MyUtil { private MyUtil() { throw
  • 一、什么是对象克隆? 首先我们需要知道,什么是对象的克隆,或者说复制。一个业务逻辑,需要一个新的对象,但是类型和值都是之前的,也就是说,新状态和之前完全一样。使用new和赋值语句或者set注入都是可以的,...
  • 假如说你想复制一个简单变量。很简单: int apples = 5; int pears = apples;...但是如果你复制的是一个对象,情况就有些复杂了。 假设说我是一个beginner,我会这样写: class Student { private ...
  • 主要介绍了JS对象的深度克隆方法,结合实例形式分析了JavaScript深度克隆实现技巧,需要的朋友可以参考下
  • js对象克隆的几种方法

    千次阅读 2020-06-26 00:55:42
    在js中对象克隆就是把对象值重新赋给一个新对象。克隆也存在深克隆于浅克隆的区别。引用类型的值都会被保存在堆内存中,在栈内存中会存在一个指针指向堆内存中的值。这时,如果只复制了指针,则可以说这个克隆为浅...
  • 今天整理了下资料,分析下为什么一句话可以实现纯数据json对象的深度克隆,感兴趣的朋友可以了解下哦
  • 对象克隆复制工具

    2018-07-31 16:25:37
    对象复制工具,基于cglib BeanCopier 实现对实体对象、持久化对象、代理对象克隆复制, 避免重复克隆复制,避免无限循环引用,(校验hashCode) 可指定实体对象和集合属性的克隆深度
  • 题目需求:实现对象的深度克隆,对象中还有对象或者数组 举个栗子: let obj = { a: 0, b: { b1: 0, b2: 3 }, c:[1,2,3] } 对上面的对象进行深度克隆...
  • js/ts 实现对象深度克隆

    千次阅读 2019-11-23 13:20:57
    自己实现了一个对象深度克隆: 主要缺陷只有一个: 对键值为循环调用的对象无能为力,会堆栈溢出。 作用: 适合常规的纯数据对象深度克隆 function clone(o: any, record = [o]) { switch (Object.type(o)) {...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 761,238
精华内容 304,495
关键字:

如何实现对象克隆