1、区别

java浅拷贝 integer java clone是深拷贝和浅拷贝_浅拷贝


2、浅拷贝

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

1、 基本类型

如果变量是基本很类型,则拷贝其值,比如int、float等。

2、 对象

如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。

3、 String字符串

若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有字符串对象保持不变。

如何使用clone()方法
I. 实现Cloneable 接口
II. 覆盖clone()
III. 在自己的clone()中调用super.clone()
IV. 在自己的clone()中捕获异常

//浅拷贝实现,默认的拷贝是浅拷贝
package cn.cupcat.java8;
public class Person implements Cloneable{
    private String name;
    private int age;
    private int[] ints;
    public int[] getInts() {
        return ints;
    }
    public Person(String name, int age, int[] ints) {
        this.name = name;
        this.age = age;
        this.ints = ints;
    }
    public void setInts(int[] ints) {
        this.ints = ints;
    }
    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 Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     *  默认实现
     * */
    @Override
    public Object clone() throws CloneNotSupportedException {
        return  super.clone();
    }
}

3、深拷贝
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

//深拷贝的实现,通过序列化实现深拷贝
public static <T extends Serializable> T clone(T obj){
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();
            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
}
//使用该工具类的对象必须要实现Serializable接口,否则是没有办法实现克隆的。
public class Person implements Serializable{
    private static final long serialVersionUID = 2631590509760908280L;
    ..................
    //去除clone()方法
}
public class Email implements Serializable{
    private static final long serialVersionUID = 1267293988171991494L;
    ...................
}
//CloneTest3 序列化深拷贝

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

public class CloneTest3
{
    public static void main(String[] args) throws Exception
    {
        Teacher3 t = new Teacher3();
        t.setName("Teacher Wang");
        t.setAge(50);

        Student3 s1 = new Student3();
        s1.setAge(20);
        s1.setName("ZhangSan");
        s1.setTeacher(t);

        Student3 s2 = (Student3) s1.deepClone();

        System.out.println("拷贝得到的信息:");
        System.out.println(s2.getName());
        System.out.println(s2.getAge());
        System.out.println(s2.getTeacher().getName());
        System.out.println(s2.getTeacher().getAge());
        System.out.println("---------------------------");

        // 将复制后的对象的老师信息修改一下:
        s2.getTeacher().setName("New Teacher Wang");
        s2.getTeacher().setAge(28);

        System.out.println("修改了拷贝对象的教师后:");
        System.out.println("拷贝对象的教师:");
        System.out.println(s2.getTeacher().getName());
        System.out.println(s2.getTeacher().getAge());
        System.out.println("原来对象的教师:");
        System.out.println(s1.getTeacher().getName());
        System.out.println(s1.getTeacher().getAge());

        // 由此证明序列化的方式实现了对象的深拷贝

    }

}

class Teacher3 implements Serializable
{
    private String name;
    private int age;

    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;
    }

}

class Student3 implements Serializable
{
    private String name;
    private int age;
    private Teacher3 teacher;

    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 Teacher3 getTeacher()
    {
        return teacher;
    }

    public void setTeacher(Teacher3 teacher)
    {
        this.teacher = teacher;
    }

    public Object deepClone() throws Exception
    {
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        return ois.readObject();
    }

}