java入门 -- 深浅拷贝及克隆

克隆

Java实现克隆需要遵循以下规则:
1.必须实现Cloneable接口
2.实现Cloneable的类应该重写clone(),重写时该方法的修饰符为public。

浅拷贝

是将原始对象中的数据型字段拷贝到新对象中去,将引用型字段的“引用”复制到新对象中去,不把“引用的对象”复制进去,所以原始对象和新对象引用同一对象,新对象中的引用型字段发生变化会导致原始对象中的对应字段也发生变化。


public class Person implements Cloneable {
    private String name;
    private int age;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    //clone是浅拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

//    //深拷贝
//    @Override
//    protected Object clone() throws CloneNotSupportedException {
//        String name = new String(this.name);
//        return new Person(23, name);
//    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(23, "李四");
       Person person2 = (Person) person1.clone();//浅拷贝
       // Person person2 = (Person) person1.clone();//深拷贝
        String result = person1.getName() == person2.getName() ? "clone是浅拷贝" : "clone是深拷贝";
        System.out.println(result);
    }
}

在这里插入图片描述
当person1的属性和person2的属性相同时,就是浅拷贝。对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,不会对内存中的对象进行改变。

深拷贝

是在引用方面不同,深拷贝就是创建一个新的和原始字段的内容相同的字段,是两个一样大的数据段,所以两者的引用是不同的,之后的新对象中的引用型字段发生改变,不会引起原始对象中的字段发生改变。

public class Person implements Cloneable {
    private String name;
    private int age;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    //clone是浅拷贝
//    @Override
//    protected Object clone() throws CloneNotSupportedException {
//        return super.clone();
//    }

    //深拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        String name = new String(this.name);
        return new Person(23, name);
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(23, "李四");
//        Person person2 = (Person) person1.clone();//浅拷贝
        Person person2 = (Person) person1.clone();//深拷贝
        String result = person1.getName() == person2.getName() ? "clone是浅拷贝" : "clone是深拷贝";
        System.out.println(result);
    }
}

在这里插入图片描述
当person1的属性和person2的属性不同时,就是深拷贝。对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,当复制了内容并对即使没有进行修改,其内存对应的地址也是不同的,就是说再内存中重新开辟了一块地址取存放。

深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。

深拷贝的另一种实现方式:进行序列化

import com.sun.corba.se.impl.io.OutputStreamHook;
import org.junit.Test;

import java.io.*;

/**
 * @author lenovo
 */
public class ObjectInputOutputStreamTest {
    @Test
    public void test01(){
        //序列化,写入到内存层面,防止被删除
        ObjectOutputStream oos =null;
        try {
            //1.造对象
             oos =new ObjectOutputStream(new FileOutputStream("Object.txt"));
            //2.造流, 存储和读取基本数据类型数据或对象的处理流 ,这里为对象
            oos.writeObject(new String("小猫咪喵喵喵"));
            //3.注意写出一次,操作flush()一次 ,刷新操作
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (oos !=null)
        //4.关闭
        {
            try {
                oos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
    @Test
    public void test02(){
        //反序列化
        ObjectInputStream ois = null;
        try {

            //1.造对象
            ois = new ObjectInputStream(new FileInputStream("Object.txt"));
            //2.造流
            Object o = ois.readObject();
            String str = (String) o;
            System.out.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }if(ois !=null)
        //3.关闭,没有刷新
        {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值