精华内容
下载资源
问答
  • 我对于这两种方式实现深拷贝做了性能基准测试。 下面是对比反射(github.com/mohae/deepcopy)与序列化(gob)所用的基准测试脚本 deepcopy_test.go package deepcopy import ( bytes encoding/gob testing ...
  • C#基于表达式(Expression)实现对象深拷贝,包含了核心类及示例数据。这是一个比较简单的帮助类,可作学习参考
  • javascript中数组深拷贝途径及对象数组深拷贝 什么是浅拷贝 在js当中,我们常常遇到数组复制的的情况,许多人一般都会使用“=”来直接把一个数组赋值给一个变量,如: var a=[1,2,3]; var b=a; console.log(b); ...
  • 对象深拷贝与浅拷贝的区别如下: 浅拷贝:仅仅复制对象的引用,而不是对象本身; 深拷贝:把复制的对象所引用的全部对象都复制一遍。 一. 浅拷贝的实现 浅拷贝的实现方法比较简单,只要使用是简单的复制语句即可。...
  • 主要介绍了JS 数组和对象深拷贝操作,结合实例形式分析了JS 数组和对象深拷贝基本原理与操作技巧,需要的朋友可以参考下
  • 写前端的时候经常会遇到对象的拷贝,一般我们...总结一下常用的对象深拷贝以及数组对象的深拷贝。1. 序列化转成json字符串深拷贝,以及存在的问题; 2. Object.assign()深拷贝,以及存在的问题; 3. 循环递归深拷贝。

    写前端的时候经常会遇到对象的拷贝,一般我们会用到深拷贝,深拷贝就是完完整整的将一个对象从内存中拷贝一份出来,放到另一块新开辟的内存中去。向下面这种赋值是浅拷贝,a、b都是对同一块内存进行引用,a、b哪一个变量修改对象的属性值都会相互影响。总结一下常用的对象深拷贝以及数组对象的深拷贝。

    var a = {id:"",name:""}
    var b = a;
    
    1. 序列化转成json字符串深拷贝,以及存在的问题
    2. Object.assign()深拷贝,以及存在的问题
    3. 循环递归深拷贝

    一、序列化转成json字符串深拷贝

    例:

    let source = {"id":1};
    //序列化转成json字符串
    let jsonStr = JSON.stringify(source)
    //反序列化为对象
    let target = JSON.parse(jsonStr);
    

    存在的问题:
    此方法仅在原对象包含可序列化值类型且没有任何循环引用时才有效。不可序列化值类型的一个例子是 Date 对象 - JSON.parse 只能将其解析为字符串而无法解析回其原始的 Date 对象

    注:
    同时总结java的序列化
    序列化:就是把一个java对象转成字节流
    反序列化:就是把字节流转成java对象
    当然序列化不仅仅可以是转成字节流或者json字符串,还有很多种方式
    为什么在java对象要序列化,什么场景要序列化?
    如果没有序列化,怎么把一个在内存里面的对象保存到文件里面去,怎么把内存的对象通过网络传输到另一台计算机的内存去呢?序列化就是把内存的对象转成字节流或者json字符串等方式进行传输用的,用在一些保存对象到文件、网络传输对象等io流传输对象的场景。


    二、Object.assign()深拷贝

    Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
    基本语法:Object.assign(target, …sources)
    例:

    var source = {"id":1,name:"lin"};
    var target = Object.assign({},source);
    

    这样就可以把source对象里面的相同属性值拷贝到target对象

    存在的问题:
    如果要拷贝的对象source里面的属性不是基础类型也是对象,或者属性含有对象数组,这种方式的拷贝就不会把source对象里面的对象或者数组对象进行深拷贝
    例:

    var source = {"id":1,list:[{"name":"小明"},{"name":"小花"}]};
    var target = Object.assign({},source);
    

    这时target里面的属性list数组对象只是浅拷贝source里面的list,还是对同一块内存的引用
    也可以向下面这样优化,循环list数组里面的对象进行Object.assign拷贝,添加到一个新的数组去,然后再赋值给target.list
    例:

    let source = {"id":1,list:[{"name":"小明"},{"name":"小花"}]};
    let target = Object.assign({},source);
    //对象数组的深拷贝
    let newlist = [];
    for(let i=0;i<target.list.length;i++){
          let obj = Object.assign({}, target.list[i]);
          newlist.push(obj);
    }
    target.list = newlist;
    

    注:如果对象里面还含有对象属性,而里面的对象属性又含有对象属性,则这种方式很麻烦不合适。

    三、循环递归深拷贝

    function deepClone(obj, newObj) {
        var newObj = newObj || {};
        for (let key in obj) {
            if (typeof obj[key] == 'object') {
                let isArray = Array.isArray(obj[key]);//判断是否数组
                newObj[key] = (isArray == true ? [] : {})
                deepClone(obj[key], newObj[key]);
            } else {
                newObj[key] = obj[key]
            }
        }
        return newObj;
    }
    
    

    参考:
    网友haogemr的js 深度拷贝的几种方法

    展开全文
  • JAVA对象拷贝分为两种方式,一种是引用拷贝,一种是对象拷贝 引用拷贝:和对象拷贝的不同之处在于,引用拷贝只会生成一个新的对象引用地址,但两个地址其最终指向的还是同一个对象对象拷贝:这种方式会重新生成...

    JAVA对象拷贝分为两种方式,一种是引用拷贝,一种是对象拷贝

    引用拷贝:和对象拷贝的不同之处在于,引用拷贝只会生成一个新的对象引用地址,但两个地址其最终指向的还是同一个对象;

    对象拷贝:这种方式会重新生成一个新的对象,生成的新对象与原来的对象没有任何关联。

    1、引用拷贝

    引用拷贝也就是我们常用的对象赋值,这种方式不会生成新的对象,只会在原对象上增加了一个新的对象引用,两个引用指向的对象还是是同一个;

    java 对象默认的赋值方式都是引用拷贝,比如说下面代码对象赋值的过程就是引用拷贝:

    User user1 = new User();


    User user2 = user1;

    引用拷贝需要注意的地方

    下面我们来看一下我们程序里面常见的例子:

    (1)首先定义一个User类


    public class User {


    private int age;//年龄
    private String name;//姓名
    }

    (2)测试代码:

    public static void main(String[] args) {
    //1、实例化一个user1对象,并对属性赋值
    User user1=new User();
    user1.setName("我是user1");
    user1.setAge(18);

    //2、把user1对象放到一个List里面
    List<User> userList=new ArrayList<User>();
    userList.add(user1);

    //3、然后创建user2 对象并从List里面拿出user1对象赋值给user2
    User user2= userList.get(0);

    //4、给user2的属性值
    user2.setAge(1);
    user2.setName("我是user2");

    //5、这个的时候我们再输出user1的对应属性值
    System.out.println(user1);

    System.out.println(user2);
    }

    最后我们看看打印结果:

    举了一个比较绕的例子是想更好的提现出对象赋值的方式可能会给我们带来的问题;

    结合引用拷贝的图解我想我们不难理解这个结果是怎么出现的,因为user1和user2其实指向的是同一个对象,所以当我们修改user2的属性时其实修改的也是user1这个对象。

    程序中如果像这种在一个对象上多次赋值再并使用其实是很危险的,有时候调用的层次多了被传递的使用者修改了对象属性会造成业务逻辑上的错误(想想上面的例子,如果在user2修改属性值之后,还有业务代码要拿user1来进行业务操作的话,那么此时的user1属性值都已经被修改了,这样势必会产生业务上的错误),而这样的问题又比较难发现,并且这样也会造成代码的理解成本变高,可读性也会变差,所以开发中我们尽量避免对象多层传递赋值。

    2、对象浅拷贝

    浅拷贝与引用拷贝不同,被浅拷贝的对象是会重新生成一个新的对象,新的对象和原来的对象是没有任何关系的,但是如果对象中的某个属性是引用类型的话,那么该属性对应的对象是不会重新生成的,浅拷贝只会重新当前拷贝的对象,并不会重新生成其属性引用的对象。

    实现浅拷贝

    需要拷贝的对象实现Cloneable 接口,再调用对象的clone方法可以实现对象的浅拷贝。

    (1)实现 Cloneable 接口 并重写clone 方法

    Teacher 类

    public class Teacher

    {
    //老师姓名
    private String teacherName;
    }

    User类

    public class User implements Cloneable{
    //名字
    private String name;
    //老师
    private Teacher teacher;
    }

    (2)测试

    public static void main(String args[]) throws Exception {
    //user1有一个teacher对象的属性
    Teacher teacher=new Teacher();
    teacher.setTeacherName("我是teacher一号");
    User user1 = new User();
    user1.setName("我是user一号");
    user1.setTeacher(teacher);

    //对user1进行浅拷贝,再重新赋值其属性
    User user2 = (User)user1.clone();
    user2.setName("我是user二号");
    user2.getTeacher().setTeacherName("我是teacher二号");

    //最后我们再打印user1的对象属性
    System.out.println("user1 的name"+user1.getName());
    System.out.println("user1 的techerName"+user1.getTeacher().getTeacherName());
    }

    (3)打印结果

    从打印结果我们可以看出:

    (1)user2修改了name之后并没有影响user1的name,这说明user2和user1对象是独立的。

    (2)user2修改了teacher 对象属性之后user1的teacher对象属性也同时改变了,这说明对象的clone方法并不会把其对象中引用的其他对象进行拷贝,这也是我们俗称的浅拷贝。

    为什么浅拷贝不会拷贝其引用的对象?

    也许你也有个疑问,为什么clone的方式不能把其引用的对象也重新生成一份,那多省事情,我想应该有以下几个原因;

    1、不给其他类强加意义

    这个就好比,User类为了能进行浅拷贝就实现了Cloneable 接口,但是其引用对象Teacher没有实现Cloneable 也许说明他本身就不想被拷贝,如果在拷贝User的情况下,同时也把Teacher拷贝了,这不就等于干了一件没有遵循他人同意的事,干了之后人家还不知道,傻傻的以为没人可以通过clone来拷贝出另外一个Teacher。

    2、不破坏其原来对象的代码逻辑

    如果User引用的Teacher 是个单例模式的对象,那如果在User拷贝的时候同时也拷贝出了一个Teacher 那是不是就会破坏Teacher这个单例模式对象的逻辑初衷。

    3、对象深拷贝

    深拷贝相比浅拷贝的不同就是,深拷贝会把拷贝的对象和其属性引用的对象都重新生成新的对象。

    如何实现深拷贝

    (1)对象实现序列化接口

    User类
    public class User implements Serializable {
    //名字
    private String name;
    //老师
    private Teacher teacher;
    }

    Teacher 类

    public class Teacher implements Serializable {
    //老师姓名
    private String teacherName;

    }

    (2)把对象进行序列化后再反序列化


    public static void main(String args[]) throws Exception {

    //user1有一个teacher对象的属性
    Teacher teacher=new Teacher();
    teacher.setTeacherName("我是teacher一号");
    User user1 = new User();
    user1.setName("我是user一号");
    user1.setTeacher(teacher);

    //序列化写入到流里
    ByteOutputStream bots=new ByteOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bots);
    oos.writeObject(user1);


    //反序列化成user2对象
    ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bots.toByteArray()));
    User user2 = (User) ois.readObject();
    user2.setName("我是user二号");
    user2.getTeacher().setTeacherName("我是teacher二号");

    //最后我们再打印user1的对象属性
    System.out.println("user1 的name"+user1.getName());
    System.out.println("user1 的techerName"+user1.getTeacher().getTeacherName());
    }

    (3)最后看结果,进行深拷贝后,改变User2对象中的属性不会对原来User1对象中的属性有任何影响,这说明,User1和User2 不管是属性还是其引用对象都是重新生成互不关联的两个对象:

    (4)最后找了一个深度拷贝工具类供大家使用


    public abstract class BeanUtil {

    public static <T> T cloneTo(T src) throws RuntimeException {
    ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
    ObjectOutputStream out = null;
    ObjectInputStream in = null;
    T dist = null;
    try {
    out = new ObjectOutputStream(memoryBuffer);
    out.writeObject(src);
    out.flush();
    in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
    dist = (T) in.readObject();
    catch (Exception e) {
    throw new RuntimeException(e);
    finally {
    if (out != null) {
    try {
    out.close();
    out = null;
    catch (IOException e) {
    throw new RuntimeException(e);
    }
    }
    if (in != null) {
    try {
    in.close();
    in = null;
    catch (IOException e) {
    throw new RuntimeException(e);
    }
    }
    }
    return dist;
    }
    }

    展开全文
  • 主要介绍了vue 使用lodash实现对象数组深拷贝操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 主要介绍了JavaScript基于遍历操作实现对象深拷贝功能,涉及javascript元素遍历与属性操作相关实现技巧,需要的朋友可以参考下
  • Android 中对Java对象深拷贝的方法

    千次阅读 2020-08-18 18:16:21
    前言 在项目中偶尔会遇到关于深拷贝的问题,比如点餐列表中的点一个饮料,它有多种规格(常温、冰),这样放到购物车列表中就可能出现2个... 深拷贝:只是拷贝了源对象的值,所以即使源对象的值发生变化时,拷贝对象.

    前言

    在项目中偶尔会遇到关于深拷贝的问题,比如点餐列表中的点一个饮料,它有多种规格(常温、冰),这样放到购物车列表中就可能出现2个相同id的饮料。

    如下图所示,其中我要对百事可乐进行拷贝一份,然后各修改它的属性值为常温/加冰。


     

    一、浅拷贝与深拷贝的区别

    在Java语言中需要拷贝一个对象时,有两种类型:浅拷贝与深拷贝。

    • 浅拷贝:只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。

    • 深拷贝:只是拷贝了源对象的值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。

    浅拷贝示例: 

    public class Food {
        String name;
        String type;
    
        public Food(String name,String type){
            this.name = name;
            this.type = type;
        }
      
    }
    
    public void main(){
        Food food1 =new Food();
        food.name ="百事可乐";
        food.type = "冰";
        //拷贝
        Food food2 =food;
        food.type= "常温";
    }

    结果:food1和food2的 type都为“常温”。

     

    接下来,我们来看看深拷贝的方法。


    二、深拷贝的方法


    (1)构造函数

    通过在调用构造函数进行深拷贝,形参如果是基本类型和字符串则直接赋值,如果是对象则重新new一个。

    public void main(){
        Food food1 =new Food("百事可乐","冰");
        //拷贝
        Food food2 =new Food(food1.name,"常温");
    
    }

    (2)重写clone()

    public class Food implements Cloneable {
        private String name;
        private String type;
     
        // constructors,get,set
     
        @Override
        public User clone() throws CloneNotSupportedException {
            Food food = (Food) super.clone();
            user.setType(this.type.clone());
            return food;
        }
    }
    
    public void main(){
    
        Food food1 = new Food("百事可乐", "冰");
     
        // 调用clone()方法进行深拷贝
        Food food2 = food1.clone();
    
    }

    (3)Apache Commons Lang序列化

    Java提供了序列化的能力,可以先将源对象进行序列化,再反序列化生成拷贝对象。但是,使用序列化的前提是拷贝的类需要实现Serializable接口。Apache Commons Lang包对Java序列化进行了封装,我们可以直接使用它。

    public class Food implement Serializable{
        String name;
        String type;
        //..
    }
    
    public void mian(){
        // 使用Apache Commons Lang序列化进行深拷贝
        Food food2 = (Food) SerializationUtils.clone(food1);
        // 修改源对象的值
    }

    (4)Gson序列化

    Gson可以将对象序列化成JSON,也可以将JSON反序列化成对象,所以我们可以用它进行深拷贝。

    public void main(){
        Food food1 =new Food("百事可乐","冰");
    
        //拷贝
        Gson gson = new Gson();
    
        Food food2 =gson.fromJson(gson.toJson(food1), Food.class);
    
        food2.setType("常温");
    
    }

    (5)Jackson序列化

    Jackson与Gson相似,可以将对象序列化成JSON。不过拷贝的类需要有默认的无参构造函数。

    public void main(){
        Food food1 =new Food("百事可乐","冰");
    
        //拷贝
        ObjectMapper objectMapper = new ObjectMapper();
    
        Food food2 =objectMapper.readValue(objectMapper.writeValueAsString(food1), Food.class));
    
        food2.setType("常温");
    
    }

    小结:

    个人项目中使用的是Gson实现的对象序列化深拷贝方法。

    原因是集成Gson已然是项目中标配,而且使用起来简洁,代码熟悉感很强。


    参考链接:https://www.cnblogs.com/xinruyi/p/11537963.html

     

    展开全文
  • ts 简单的对象深拷贝

    千次阅读 2019-12-10 15:55:17
    简单的通过循环对象的 key , 如果 key 还是一个对象 通过递归来不断的进行对象拷贝。 export function deepMerge(...objs: any[]): any { const result = Object.create(null) objs.forEach(obj => { if ...

     简单的通过循环对象的 key , 如果 key 还是一个对象 通过递归来不断的进行对象的拷贝。

    export function deepMerge(...objs: any[]): any {
      const result = Object.create(null)
      objs.forEach(obj => {
        if (obj) {
          Object.keys(obj).forEach(key => {
            const val = obj[key]
            if (isPlainObject(val)) {
              // 递归
              if (isPlainObject(result[key])) {
                result[key] = deepMerge(result[key], val)
              } else {
                result[key] = deepMerge(val)
              }
            } else {
              result[key] = val
            }
          })
        }
      })
      return result
    }
    
    export function isPlainObject(val: any): val is Object {
      return toString.call(val) === '[object Object]'
    }

     

    展开全文
  • = val } } }) } }) console.log(result) return result } isPlainObject(val) { const toString = Object.prototype.toString return toString.call(val) === '[object Object]' } deepMerge 参数,后面对象会覆盖...
  • 简单好用的java bean对象拷贝工具。 支持字段注解,注解错误抛出异常。 github仓库 简单的拷贝class A copy to new class A 你只需要简单的这样的代码: A a = new A(); A a2 = Copier.copy(a); // clone new ...
  • Java 类对象深拷贝方法

    千次阅读 2019-09-03 22:30:13
    Java中实现深拷贝的两种方式–——clone() & Serialized 通过反射机制 通过工具类 cglib: beancopier apache: beanutils PropertyUtils 通过FastJson public static<T> T convert(Object src, Cla...
  • C#对象深拷贝

    2019-09-28 14:30:32
    C#对象深拷贝 众所周知,c#中的对象存在值类型和引用类型之分,故而对象之间的赋值就存在浅拷贝和深拷贝的概念 网上的深拷贝方法也很多,但是要么写的无比复杂,要么有诸多限制 最终还是选择了反射的方法...
  • 实现深拷贝对象的方法。分享给大家供大家参考,具体如下: 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 深浅拷贝对应的参数就是[deep],是可选的,为true或false。默认情况是false(浅拷贝),...
  • js代码-JS练习 for...in 与 对象深拷贝
  • 深拷贝:比如Object.assign()、JSON对象的parse和stringify、JQ的extend,但是它们有一个共同的问题就是对简单对象可以实现深拷贝,但是对复杂对象就不行了,比如这样一个对象(属性值有函数、数组、复杂对象等) ...
  • 关于iOS的深拷贝,浅拷贝已经有很多文章,不必在过多赘述。有关系统常见可变对象和不可变对象的copy 和 mutableCopy网上有很多文章,一张图基本上可以说明那么本文着重要研究的是自定义对象的拷贝问题,特别比如说...
  • package ioc; /** * @Author:zhuo * @Date:2018/4/30 15:46 * */ ...public class VarCopyDemo { public static void main(String[] args) { ...\n********下面是浅拷贝内容********\n");...
  • 对多维数组,对象,进行去重,相同的值只保留一个,常见的new Set()和filter,只能去重一维数组,并不能进行深层的去重,逻辑:判断是否为对象,为对象判断是否为数组或是真的对象,递归一直筛选为值,判断首次...
  • 实现一个对象深拷贝函数cloneDeep()

    千次阅读 2020-09-03 19:04:40
    (2)不需要拷贝原型链上的属性和方法; 直接上代码 //创建测试对象 let obj = { a: [1, { ss: "ss" }, [3], 4, 5, ["sad", "123", true]], age: 10, name: "老八", eat: "秘制小汉堡", show: { skill: "鸡...
  • js 日期对象深拷贝

    千次阅读 2019-04-25 22:08:16
    更详细的对象深拷贝方法请参考:https://blog.csdn.net/liwusen/article/details/78759373写的很详细 因为valueOf方法,日期类定义的valueOf()方法会返回它的一个内部表示:1970年1月1日以来的毫秒数.因此我们可以...
  • Java中分为深拷贝和浅拷贝; BeanA 对象如下: public class BeanA { private String str1, str2; private List<BeanB> beanBList; } 如需浅拷贝,则需实现Serializable 接口,并重写 clone 方法,...
  • js考虑最完善的深拷贝函数,可以深拷贝引用对象和基本对象
  • js对象深拷贝

    千次阅读 2017-10-11 19:00:49
    前置知识基本类型和引用类型 基本类型:存放在栈... 引用类型:存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。 当我们需要访问引用类
  • function checktype(obj){ //检查对象类型 return Object.prototype....function depCopy(target,hash=new WeakMap()){ //hash 作为一个检查器,避免对象深拷贝中出现环引用,导致爆栈。 let type = checktype(...
  • js代码-对象深拷贝

    2021-07-16 16:09:30
    js代码-对象深拷贝
  • JS对象深拷贝的几种方法总结

    千次阅读 2020-05-16 14:46:10
    例: var obj = { name: "韩信", age: 18, skin: [ { id: 0, name: '街头霸王', color: 'yellow'...1. for…in遍历拷贝对象 function copy(obj) { var obj2 = {} for (var key in obj) { obj2[key] = typeof ob

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 140,631
精华内容 56,252
关键字:

对象深拷贝