Java 常见的面试题(对象拷贝)

一、为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存,因此对这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆,可以用反射的方式或序列化的方式实现。

二、如何实现对象克隆?

  • 实现Cloneable接口并重写Object类中的clone()方法;

    public class CloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {

    	Text s1=new Text("aaaa",18);
    	System.out.println("S1的姓名:"+s1.getName()+",年龄:"+s1.getAge());
    	
    	//使用clone方法实现克隆
    	Object obj=s1.clone();
    	Text s2 = (Text)obj;
    	System.out.println("S2的姓名:"+s2.getName()+",年龄:"+s2.getAge());
    	
    	//此处也可以实现复制,但是此种方法是将s1的地址给了s3,这是如果改变s3里面的东西s1也会跟着变化,但是由于s2是克隆的s1,所以s2并不会被改变
    	Student s3=s1;
    	System.out.println("S3的姓名:"+s3.getName()+",年龄:"+s3.getAge());
    	
    	s3.setAge(20);
    	s3.setName("bbbb");
    	
    	System.out.println("S1的姓名:"+s1.getName()+",年龄:"+s1.getAge());
    	System.out.println("S2的姓名:"+s2.getName()+",年龄:"+s2.getAge());
    	System.out.println("S3的姓名:"+s3.getName()+",年龄:"+s3.getAge());
    }
    

    }

    //此处实现Cloneable接口
    class Text implements Cloneable{
    private String name;
    private int age;
    public Text() {

    }
    public Text(String name,int age) {
    	this.name=name;
    	this.age=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;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    	return super.clone();
    }
    

    }

  • 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆;

    public class User implements Serializable{
    private String name;
    private Integer age;

    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;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
    

    }

    //序列化测试
    @Test
    public void serializableTest() throws Exception {
    //创建一个User对象,并将其赋值
    User user = new User();
    user.setName(“aaaa”);
    user.setAge(25);
    //创建内容存放位置,路径以及文件请提前创建好
    File file = new File(“H:\test.txt”);
    FileOutputStream fos = new FileOutputStream(file);
    //开始序列化
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(user);
    oos.flush();
    oos.close();
    fos.close();
    }

三、深拷贝和浅拷贝区别是什么?

  • 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。
  • 深拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针和堆内存中的对象。

区别:
浅拷贝:当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是引用数据类型时,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝:会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!

注:此博客只是为了记忆相关知识点,大部分为网络上的文章,在此向各个文章的作者表示感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值