前言
Java 中存在基础类型和引用类型。Java 的赋值都是传值的
- 对于基础类型,会拷贝具体的内容。
- 对于引用类型,存储的这个值只是指向实际对象的地址,拷贝也只会拷贝引用地址。
在此基础上,「对象的拷贝」可分为两种情况
- 浅拷贝
- 对基本数据类型进行值传递
- 对引用数据类型进行引用地址的拷贝
- 深拷贝
- 对基本数据类型进行值传递
- 对引用数据类型,创建一个新的对象,并复制其内容
拷贝相关API
Object#clone
Java 中所有的对象都是继承自 java.lang.Object
。Object
对象中提供了一个 protected
类型的 clone
方法。
protected native Object clone()
throws CloneNotSupportedException;
Object#clone()
方法是 native
的,所以不需要我们来实现。需要注意的是,clone
方法是 protected
的,这意味着 clone
方法只能在 java.lang
包或者其子类可见。
如果我们想要在一个程序中调用某个对象的 clone
方法则是不可以的。因为 clone
方法是定义在 Object
中的,该对象并没有对外可见的 clone
方法。
Cloneable接口
在上文中提到,Object#clone()
方法是 protected
的,我们不能直接在程序中对一个对象调用 clone
方法。
JDK 推荐「实现 Cloneable
接口并重写 clone
方法(可使用 public
修饰符)来实现属性的拷贝」。
package java.lang;
/**
* 此处给出 Cloneable 的部分注释
* A class implements the Cloneable interface to
* indicate to the java.lang.Object#clone() method that it
* is legal for that method to make a
* field-for-field copy of instances of that class.
*
* Invoking Object's clone method on an instance that does not implement the
* Cloneable interface results in the exception
* CloneNotSupportedException being thrown.
*
* By convention, classes that implement this interface should override
* Object.clone (which is protected) with a public method.
*/
public interface Cloneable {
}
阅读 Cloneable
源码,有如下结论
- 对于实现
Cloneable
接口的对象,是可以调用Object#clone()
方法来进行属性的拷贝。 - 若一个对象没有实现
Cloneable
接口,直接调用Object#clone()
方法,会抛出CloneNotSupportedException
异常。 Cloneable
是一个空接口,并不包含clone
方法。但是按照惯例(by convention
),实现Cloneable
接口时,应该以public
修饰符重写Object#clone()
方法(该方法在