clone()方法是用于浅克隆或者深克隆一个java对象的,但是要注意一个误区:clone方法是Object类的,并不是Cloneable接口的,Cloneable只是一个标记接口,标记接口是用于标记实现该接口的类具有某种该接口标记的功能,常见的标记接口有三个:Serializable、Cloneable、RandomAccess,没有实现Cloneable接口,那么调用clone方法就会爆出CloneNotSupportedException异常。
要使得一个java类可以实现克隆,那么该类就需要实现Cloneable接口,并且重写基类Object的clone方法,其实Object的clone方法就已经默认有克隆的能力了,并且实现的是浅克隆,那为什么一定得重写clone方法呢?
我们先来看Object类的clone方法源码:
protected native Object clone() throws CloneNotSupportedException;
可以看到,该方法非常之特殊:
- 方法被native关键字修饰,并且该方法没有方法体,没有方法体的方法我们认为是抽象方法,可是Object类并不是一个抽象类,而是一个具体类,那为什么还能容纳抽象方法呢,其实就是native关键字在起作用,被native关键字修饰的方法属于本地方法,表示Java的作用范围已经无法达到,底层会去调用C语言或者C++的库。
- 该方法是被protected修饰,这就表明我们在子类中不重写此方法,就在子类外无法访问,因为这个protected权限是仅仅能在Object所在的包和子类能访问的,这也验证了子类重写父类方法权限修饰符可以变大但不能变小的说法。
所以我们要使得一个类具有clone的能力,可以先实现Cloneable接口,再重写clone方法,方法内部去调用了父类的clone方法,其实是为了扩大访问权限,也可以把protected改为public,以后再继承就不用重写了。当然这只是浅克隆的clone函数,深克隆就需要修改clone的方法体了。
public class Mytest implements Cloneable{
/**
* 重写clone方法,调用父类默认的clone方法,实现的是浅克隆
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}