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;
    }
}

 

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Java中的clone()方法Object类中定义的方法,它用于创建并返回当前对象的一个副本。这个副本就是一个新的对象,它与原始对象具有相同的属性和方法。通常情况下,我们需要在一个类中实现clone()方法来支持对象的克隆。 克隆对象是在Java中处理对象的一种常见方式。通过克隆,我们可以在不修改原始对象的情况下创建该对象的一个副本。这在某些情况下是非常有用的,例如在多线程环境下,我们需要多个线程同时访问同一个对象,但是又不希望它们之间相互干扰。 在Java中,要使用clone()方法来实现对象的克隆,我们需要满足两个条件: 1. 实现Cloneable接口:这个接口是一个标记接口,它没有任何方法,只是用来标记一个类可以被克隆。 2. 重写clone()方法:这个方法Object类中的一个protected方法,需要在我们的类中进行重写。在重写这个方法时,我们需要调用super.clone()方法来创建一个新的对象,并将原始对象中的属性复制到这个新对象中。 下面是一个示例代码,演示了如何在Java中实现对象的克隆: ``` public class MyClass implements Cloneable { private int value; public MyClass(int value) { this.value = value; } public int getValue() { return value; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这个示例代码中,我们实现了一个MyClass类,并重写了clone()方法。在这个方法中,我们调用了super.clone()方法来创建一个新的对象,并返回这个新对象。由于我们的类实现了Cloneable接口,因此它可以被克隆。 使用这个类进行克隆的代码如下: ``` MyClass obj1 = new MyClass(10); MyClass obj2 = (MyClass) obj1.clone(); System.out.println(obj1.getValue()); // 输出10 System.out.println(obj2.getValue()); // 输出10 ``` 在这个代码中,我们创建了一个MyClass对象obj1,并将其克隆为obj2。由于这两个对象具有相同的属性和方法,因此它们的输出结果也是相同的。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值