在一次测试clone方法时,D类Override了Object类的clone方法
public class D {
private Integer A1;
private Integer A2;
public D() {
}
public D(Integer a1, Integer a2 {
A1 = a1;
A2 = a2;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
123456789101112131415161718
在测试类中执行clone方法报错了
public class Test5 {
public static void main(String[] args) {
D p = new D();
D p2 = null;
try {
p2 = (D)p.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(p == p2);
}
}
12345678910111213141516
抛出了 CloneNotSupportedException
既然是重写自Object的clone方法,那么去看看Object对该方法的定义:
protected native Object clone() throws CloneNotSupportedException;
1
其中对于异常抛出的描述如下:
Throws:
CloneNotSupportedException – if the object’s class does not support the Cloneable interface. Subclasses that override the clone method can also throw this exception to indicate that an instance cannot be cloned.
如果对象的class不实现Cloneable接口,子类重写clone方法会同样抛出异常表示实例不能被克隆;
哦?
那不意思就是说:你要不父类实现Cloneable接口,要不就子类实现Cloneable
两个测试代码:
测试1: 在父类上实现Cloneable接口
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Father father = new Father();
Father fatherClone = (Father) father.clone();
Son son = new Son();
Son sonClone = (Son) son.clone();
System.out.println(father==fatherClone);
System.out.println(son==sonClone);
}
}
class Father implements Cloneable{
private Integer f1;
private Integer f2;
public Father() {
}
public Father(Integer f1, Integer f2) {
this.f1 = f1;
this.f2 = f2;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Son extends Father{
private Integer s1;
private Integer s2;
public Son() {
}
public Son(Integer s1, Integer s2) {
this.s1 = s1;
this.s2 = s2;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
不出意外,没有任何问题
测试2:在子类上实现Cloneable接口
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
// Father father = new Father();
// Father fatherClone = (Father) father.clone();
Son son = new Son();
Son sonClone = (Son) son.clone();
// System.out.println(father==fatherClone);
System.out.println(son==sonClone);
}
}
class Father {
private Integer f1;
private Integer f2;
public Father() {
}
public Father(Integer f1, Integer f2) {
this.f1 = f1;
this.f2 = f2;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Son extends Father implements Cloneable{
private Integer s1;
private Integer s2;
public Son() {
}
public Son(Integer s1, Integer s2) {
this.s1 = s1;
this.s2 = s2;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
执行父类的clone报错,但是执行子类的clone没得问题
哪个类的需要clone,就在那个类在重写clone方法,并且在那个类或者其父类中实现Cloneable接口
由于Object的clone方法是native修饰的,也就是虚拟机内部实现的方法
根据Hotspot虚拟机定义,找到Object.c
在JVM_Clone方法中有这样一段判断:
很明显,虚拟机给你抛出的异常
很明显,直接在堆内存中执行allocate方法开辟新的对象空间
并返回一个 oop 对象,也就是对象描述的指针(指向对象的首地址)