Object的clone()方法的使用

Object类是所有类的父类,所以它们都继承了Object类中的clone()方法,下面尝试使用下clone()。

一、

测试代码

class MyObject {}   // 定义一个空类,Object类的子类

public class CloneTest {  		// Object类的子类
	public static void main(String[] args) {
		Object obj = new Object();
		Object obj1 = obj.clone();
		
		MyObject myObj = new MyObject();
		MyObject myObj1 = myObj.clone();     // 错误: 不兼容的类型: Object无法转换为MyObject
		
		CloneTest cloneTest = new CloneTest();
		CloneTest cloneTest1 = cloneTest.clone(); //错误: 不兼容的类型: Object无法转换为MyObject
		
		System.out.println("obj: "+obj+"  obj1: "+obj1);
		System.out.println("myObj: "+myObj+"  myObj1: "+myObj1);
		System.out.println("cloneTet: "+cloneTest+"  cloneTest1: "+cloneTest1);
	}
}

编译结果如下:

将后两行代码进行修改为

MyObject myObj = new MyObject();
//MyObject myObj1 = myObj.clone();     // 错误: 不兼容的类型: Object无法转换为MyObject
Object myObj1 = myObj.clone();		

CloneTest cloneTest = new CloneTest();
//CloneTest cloneTest1 = cloneTest.clone(); //错误: 不兼容的类型: Object无法转换为MyObject
Object cloneTest1 = cloneTest.clone();

后面的两个错误就没了

结果分析

在上面的代码中,主类CloneTest、空类MyObject都是Object类的子类,都继承了Object的clone()方法

1、cloneTest.clone()正常执行,而obj.clone()、myObj.clone()则不可见,说明:

子类CloneTest的对象可以访问自己类型的clone()方法, 却不能访问其父类Object、另一个子类myObj的clone()

也就是说,

不能在一个子类中访问另一个子类的对象的protected方法,尽管这两个子类继承自同一个父类;此外,子类不能访问父类的对象的protected方法,要通过自己类型的对象才能访问

即,只能通过自身实例(自身的引用)访问,不能通过父类实例(父类的引用)、其他子类实例(除非是该子类有重写clone()方法)

2、子类使用继承自父类的clone()方法时,返回的对象仍然是父类类型的对象

二、

测试代码2

class MyObject {
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class CloneTest {  		
	public static void main(String[] args) throws CloneNotSupportedException {
		
		MyObject myObj = new MyObject();
		Object myObj1 = myObj.clone();
		
		CloneTest cloneTest = new CloneTest();
		Object cloneTest1 = cloneTest.clone();
		
		System.out.println("myObj: "+myObj+"  myObj1: "+myObj1);
		System.out.println("cloneTet: "+cloneTest+"  cloneTest1: "+cloneTest1);
	}
}

在MyObject类中重写clone()方法,覆盖掉继承自父类的clone()方法,则编译通过,不再有因为protected引起的不可见问题

这时,子类CloneTest可以访问另一个子类MyObject的一个对象的clone()方法。

这时因为,在MyObject类中覆盖clone()方法时,MyObject类和CloneTest类在同一个包下,所以此protected方法对CloneTest类可见。

注意:main方法、重写的clone方法需要throws CloneNotSupportedException,否则编译时会出现下面的错误

但是,在这里虽然编译成功,当我们运行程序时依然会出错

原因分析:

查看Object的源码及文档,发现有这么一句话

The class Object does not itself implement the interface Cloneable, so calling the clone method on an object whose class is Object will result in throwing an exception at run time.

即,Object类中的clone()没有实现Cloneable接口,运行时就会抛出CloneNotSupportedException

而我们的子类MyObject在重写clone()时,也没有实现该接口,所以也会抛出异常

三、实现Cloneable接口

class MyObject implements Cloneable {
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

public class CloneTest implements Cloneable {  		
	public static void main(String[] args) throws CloneNotSupportedException {	
		MyObject myObj = new MyObject();
		Object myObj1 = myObj.clone();
		
		CloneTest cloneTest = new CloneTest();
		Object cloneTest1 = cloneTest.clone();

		System.out.println("myObj: "+myObj+"  myObj1: "+myObj1);
		System.out.println("cloneTet: "+cloneTest+"  cloneTest1: "+cloneTest1);
		}
}

在两个类的定义时写上implements Cloneable,再次编译、运行,这时运行就不会抛出CloneableNotSupportedException了

此外,可以发现

(1)调用clone()返回的对象是一个独立的副本,两个对象地址不同,属性相同。

(2)当我们直接输出两个对象时,尽管原对象的引用是子类类型、副本对象的引用是Object父类类型,输出结果显示对象是子类类型。也就是说,父类类型、子类类型的引用,都可以指向子类类型的对象。

(3)前面看到,clone()返回的对象依然是Object类型,因此,我们只需做强制转换,就可以转化成想要的类型了

MyObject myObj = new MyObject();
//MyObject myObj1 = myObj.clone();          //  错误: 不兼容的类型: Object无法转换为MyObject
//Object myObj1 = myObj.clone();
MyObject myObj1 = (MyObject)myObj.clone();
		
CloneTest cloneTest = new CloneTest();
//CloneTest cloneTest1 = cloneTest.clone(); //  错误: 不兼容的类型: Object无法转换为MyObject
//Object cloneTest1 = cloneTest.clone();
CloneTest cloneTest1 = (CloneTest)cloneTest.clone();

四、clone的另一种重写方式

/*
class MyObject implements Cloneable {
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
*/

class MyObject implements Cloneable {
    public Object clone() {
        MyObject mo = null;
        try {
            mo = (MyObject)super.clone();
        } catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return mo;
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_30973431/article/details/81872636
今日推荐