clone类
JAVA提供了一个Cloneable接口,但是这个接口为一个空接口,它没有定义任何的方法。一个没有定义任何方法的接口能够做什么呢?从官方文档上可以看出,这个Cloneable接口是用来与Object类的clone方法结合使用。当一个类实现了Cloneable这个接口时,那么他就可以使用这个clone接口,否则它将抛出一个异常CloneNotSupportedException。这是理想的情况,但是,实际情况却不是这个样子,就是因为Cloneable接口为空。
我们在看一下这个Object的clone方法是如何定义的,首先它是一个protected方法,那么外部的对象就无法直接使用这个接口,如果需要使用clone方法,那么应该继承这个Object类,并覆盖clone方法,指定其访问修饰符为public,下面我们演示一段程序,定义一个支持clone方法的类WebSite。class WebSite implements Cloneable{
private String mDomainName;
private String mName;
private String mEmail;
privateint mAge;
privateint mClick;
public WebSite(){
mDomainName = "www.jiesoon.com";
mName = "jiesoon";
mEmail = "jiesoon@jiesoon.com";
mAge = 3;
mClick = 3000;
}
public WebSite(String domainName, String name, String email,
int age, int click){
mDomainName = new String(domainName);
mName = new String(name);
mEmail = new String(email);
mAge = age;
mClick = click;
}
publicvoid setDomainName(String domainName){
mDomainName = domainName;
}
publicvoid setAge(int age){
mAge = age;
}
publicvoid print(){
System.out.println("Domain name:" + mDomainName);
}
public Object clone(){
returnnew WebSite(mDomainName, mName,
mEmail, mAge, mClick);
}
}
在这个WebSite类中,我们定义了两个构造函数,两个设置函数,一个clone函数和一个打印函数,而这个类同时实现了Cloneable接口,需要注意的是:Cloneable接口不包含任何方法,clone方法是覆盖了Object类的方法。在这个类的定义中,我们定义了一个缺省构造函数和一个含有5个参数的构造函数,这个构造函数为创建当前对象copy的方法。完成这个WebSite类的定义之后,我们就可以实现通过clone接口来创建一个WebSite对象的copy。
publicclass JSCloneable {
publicstaticvoid main(String[] args) {
WebSite jiesoon = new WebSite();
WebSite java = (WebSite)jiesoon.clone();
java.setDomainName("java.jiesoon.com");
jiesoon.print();
java.print();
}
}
在上述的测试代码中,我们使用WebSite的缺省构造函数创建了jiesoon对象,之后我使用jiesoon对象的clone方法构造了一个新的WebSite对象java,在clone函数中,我们采用将当前WebSite对象中的5个参数构造一个WebSite对象的方法,而不是单独地指向这个jiesoon对象。这样就意味着两个WebSite对象现在是完全独立的,如果我们在clone方法中采用赋值的方式:
public Object clone(){
returnthis;
}
那么,jiesoon和java为两个完全相同的对象,而不是执行的clone操作。
在文章的前面,我们介绍了Cloneable接口为一个空接口,所以我们在定义这个类WebSite的时候,其实可以省略从Cloneable实现(强烈建议不要省略这个Cloneable接口),这样做完全是合乎语法的。class WebSite/* implements Cloneable*/{
//定义函数与成员变量
}
clone类的特性
在上述的代码示例中,我们实现了自己的Cloneable方法和覆盖了clone接口,通过使用clone方法所构建的WebSite对象(java)与原来的WebSite对象(jiesoon)有什么区别和联系呢?
两个不同的对象
创建完成jiesoon和java这两个WebSite对象之后,我们使用!=操作符来比较两个对象是否为同一个对象,如下的代码:
publicstaticvoid main(String[] args) {
WebSite jiesoon = new WebSite();
WebSite java = (WebSite)jiesoon.clone();
java.setDomainName("java.jiesoon.com");
jiesoon.print();
java.print();
if(jiesoon != java){
System.out.println("jiesoon != java");
}
}
上述的输出为:jiesoon != java,表明clone出来的WebSite对象是一个崭新的WebSite对象。
隶属于同一个类
我们使用下面的代码将这两个对象的类名称打印出来:
publicstaticvoid main(String[] args) {
WebSite jiesoon = new WebSite();
WebSite java = (WebSite)jiesoon.clone();
java.setDomainName("java.jiesoon.com");
System.out.println("jiesoon.class:" + jiesoon.getClass());
System.out.println("java.class:" + java.getClass());
}
这两个输出结果为:
jiesoon.class:class com.jiesoon.WebSite
java.class:class com.jiesoon.WebSite
也就是说,它们都隶属于WebSite类。
成员内容
我们在这个WebSite类中对于成员内容的输出只包含了一项内容:域名信息。但我们在clone中对所有的成员都进行了复制,它们在成员变量的内容上是完全一致的,下面的代码只输出了域名:
publicstaticvoid main(String[] args) {
WebSite jiesoon = new WebSite();
WebSite java = (WebSite)jiesoon.clone();
jiesoon.print();
java.print();
}
综上所述,我们可以得出这样的结论:clone方法是实现对象复制的关键,Cloneable是一个空接口;clone出来的对象是一个全新的对象,它与原来的对象没有关系;clone出来的对象其内容与原来对象的内容应保持一致。
完整代码
package com.jiesoon;
class WebSite implements Cloneable{
private String mDomainName;
private String mName;
private String mEmail;
privateint mAge;
privateint mClick;
public WebSite(){
mDomainName = "www.jiesoon.com";
mName = "jiesoon";
mEmail = "jiesoon@jiesoon.com";
mAge = 3;
mClick = 3000;
}
public WebSite(String domainName, String name, String email,
int age, int click){
mDomainName = new String(domainName);
mName = new String(name);
mEmail = new String(email);
mAge = age;
mClick = click;
}
publicvoid setDomainName(String domainName){
mDomainName = domainName;
}
publicvoid setAge(int age){
mAge = age;
}
publicvoid print(){
System.out.println("Domain name:" + mDomainName);
}
public Object clone(){
returnnew WebSite(mDomainName, mName,
mEmail, mAge, mClick);
}
}
class Page implements Cloneable{
public Object clone(){
returnnew Page();
}
}
publicclass JSCloneable {
/**
* @param args
*/
publicstaticvoid main(String[] args) {
WebSite jiesoon = new WebSite();
WebSite java = (WebSite)jiesoon.clone();
jiesoon.print();
java.print();
if(jiesoon != java){
System.out.println("jiesoon != java");
}
System.out.println("jiesoon.class:" + jiesoon.getClass());
System.out.println("java.class:" + java.getClass());
}
}