精华内容
下载资源
问答
  • 主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下
  • Java克隆(Clone)是Java语言的特性之一,本篇文章主要介绍了Java中的Clone机制是如何工作的,需要的朋友可以参考下
  • js代码-手动实现浅克隆
  • 浅克隆

    2021-03-05 16:48:28
    浅克隆只是克隆s1对象,但是针对s1中的引用类型属性只是克隆地址 import java.util.Date; //只是克隆s1对象,但是针对s1中的引用类型属性只是克隆地址 public class 浅克隆 { public static void main(String[] ...

    浅克隆只是克隆s1对象,但是针对s1中的引用类型属性只是克隆地址

    
    import java.util.Date;
    //只是克隆s1对象,但是针对s1中的引用类型属性只是克隆地址
    public class 浅克隆 {
    	public static void main(String[] args) throws Exception {
    		Stu s1=new Stu();
    		s1.setId(200L);
    		s1.setBirth(new Date());
    		Stu s2=(Stu)s1.clone();
    		s2.getBirth().setYear(9000);
    		System.out.println("s1..."+s1);
    		System.out.println("s2..."+s2);
    	}
    
    }
     class Stu implements Cloneable{
    	 private Long id;
    	 private Date birth;
    	 
    	 public Object clone() throws CloneNotSupportedException {
    		return super.clone();
    		 
    	 }
    	public Long getId() {
    		return id;
    	}
    	public void setId(Long id) {
    		this.id = id;
    	}
    	public Date getBirth() {
    		return birth;
    	}
    	public void setBirth(Date birth) {
    		this.birth = birth;
    	}
    	@Override
    	public String toString() {
    		return "stu [id=" + id + ", birth=" + birth + "]";
    	}
    	 
     }
    
    
    展开全文
  • 浅克隆 浅克隆是指:只克隆数组/对象的第一层级内容(开辟新的堆内存),而第二层级及以上层级的内容则直接引用(使用原来第二层级及以上层级的堆内存)。如果对克隆后对象的二级或以上层级进行修改,那么克隆前...

    浅克隆

    浅克隆是指:只克隆数组/对象的第一层级内容(开辟新的堆内存),而第二层级及以上层级的内容则直接引用(使用原来第二层级及以上层级的堆内存)。如果对克隆后对象的二级或以上层级进行修改,那么克隆前对象的二级或以上层级也会跟着被修改。
    例如:现有一个对象obj1对应堆内存地址0x000,obj1对象中还有个子对象obj1_1对应堆内存0x001,现在想对obj1对象进行浅克隆,则会创建一个新的对象obj2对应新的堆内存地址0x002,对于对象obj1中的基本类型数据则会直接拷贝到obj2中,而obj1中的引用类型也就是子对象obj1_1则会直接被新对象obj2引用,而不是创建新的堆内存。后面如果通过操作obj2对obj2中的子对象obj1_1进行更改,那么obj1中的obj1_1也会随着变化,因为它们用的是同一个堆内存。来看下面的图会更直观一些
    在这里插入图片描述

    实现浅克隆的几种方案

    • 对象的浅克隆方案一:基于循环实现
    let obj1 = {
    	python: "python",
    	java: "java"
    	fontend: {
    		javascript: "javascript",
    		html: "html"
    	}
    }
    let obj2 = {};//创建一个新对象(开辟新的堆内存)
    //把obj1中私有的key和Symbol类型的key存在数组中
    let keys = [
    	...Object.keys(obj1),//展开运算符
    	...Object.getOwnPropertySymbols(obj1)
    ]
    keys.forEach(key => {
    	obj2[key] = obj1[key];
    });
    console.log(obj1 === obj2); //false
    console.log(obj1.fontend === obj2.fontend);// true
    
    • 对象的浅克隆方案二: 展开运算符
    let obj1 = {
    	python: "python",
    	java: "java"
    	fontend: {
    		javascript: "javascript",
    		html: "html"
    	}
    }
    let obj2 = {
    	...obj1
    };
    console.log(obj1 === obj2); //false
    console.log(obj1.fontend === obj2.fontend);// true
    
    • 对象的浅克隆方案三:基于Object.assign()函数

    Object.assign([obj1], …[obj2]):该方法接收多个参数,执行后会将obj2中的键值对合并到obj1中,并将obj1的堆内存地址返回。注意:这里返回的不是新的对象,而是把第一个参数作为返回值返回。
    所以我们可以利用这个特点进行对象的浅克隆

    let obj1 = {
    	python: "python",
    	java: "java"
    	fontend: {
    		javascript: "javascript",
    		html: "html"
    	}
    }
    //因为assign方法默认会把第一个参数返回,所以这里传一个空对象进去,执行asign方法将obj1合并后,再将合并后的对象返回,就达到了克隆目的
    let obj2 = Object.assign({}, obj1);
    
    console.log(obj1 === obj2); //false
    console.log(obj1.fontend === obj2.fontend);// true
    
    • 数组浅克隆方案一:基于forEach或map
    let arr = [12,3,[4,50]];
    let arr2 = [];
    arr.forEach((item, index) => {
    	arr2[index] = item;
    });
    
    arr2 = arr.map(item => item);
    

    数组浅克隆方案二:基于展开运算符或Object.asing(),与对象相同

    let arr = [12,3,[4,50]];
    let arr2 = [
    	...arr
    ];
    
    arr2 = Object.assign([], arr);
    

    数据浅克隆方案三:基于数组的slice方法,不传参数默认从数组第一项开始截取到数组的最后一项

    let arr = [12,3,[4,50]];
    let arr2 = arr.slice();
    
    • 数组和对象的浅克隆 - 通用方案:自己撸代码
    //定义一个用于检测数据类型的通用方法
    function toType(value){
    let obj = {};
    ['Number','String','Boolean','Null','Undefined','Symbol','BigInt','Function','GeneratorFunction','Date','RegExp','Object','Error'].forEach(item => {
    	obj["[object "+item+"]"] = item.toLowerCase()
    });
     return obj[Object.prototype.toString.call(value)];
    }
    //定义一个获取对象/数组所有私有属性(包括Symbol类型)的方法
    function getOwnProperties(obj){
    //数据类型检测
    if(obj == null) return [];
    //获取所有私有属性包括Symbol类型
    let keys = [
    	...Object.keys(obj),
    	...Object.getOwnPropertySymbols(obj)
    ]
    return keys;
    }
    
    function shallowClone(obj){
    	//如果是基本数据类型值,则传啥就返回啥
    	let type = toType(obj);
    	if(/^(number|string|boolean|null|undefined|symbol|bigint)$/.test(type)) return obj;
    	if(type === 'function') {
    		//返回一个不同函数,但最后执行效果跟原始函数一致
    		return function proxy(){
    			obj();
    		}
    	}
    	//if(type === 'regexp') return new RegExp(obj);
    	//if(type === 'date') return new Date(obj);
    	if(/^(regexp|date)$/.test(type)) return new obj.constructor(obj);
    	if(type === 'error') return new Error(obj.message);
    	
    	let keys = getOwnProperties(obj);
    	let clone = {};
    	Array.isArray(obj) ? clone = [] : null;
    	keys.forEach(item => {
    		clone[item] = obj[item];
    	});
    	return clone;
    }
    

    数组和对象的深克隆

    相信经过前面对数组和对象的浅克隆的了解,深克隆也就不难理解了;
    前面说浅克隆是只克隆数组或对象的第一层级,二级及以上层级是直接引用;那么深克隆则是克隆数组或对象的每个层级,不管一个对象或数组有多少层级,那么当我们进行深克隆时每一个层级都会开辟一块新的堆内存地址。对于克隆后对象/数组的任何层级做任何修改都不会影响到克隆前的对象/数组,因为它们都是独立的不同的堆内存。如下图所示
    在这里插入图片描述

    • 数组和对象的深克隆方案一:基于JSON.stringfiy、JSON.parse实现深克隆

    原理:先将数组或对象基于JSON.stringify转换为字符串,然后再基于JSON.parse把字符串转换为对象,此时对象中对应每个层级都会开辟一块全新的堆内存来存储
    缺点:因为JSON.stringify变为字符串,很多类型是不支持的

    • 正则/Math数学函数会被处理为空对象
    • 具备函数/Symbol/undefined属性值的属性会被直接删除掉
    • BigInt无法处理,会报错
    • 日期对象转换后变为字符串
    let obj1 = {
    	python: "python",
    	java: "java"
    	fontend: {
    		javascript: "javascript",
    		html: "html"
    	}
    }
    let obj2 = JSON.parse(JSON.stringify(obj1));
    

    数组/对象深克隆方案二:自己撸代码

    function toType(value){
    let obj = {};
    ['Number','String','Boolean','Null','Undefined','Symbol','BigInt','Function','GeneratorFunction','Date','RegExp','Object',"Error"].forEach(item => {
    	obj["[object "+item+"]"] = item.toLowerCase()
    });
     return obj[Object.prototype.toString.call(value)];
    }
    //定义一个获取对象/数组所有私有属性(包括Symbol类型)的方法
    function getOwnProperties(obj){
    //数据类型检测
    if(obj == null) return [];
    //获取所有私有属性包括Symbol类型
    let keys = [
    	...Object.keys(obj),
    	...Object.getOwnPropertySymbols(obj)
    ]
    return keys;
    }
    
    function deepClone(obj, cache = new Set()){	
    	/*
    	if(/^(number|string|boolean|null|undefined|symbol|bigint)$/.test(type)) return obj;
    	if(type === 'function') {
    		//返回一个不同函数,但最后执行效果跟原始函数一致
    		return function proxy(){
    			obj();
    		}
    	}
    	//if(type === 'regexp') return new RegExp(obj);
    	//if(type === 'date') return new Date(obj);
    	if(/^(regexp|date)$/.test(type)) return new obj.constructor(obj);
    	if(type === 'error') return new Error(obj.message);
    	*/
    	//如果是基本数据类型值,则传啥就返回啥
    	let type = toType(obj);
    	//如果不是数组或对象则直接按浅克隆处理
    	if(!/^(array|object)$/.test(type)) return shallowClone(obj);
    	
    	let keys = getOwnProperties(obj);
    	let clone = {};
    	Array.isArray(obj) ? clone = [] : null;
    	if(cache.has(obj)) return obj;
    	cache.add(obj);
    	keys.forEach(item => {
    		//if(/^(array|object)$/.test(toType(obj[item]))){
    		//	clone[item] = deepClone(obj[item]);
    		//}
    		clone[item] = deepClone(obj[item], cache);
    	});
    	return clone;
    }
    
    展开全文
  • 深浅克隆

    2020-06-22 18:05:09
    浅克隆就是将栈内存中的引用复制一份,赋给一个新的变量,本质上两个指向堆内存中的同一地址,内容也相同,其中一个变化另一个内容也会变化(根本上改变的是同一个对象)。 深拷贝: 深克隆就是创建一个新的空对象...

    浅拷贝:

    浅克隆就是将栈内存中的引用复制一份,赋给一个新的变量,本质上两个指向堆内存中的同一地址,内容也相同,其中一个变化另一个内容也会变化(根本上改变的是同一个对象)。

    深拷贝:

    深克隆就是创建一个新的空对象,开辟一块内存,然后将原对象中的数据全部复制过去,完全切断两个对象间的联系。

    // 浅克隆
    
    var a = new Array();
    a[0] = "小明";
    a[1] = "小红";
    a[2] = "小光";
    b = a;
    alert(b);
    b[1] = "小美";
    alert(a);
    
    // 递归实现深克隆
    
    function deepClone (obj) {
        if (typeof obj != 'object') {
            return obj
        }
        // 定义一个空对象
        var result = {}
        for (var i in obj) {
            if(obj[i])
            result[i] = deepClone(obj[i]) // 递归遍历
        }
        
        return result
    }
    
    var obj = {
        name: "xiaoming",
        age: 20
    }
    // 测试代码
    var obj1 = obj;
    var obj2 = deepClone(obj);
    console.log(obj1);       // name: "xiaoming", age: 20
    obj2.name = "小明";
    console.log(obj2);       // name: "小明", age: 20
    
    // 姓名和年龄顺序不一样是因为元素的属性内部是一个map,本身就是无序的

    Object.assign: 第一级属性深拷贝,第一级以下的级别属性浅拷贝 。

    例1
     
    let man = { key: { age: '123' } }
    let women = Object.assign({}, man)
    man.key.age = 10
    console.log(man , women)
     
    运行结果:
    { key: { age: 10 } }
    { key: { age: 10 } }
     
    例2
    let man = { key: { age: '123' } }
    let women = Object.assign({}, man)
    man.key = 123
    console.log(man, women)
     
    运行结果:
    { key: 123 }
    { key: { age: '123' } }

    json 深克隆

    var obj1 = {a:'abc', b:'hello'}
    var obj2 = JSON.parse(JSON.stringify(obj1))

     

    展开全文
  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址; 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址; ...

    1 概述

    1.1 浅克隆

    创建一个新对象,新对象的属性值和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象。

    1.2 深克隆

    创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象。

    1.3 异同点

    1. 深浅克隆都会在堆中新创建一个对象;
    2. 区别在于对象属性引用的对象是否也进行了克隆(递归性的,深的克隆,浅的不克隆);

    示例

    1. pos:当前对象的地址;

    2. son:son属性所指向的地址;

    3. name:对象的name属性。

    在这里插入图片描述

    2 案例

    2.1 浅克隆实现步骤

    1. 实现Cloneable接口(标识接口,没有任何接口方法,表明实现该接口的类可被克隆);
    2. 在类中重写Object类中的clone()方法,调用super.clone(),实现浅克隆;
    3. 把克隆的引用指向原型对象新的克隆体;
    class Address{
        private Integer id;
        private String name;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    import java.io.*;
    
    class Person implements Cloneable,Serializable{
        private String name;
        private Integer age;
        private Address address;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return this.name+"  "+this.age+"  "+this.address+"  "+super.toString();
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Object o = null;
            try{
                o = (Person)super.clone();
            }catch (Exception e){
                e.printStackTrace();
            }
            return o;
        }
    }
    
    public class MyTest {
        public static void main(String[] args) throws Exception{
            Address address = new Address();
            address.setId(1);
            address.setName("西安");
    
            Person person1 = new Person();
            person1.setName("张三");
            person1.setAge(24);
            person1.setAddress(address);
            Person person2 = (Person)person1.clone();
    
            System.out.println(person1);
            System.out.println(person2);
        }
    }
    
    瓜田李下  24  Address@4554617c  Person@74a14482
    瓜田李下  24  Address@4554617c  Person@1540e19d
    

    2.2 深克隆实现步骤

    1. 实现Cloneable和Serializable接口(该接口也为标识接口,表明实现该接口的类可被序列化);
    2. 在类中重写Object类中的clone()方法,通过对象的序列化和反序列化实现深克隆;
    3. 把克隆的引用指向原型对象新的克隆体;
    import java.io.Serializable;
    
    class Address implements Serializable{
        private Integer id;
        private String name;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    import java.io.*;
    
    class Person implements Cloneable,Serializable{
        private String name;
        private Integer age;
        private Address address;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return this.name+"  "+this.age+"  "+this.address+"  "+super.toString();
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Object o = null;
            try{
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
                objectOutputStream.writeObject(this);
    
                ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
                ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
    
                o = objectInputStream.readObject();
    
            }catch (Exception e){
                e.printStackTrace();
            }
            return o;
        }
    }
    
    public class MyTest {
        public static void main(String[] args) throws Exception{
            Address address = new Address();
            address.setId(1);
            address.setName("西安");
    
            Person person1 = new Person();
            person1.setName("张三");
            person1.setAge(24);
            person1.setAddress(address);
            Person person2 = (Person)person1.clone();
    
            System.out.println(person1);
            System.out.println(person2);
        }
    }
    
    张三  24  Address@330bedb4  Person@45ee12a7
    张三  24  Address@66d3c617  Person@63947c6b
    
    展开全文
  • 面试题:深克隆和浅克隆的实现方式 面试官考察点 考察目的:深克隆和浅克隆,考察的是Java基础知识的理解。 考察人群:2到5年开发经验。 背景知识详解 先了解下浅克隆和深克隆的定义: 浅克隆:被复制对象...
  • 浅克隆 let obj = { a: 100, b: [10, 20, 30], c: { x: 10 }, d: /^\d+$/ }; let obj2 = {}; 现在想把obj里的每一项都复制给obj2,循环实现浅克隆 for ( let key in obj ) { /*obj.hasOwnProperty(key)...
  • 易懂js的浅克隆和深克隆原理

    千次阅读 2020-05-02 18:01:59
    什么是克隆 其实js里的克隆跟生活里说的克隆是一样的。有一个本体,克隆出跟本体一摸一样的副体,当本体“受伤”时副体是不会“受伤”的,js的克隆也是如此。 来看下面代码 <script> var benti = { top: ...
  • 目录一、如何实现深克隆与浅克隆?1、浅克隆2、深克隆二、深克隆与浅克隆的区别 最近在回顾之前的笔记时,无意间翻阅到了深克隆和浅克隆的模块,感觉其中涉及了很多以后面试中可能会遇到的问题,所以写下此博客用于...
  • 目录为什么要使用克隆(clone)? 为什么要使用克隆(clone)? 当拷贝一个对象时,原始变量与拷贝变量引用同一个对象,也就是说,改变一个变量所引用的对象将会对另一个变量产生影响。先来看一个例子 ...
  • 克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆。浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变。但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈...
  • 浅克隆与深克隆的区别及特点

    千次阅读 2020-06-29 10:29:20
    浅克隆与深克隆的区别 1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String...
  • 浅克隆(Shadow Clone)是把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克隆对象,也就是原型对象中如果有成员变量为引用对象,则此引用对象的地址是共享...
  • 浅克隆 浅克隆是指在克隆对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行克隆。就是将栈中的值复制一份给新的变量,但是两个对象指向都是同一个地址,一个发生改变另外一个也...
  • js简单实现深浅克隆

    2021-10-08 20:27:04
    定义函数将其挂载到Object的原型上,函数接收一个参数,用做判断是深克隆还浅克隆,传递参数为true代表深刻隆,传递false或者不传代表浅克隆。然后通过判断其操作的数据类型来实现 如果该数据是fun
  • Java对象克隆——浅克隆和深克隆的区别

    万次阅读 多人点赞 2017-08-06 00:51:35
    在Java中对象的克隆有深克隆和浅克隆之分。有这种区分的原因是Java中分为基本数据类型和引用数据类型,对于不同的数据类型在内存中的存储的区域是不同的。基本数据类型存储在栈中,引用数据类型存储在堆中。 ...
  • let obj1 = { name:'cdd' curse:{ c1:'数学', c2:'语文' ...浅克隆:只克隆了第一级,对于后代级别还是公用之前的,新克隆的对象/数组还是可以改变原对象/数组中的内容 对象 循环遍历 let obj2 = {}
  • 前言克隆,即复制一个对象,该对象的属性与被复制的对象一致,如果不使用Object类中的clone方法实现克隆,可以...Java中的克隆分为浅克隆与深克隆一、实现克隆的方式1.对象的类需要实现Cloneable接口2.重写Object...
  • 前端-深克隆与浅克隆

    2020-03-30 23:13:07
    深克隆与浅克隆
  • 本文详细介绍了Java中的浅克隆和深克隆的概念,及案例演示如何实现深克隆!
  • 浅克隆:是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象,也就是说对象虽然克隆出来了,但是引用的对象还是那个。 深克隆:不仅拷贝对象本身,而且拷贝对象包含的...
  • 深克隆和浅克隆的区别: 被克隆的类需要实现Clonenable标记接口,重写父类Object类中的方法clone。   浅克隆浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象...
  • js中深克隆与浅克隆

    千次阅读 2018-12-08 11:04:19
    js中深克隆与浅克隆 参考:https://blog.csdn.net/sinat_17775997/article/details/70482279 最近的项目要做一个对表数据的增加,由于表的设计比较复杂:字段中存的数据是json格式,相当于表中表。8多说,上图。 ...
  • 文章目录原型设计模式,克隆一个苹果Code 克隆用的Apple类苹果基类可克隆的苹果(用于浅克隆)可克隆的苹果(用于深克隆)可序列化的苹果(用于深克隆)家庭作业类(用于测试原型模式性能)克隆Test浅克隆测试深克隆...
  • js拷贝对象 浅克隆深克隆 深拷贝浅拷贝 对象简介 js程序中都是用对象结构来描述显示中一个事物,对象就是一组属性和方法的集合。 面向对象三大特点: 封装,继承,多态。 克隆对象 浅克隆是克隆 一层,深层次的对象...
  • vue数组的深克隆和浅克隆

    千次阅读 2020-01-02 14:48:31
    这就是浅克隆的写法,因为后端返回的data是一个数组,而数组是引用数据类型(自行了解基本数据类型和引用数据类型) 如果我们接下来的代码对 _data 进行的处理操作,res.data也会一起改变,这是因为浅克隆, 克隆的...
  • 1)浅克隆 默认的 clone() 方法,为浅克隆,代码如下: class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { Dog dog = new Dog(); dog.name = "旺财"; dog.age = 5; /...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,277
精华内容 12,910
关键字:

浅克隆