精华内容
下载资源
问答
  • js 深拷贝函数

    2020-10-30 04:01:33
    Javascript中的对像赋值与Java中是一样的,都为引用传递.就是说,在把一个对像赋值给一个变量时,那么这个变量所指向的仍就是原来对像的地址.那怎么来做呢 答案是克隆.
  • 1.预定义非集合类型--拷贝构造函数 public class TestA { public static void main(String[] args) { Integer a = 1; Integer b = new Integer(a); b = 2; if (!a.equals(b)) { System.out....

    1.预定义非集合类型--拷贝构造函数

    public class TestA {
    
    	public static void main(String[] args) {
    		Integer a = 1;
    		Integer b = new Integer(a);
    		b = 2;
    		if (!a.equals(b)) {
    			System.out.println("deep copy");
    		}
    
    		String m = "ok";
    		String n = new String(m);
    		n = "no";
    		if (!m.equals(n)) {
    			System.out.println("deep copy");
    		}
    	}
    }

     结果:都是deep copy

     结论:预定义非集合类型,如果支持拷贝构造函数的类型,则是深拷贝

     

    2. 预定义集合类型--拷贝构造函数--元素为预定义集合类型

    import java.util.ArrayList;
    
    public class TestA {
    
    	public static void main(String[] args) {
    		ArrayList list1 = new ArrayList();
    		list1.add("yangzhou");
    		ArrayList list2 = new ArrayList(list1);
    		list1.clear();
    
    		if (list2.isEmpty()) {
    			System.out.println("shallow copy");
    		} else {
    			System.out.println("deep copy");
    		}
    	}
    }

     结果:deep copy

     结论:预定义集合类型拷贝构造函数,会逐个调用每个元素的operator=方法,当元素为预定义非集合类型时则为深拷贝

     

     

    展开全文
  • 要利用clone实现Java中深拷贝,需要继承Cloneable接口,并重写其中的...package clone深拷贝; public class Main{ // 创建内部类Person,主要是为了在同一个类里面实现相互调用 public static class Person impleme...

    要利用clone实现Java中深拷贝,需要继承Cloneable接口,并重写其中的clone方法。之前看网上的有些例子写得比较复杂,写一个简单的实例供大家参考。


    【代码】

    package clone深拷贝;
    
    public class Main{
    // 创建内部类Person,主要是为了在同一个类里面实现相互调用
        public static class Person implements Cloneable{
            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;
            }
            private int age;
            private String name;
            public Person(int age,String name){
                this.age=age;
                this.name=name;
            }
            public void printInfo(){
                System.out.println("姓名是"+this.name+",年龄是"+this.age);
            }
            // 实现深层拷贝的函数
            @Override
            public Object clone() throws CloneNotSupportedException{
                Person p1=(Person)super.clone();
                return p1;
            }
        }
        public static void main(String[] args){
            Person per1=new Person(23,"张三");
            Person per2;
            try {
                per2 = (Person) per1.clone(); // 成功深层拷贝per1,改变per2的值不会影响per1
                per2.setName("李四");
                per2.setAge(34);
                per1.printInfo();
                per2.printInfo();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
    }

    【结果】

    姓名是张三,年龄是23
    姓名是李四,年龄是34
    展开全文
  • Java对象深拷贝

    2015-12-22 17:52:08
    到网上搜索“Java对象深拷贝”,大多的实现方式是:clone函数实现、序列化+流读写实现新对象创建。 而今天同事想到了一个很简单地方法,采用第三方库gson来实现,太聪明了~ Gson gson = new Gson(); ...

    到网上搜索“Java对象深拷贝”,大多的实现方式是:clone函数实现、序列化+流读写实现新对象创建。


    而今天同事想到了一个很简单地方法,采用第三方库gson来实现,太聪明了~


    Gson gson = new Gson();
    
    ClassA tmp = gson.fromJson(gson.toJson(tradeItem), ClassA.class);

    展开全文
  • 1.首先,你要知道怎么实现克隆:实现Cloneable接口,在bean里面重写clone()...这个也就是我们在没了解清楚这个Java的clone的时候,会出现的问题。 看完代码,我再说明这个时候的问题。 先看我要克隆的学生bean的代...

    1.首先,你要知道怎么实现克隆:实现Cloneable接口,在bean里面重写clone()方法,权限为public。
    2.其次,你要大概知道什么是地址传递,什么是值传递。
    3.最后,你要知道你为什么使用这个clone方法。

    先看第一条,简单的克隆代码的实现。这个也就是我们在没了解清楚这个Java的clone的时候,会出现的问题。
    看完代码,我再说明这个时候的问题。
    先看我要克隆的学生bean的代码:

    package com.lxk.model;
    
    /**
     * 学生类:有2个属性:1,基本属性-String-name;2,引用类型-Car-car。
     * <p>
     * Created by lxk on 2017/3/23
     */
    public class Student implements Cloneable {
        private String name;
        private Car car;
    
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Car getCar() {
            return car;
        }
    
        public void setCar(Car car) {
            this.car = car;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", car=" + car +
                    '}';
        }
    
        @Override
        public Student clone() {
            Student student = null;
            try {
                student = (Student) super.clone();
            } catch (CloneNotSupportedException ignored) {
                System.out.println(ignored.getMessage());
            }
            return student;
        }
    }
    

    学生内部引用了Car这个bean

    package com.lxk.model;
    
    import java.util.List;
    
    public class Car implements Comparable<Car> {
        private String sign;
        private int price;
        private List<Dog> myDog;
        private List<String> boys;
    
        public Car() {
        }
    
        public Car(String sign, int price) {
            this.sign = sign;
            this.price = price;
        }
    
        public Car(String sign, int price, List<Dog> myDog) {
            this.sign = sign;
            this.price = price;
            this.myDog = myDog;
        }
    
        public Car(String sign, int price, List<Dog> myDog, List<String> boys) {
            this.sign = sign;
            this.price = price;
            this.myDog = myDog;
            this.boys = boys;
        }
    
        public String getSign() {
            return sign;
        }
    
        public void setSign(String sign) {
            this.sign = sign;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
        public List<Dog> getMyDog() {
            return myDog;
        }
    
        public void setMyDog(List<Dog> myDog) {
            this.myDog = myDog;
        }
    
        public List<String> getBoys() {
            return boys;
        }
    
        public void setBoys(List<String> boys) {
            this.boys = boys;
        }
    
        @Override
        public int compareTo(Car o) {
            //同理也可以根据sign属性排序,就不举例啦。
            return this.getPrice() - o.getPrice();
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "sign='" + sign + '\'' +
                    ", price=" + price +
                    ", myDog=" + myDog +
                    ", boys=" + boys +
                    '}';
        }
    }

    最后就是main测试类

    package com.lxk.findBugs;
    
    import com.lxk.model.Car;
    import com.lxk.model.Student;
    
    /**
     * 引用传递也就是地址传递需要注意的地方,引起的bug
     * <p>
     * Created by lxk on 2017/3/23
     */
    public class Bug2 {
        public static void main(String[] args) {
            Student student1 = new Student();
            Car car = new Car("oooo", 100);
            student1.setCar(car);
            student1.setName("lxk");
            //克隆完之后,student1和student2应该没关系的,修改student1不影响student2的值,但是完之后发现,你修改car的值,student2也受影响啦。
            Student student2 = student1.clone();
            System.out.println("学生2:" + student2);//先输出student2刚刚克隆完之后的值,然后在修改student1的相关引用类型的属性值(car)和基本属性值(name)
            car.setSign("X5");
            student1.setName("xxx");
            System.out.println("学生2:" + student2);//再次输出看修改的结果
        }
    }
    

    之后就该是执行的结果图了:

    对上面执行结果的疑惑,以及解释说明:

    我们可能觉得自己在bean里面实现clone接口,重写了这个clone方法,那么学生2是经由学生1clone,复制出来的,
    那么学生1和学生2,应该是毫不相干的,各自是各自,然后,在修改学生1的时候,学生2是不会受影响的。
    但是结果,不尽人意。从上图执行结果可以看出来,除了名字,这个属性是没有被学生1影响,关于car的sign属性已经
    因为学生1的变化而变化,这不是我希望的结果。
    可见,这个简单的克隆实现也仅仅是个“浅克隆”,也就是基本类型数据,他是会给你重新复制一份新的,但是引用类型的,
    他就不会重新复制份新的。引用类型包括,上面的其他bean的引用,list集合,等一些引用类型。

    那么怎么实现深克隆呢?
    对上述代码稍作修改,如下:
    学生bean的clone重写方法如下所示:

        @Override
        public Student clone() {
            Student student = null;
            try {
                student = (Student) super.clone();
                if (car != null) {
                    student.setCar(car.clone());
                }
            } catch (CloneNotSupportedException ignored) {
                System.out.println(ignored.getMessage());
            }
            return student;
        }

    然后还要Car类实现cloneable接口,复写clone方法:

        @Override
        public Car clone() {
            Car car = null;
            try {
                car = (Car) super.clone();
                if (myDog != null) {
                    car.setMyDog(Lists.newArrayList(myDog));
                }
                if (boys != null) {
                    car.setBoys(Lists.newArrayList(boys));
                }
            } catch (CloneNotSupportedException ignored) {
                System.out.println(ignored.getMessage());
            }
            return car;
        }

    主测试代码不动,这个时候的执行结果如下:

    可以看到,这个时候,你再修改学生1的值,就不会影响到学生2的值,这才是真正的克隆,也就是所谓的深克隆。

    怎么举一反三?
    可以看到,这个例子里面的引用类型就一个Car类型的属性,但是实际开发中,除了这个引用其他bean类型的属性外,
    可能还要list类型的属性值用的最多。那么要怎么深克隆呢,就像我在Car bean类里面做的那样,把所有的引用类型的属性,
    都在clone一遍。那么你在最上层调用这个clone方法的时候,他就是真的深克隆啦。
    我代码里面那么判断是为了避免空指针异常。当然,这个你也得注意咯。

    注意 重写clone方法的时候,里面各个属性的null的判断哦。
     

    最后,觉得写的好,还请点个赞,留个言啥的。觉得有问题的,提出来,我改,但是,请不要踩我的文章。

    2018-08-10 更新

    上面的是override clone()方法来实现深克隆的。如果你这个要克隆的对象很复杂的话,你就不得不去每个引用到的对象去复写这个clone方法,这个太啰嗦来,改的地方,太多啦。

    还有个方法就是使用序列化来实现这个深拷贝

       /**
         * 对象的深度克隆,此处的对象涉及Collection接口和Map接口下对象的深度克隆
         * 利用序列化和反序列化的方式进行深度克隆对象
         *
         * @param object 待克隆的对象
         * @param <T> 待克隆对象的数据类型
         * @return 已经深度克隆过的对象
         */
    	public static <T extends Serializable> T deepCloneObject(T object) {
            T deepClone = null;
            ByteArrayOutputStream baos = null;
            ObjectOutputStream oos = null;
            ByteArrayInputStream bais = null;
            ObjectInputStream ois = null;
            try {
                baos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(baos);
                oos.writeObject(object);
                bais = new ByteArrayInputStream(baos
                        .toByteArray());
                ois = new ObjectInputStream(bais);
                deepClone = (T)ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
               e.printStackTrace();
            } finally {
                try {
                    if(baos != null) {
                        baos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                try {
                    if(oos != null) {
                        oos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                try{
                    if(bais != null) {
                        bais.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                try{
                    if(ois != null) {
                        ois.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return deepClone;
        }

    具体的使用如下:

        /**
         * 使用序列化来实现深拷贝简单。但是,所涉及到的所有对象都的实现序列化接口。
         */
        private static void cloneBySerializable() {
            Student student1 = new Student();
            Car car = new Car("oooo", 100, Lists.newArrayList(new Dog("aaa", true, true)));
            student1.setCar(car);
            student1.setName("lxk");
    
            Student student2 = deepCloneObject(student1);
            System.out.println("学生2:" + student2);
    
            car.setSign("X5");
            car.setMyDog(null);
            student1.setName("xxx");
            System.out.println("学生2:" + student2);
        }

    实现的效果,还是和上面的一样的,但是这个就简单多来,只需要给涉及到的每个引用类型,都去实现序列化接口就好啦。

    关于这个序列化,师兄我这也有个文章,不嫌弃的,可以看看。链接如下:

    Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

    这里面解释啦下,这个序列化是干啥的,一个model是否序列化,会有什么影响,以及,那个序列化ID的作用是干啥。

    展开全文
  • Android 中对Java对象深拷贝的方法

    千次阅读 2020-08-18 18:16:21
    Java语言中需要拷贝一个对象时,有两种类型:浅拷贝与深拷贝。 浅拷贝:只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。 深拷贝:只是拷贝了源对象的值,所以即使源对象的...
  • Java实现深拷贝的方法—学习笔记

    千次阅读 2017-03-05 16:37:18
    实现Cloneable接口,然后用调用clone()方法,那么返回的...方法一:类实现一个标记接口Serializable通过IO流来实现对象的深拷贝 public class Menus implements Serializable{ private static final long serialV
  • java 深拷贝探讨

    2016-01-26 18:37:41
    java 深拷贝探讨 本文将讨论以下4个问题 1. java Cloneable接口实现深拷贝 ...在C++中实现深拷贝一般情况下重载赋值操作符 “=” 来实现同一个类的对象间的深拷贝,所以很自然的在java中我们也同样
  • Java深拷贝和浅拷贝

    千次阅读 2013-07-23 16:45:04
    深拷贝就是两个对象的值相等,但是互相独立。本来想把以前写的一篇文章扩充一下,没想到居然牵扯出很多复杂的问题。本文测试环境是windows xp sp3中文版、NetBeans6.7.1,JDK1.6-update16。这里抛砖引玉,希望大家能...
  • Java深拷贝和浅拷贝

    千次阅读 2021-03-23 11:25:43
    Java深拷贝和浅拷贝浅拷贝浅拷贝介绍浅拷贝特点深拷贝深拷贝介绍深拷贝特点 浅拷贝 浅拷贝介绍 浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的...
  • java 对象 深拷贝

    2010-11-17 16:42:00
    深拷贝就是两个对象的 值相等,但是互相独立。本来想把以前写的一篇文章扩充一下,没想到居然牵扯出很多复杂的问题。本文测试环境是windows xp sp3中文版、NetBeans6.7.1,JDK1.6-update16。这里抛砖引玉,希望...
  • java拷贝构造函数

    2016-08-15 09:47:00
    浅拷贝就是指两个对象共同拥有同一个值,一个对象改变了该值,也会影响到另一个对象。...如果支持拷贝构造函数的类型,则是深拷贝 不支持 自定义类型 浅拷贝 取决于实现 取决于实现 ...
  • java 深拷贝 浅拷贝

    2013-12-11 10:10:57
    由于Java不支持运算符重载,我们无法在自定义类型中定义operator=,所以使用operator=获取的对象都是浅拷贝,若要实现深拷贝那只能借助于拷贝构造函数和clone方法。 这里我们先看一个基本的原则关系图,掌握了这些...
  • Java-深拷贝(deep copy)

    千次阅读 2019-06-05 16:22:09
    1. 首先Java的clone()方法,我们已经了解 2. 接着clone()方法的浅拷贝,浅拷贝有一些不尽人意的地方 ... 我们需要实现深拷贝(deep copy)。 4. 示例: package com.basis.entity; public class Perso...
  • C++和Java的浅层拷贝与深层拷贝

    千次阅读 2017-05-24 23:07:26
    今天上课学到了C++的浅层拷贝与深层拷贝, 于是在这里将C++和Java关于浅层拷贝与深层拷贝做一个对比.一.C++的浅层拷贝与深层拷贝 先来了解一下C++中的复制构造函数: //假设有这样一个TEST类: class TEST { private: ...
  • Java深拷贝浅拷贝

    2013-11-09 16:29:42
    首先,Java中常用的拷贝操作有三个,operator = 、拷贝构造函数 和 clone()方法。由于Java不支持运算符重载,我们无法在自己的自定义类型中定义operator=。拷贝构造函数大家应该很熟悉,现在看一下如何支持clone...
  • java深拷贝与浅拷贝

    万次阅读 多人点赞 2016-07-22 10:46:02
    转载:http://www.2cto.com/kf/201401/273852.htmlJava中对象的创建clone顾名思义就是复制, 在Java语言...那么在java语言中,有几种方式可以创建对象呢?1 使用new操作符创建一个对象2 使用clone方法复制一个对象那...
  • 1.什么是深拷贝与浅拷贝 何为深拷贝?完全复制一个新的对象,需要申请新的内存空间; 浅拷贝,就是仅仅将引用赋值。 int a = 3; int b = a; a=4; 这是深拷贝,改变a的值不会影响到b; Object x = new Object(); ...
  • Java中常用的拷贝操作有三个,operator = 、拷贝构造函数 和 clone()方法。 不同的类型在拷贝过程中的表现:  (一)预定义非集合类型等号(=)赋值  private void testEqualOperator() { int x = 1; int ...
  • 1.浅复制与复制概念 (1)浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 (2)...
  • 深拷贝:需要拷贝当前引用在堆中所指向的内容,根据这个内容创建一个新的对象(并为属性分配新的空间)。 另外在还可以用二维数组来验证: 因为二维数组存放的也是引用; public class TestArrayCopy { public ...
  • 深拷贝:把引用指向内容复制了一份,真正的拷贝。 常用的拷贝操作有三个: = 、拷贝构造函数 和 clone()方法。 图片转载自:传送门 预定义非集合类型: int, Integer, String 这种,用 = 赋值就是深拷贝。 自定义...
  • Java List 的深拷贝

    千次阅读 2014-10-05 15:37:06
    老是会遇到深拷贝与浅拷贝的问题,这里进行了一些测试,代码如下: /* * To change this template, choose Tools | Templates * and open the template in the editor. */ import java.io.ByteArrayInputStream;...
  • java序列化与反序列化(4)------jdk原生序列化机制实现深拷贝
  • Java深入理解深拷贝和浅拷贝区别

    千次阅读 2020-11-08 10:22:42
    浅拷贝和深拷贝都是对一个已有对象的操作,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函。 在java中,一般使用=好做赋值操作的时候,对于基本数据类型
  • Java 数组 浅拷贝与深拷贝

    千次阅读 2014-01-12 07:59:05
    Java 数组 浅拷贝与深拷贝 定义一个数组int[] a={3,1,4,2,5}; int[] b=a; 数组b只是对数组a的又一个引用,即浅拷贝。如果改变数组b中元素的值,其实是改变了数组a的元素的值 要实现深度复制,可以用clone或者...
  • 1: Java中浅拷贝和深拷贝的定义:  浅拷贝:就是指两个对象共同拥有同一个值,一个对象改变了该值,也会影响到另一个对象。  深拷贝:就是两个对象的值相等,但是互相独立。 (深拷贝才是真正的拷贝,浅拷贝只是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,581
精华内容 15,432
关键字:

java实现深拷贝函数

java 订阅