王京 的个人博客

记录精彩的程序人生

  menu
44 文章
0 浏览
0 当前访客
ღゝ◡╹)ノ❤️

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

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

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

区别:

浅拷贝:当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是引用数据类型时,那么新对象和原对象的属性值其指向的是同一块内存地址。

深拷贝:会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

****编辑****编辑

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

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


标题:Java 常见的面试题(对象拷贝)
作者:wangjing
地址:https://www.codedblogs.cn/articles/2024/04/12/1712889323058.html