克隆的两种方式:
在Java中存在两种克隆方式:
深克隆:是指通过实现Serialzable接口,该种克隆方式不仅克隆对象本身,还克隆对象包含的引用所指向的所有对象。
浅克隆:是指通过实现Cloneable接口,该种克隆方式只克隆对象本身,不克隆对象中的引用指向的对象。
为什么需要使用克隆?
在java中,如果我们想对一个对象进行复制,而且还想保留原有的对象去进行接下来的操作,此时就需要克隆!
实现克隆的方法:
在java中:
对于深克隆的实现,我们先实现Serializable接口,再通过对象的序列化和反序列化实现深克隆
对于浅克隆的实现,我们通过实现Cloneable接口,与深克隆需要实现的Serializable接口一样,该接口中也不包含任何方法,但区别在于,浅克隆的实现还需要重写Object中的clone()方法
此外,BeanUtils,apache和Spring都提供了bean工具,只是这都是浅克隆。
深克隆与浅克隆的区别:
虽然深克隆和浅克隆都是用来创建对象副本的方式,但它们之间存在着重要的区别:
1:浅克隆只复制对象本身和对象中的基本类型字段,不复制对象中引用类型字段,而深克隆通过递归将整个对象以及对象引用的对象全部复制。
2:浅克隆创建的对象与原始对象共享内部对象,对新对象的修改可能会影响到原始对象,而深克隆创建的对象与原始对象完全独立,对新对象的修改不会影响到原始对象。
3:浅克隆通常比深克隆更快,因为它不需要复制整个对象树。但是,如果对象树很大或者包含循环引用,深克隆可能会导致性能问题或者无限循环
深克隆与浅克隆如何选择?
1:当需要创建一个与原始对象完全独立的副本时,应该使用深克隆,而当只需要在对象之间共享一些内部对象或者需要快速创建对象副本时,可以使用浅克隆。
2:当一个对象有一个引用类型字段,其中包含了对该对象本身的引用,浅克隆会导致无限递归的克隆,这种情况下,只能使用深克隆。
对于二者我们更推荐使用序列化和反序列化实现克隆,因为基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种方案明显优于使用Object类的clone方法克隆对象,让问题在编译的时候暴露出来总好过把问题留到运行时。
最后补充一下有关泛型限定的知识!
泛型限定:
泛型限定是指在泛型中对类型参数进行限制,以确保类型参数满足某些特定条件。
限定可以是类、接口或类和接口的组合。
在Java中,泛型限定使用 extends 关键字。
如果要限定某个泛型类型参数必须是某个类或其子类,可以使用 extends 关键字,例如:
//这表示泛型类型参数 T 必须是 Number 类或其子类。 class MyClass<T extends Number> { ... }
如果要限定泛型类型参数必须实现某个接口,可以使用 extends 关键字,例如:
//这表示泛型类型参数 T 必须实现 Comparable 接口。 class MyClass<T extends Comparable<T>> { ... }
如果要同时限定泛型类型参数必须是某个类或其子类以及实现某个接口,可以使用 extends 关键字,例如:
//这表示泛型类型参数 T 必须是 Number 类或其子类,并且实现 Comparable 接口。 class MyClass<T extends Number & Comparable<T>> { ... }