关于Java的clone()

本文详细介绍了Java中对象克隆的实现方式,包括浅复制与深复制的区别,并通过具体示例展示了如何正确实现Cloneable接口及super.clone()方法。

相关要点:

1.必须实现Cloneable接口,这个接口只是一个标识;如果不实现,调用了clone(),运行时会报CloneNotSupportedException

2.clone是Object的方法,标识为protected,子类必须重写,标识符可改为public

3.对于jdk1.5,clone可以返回相应类的类型或Object;对于1.4,只能返回Object

4.注意深复制和浅复制

 

 

浅复制

(1)对于int,double,Double,String等基本类型,super.clone()是采用的深复制

 

  1. public class TestShallow implements Cloneable {  
  2.     public int a;  
  3.     public String b;  
  4.     public Double c;  
  5.     public TestShallow clone() throws CloneNotSupportedException{  
  6.         return (TestShallow)super.clone();  
  7.     }  
  8. }  
  9. class Test {  
  10.     public static void main(String[] args) throws CloneNotSupportedException {  
  11.         TestShallow a = new TestShallow();  
  12.         a.a = 12;  
  13.         a.b = "hahaa";  
  14.         a.c = 14.11;  
  15.         System.out.println("a原值");  
  16.         print(a);  
  17.         TestShallow b = a.clone();  
  18.         b.a = 13;  
  19.         b.b = "hahab";  
  20.         b.c = 15.11;  
  21.         System.out.println("a现值");  
  22.         print(a);  
  23.         System.out.println("b现值");  
  24.         print(b);  
  25.     }  
  26.       
  27.     public static void print(TestShallow a) {  
  28.         System.out.println("a=" + a.a);  
  29.         System.out.println("b=" + a.b);  
  30.         System.out.println("c=" + a.c);  
  31.     }  
  32. }  
 

结果:

a原值
a=12
b=hahaa
c=14.11
a现值
a=12
b=hahaa
c=14.11
b现值
a=13
b=hahab
c=15.11

(2)对其他类及自定义类,默认采用的是浅复制

  1. class A {  
  2.     public String a;  
  3. }  
  4. public class TestShallow1 implements Cloneable {  
  5.     public int a;  
  6.     public A b;  
  7.     public TestShallow1() {  
  8.         b = new A();  
  9.     }  
  10.     public TestShallow1 clone() throws CloneNotSupportedException{  
  11.         return (TestShallow1)super.clone();  
  12.     }  
  13. }  
  14. class Test1 {  
  15.     public static void main(String[] args) throws CloneNotSupportedException {  
  16.         TestShallow1 a = new TestShallow1();  
  17.         a.a = 12;  
  18.         a.b.a = "hahaa";  
  19.         System.out.println("a原值");  
  20.         print(a);  
  21.         TestShallow1 b = a.clone();  
  22.         b.a = 13;  
  23.         b.b.a = "hahab";  
  24.         System.out.println("a现值");  
  25.         print(a);  
  26.         System.out.println("b现值");  
  27.         print(b);  
  28.     }  
  29.       
  30.     public static void print(TestShallow1 a) {  
  31.         System.out.println("a=" + a.a);  
  32.         System.out.println("b=" + a.b.a);  
  33.     }  
  34. }  

结果:

a原值
a=12
b=hahaa
a现值
a=12
b=hahab
b现值
a=13
b=hahab

 

深复制

对于其中非基本类型的字段,必须明确进行其赋值

  1. class A implements Cloneable {  
  2.     public String a;  
  3.     public A clone() throws CloneNotSupportedException{  
  4.         return (A)super.clone();  
  5.     }  
  6. }  
  7. public class TestDeep implements Cloneable {  
  8.     public int a;  
  9.     public A b;  
  10.     public TestDeep() {  
  11.         b = new A();  
  12.     }  
  13.     public TestDeep clone() throws CloneNotSupportedException{  
  14.         TestDeep clone = (TestDeep)super.clone();  
  15.         clone.b = this.b.clone();  
  16.         return clone;  
  17.     }  
  18. }  
  19. class Test1 {  
  20.     public static void main(String[] args) throws CloneNotSupportedException {  
  21.         TestDeep a = new TestDeep();  
  22.         a.a = 12;  
  23.         a.b.a = "hahaa";  
  24.         System.out.println("a原值");  
  25.         print(a);  
  26.         TestDeep b = a.clone();  
  27.         b.a = 13;  
  28.         b.b.a = "hahab";  
  29.         System.out.println("a现值");  
  30.         print(a);  
  31.         System.out.println("b现值");  
  32.         print(b);  
  33.     }  
  34.       
  35.     public static void print(TestDeep a) {  
  36.         System.out.println("a=" + a.a);  
  37.         System.out.println("b=" + a.b.a);  
  38.     }  
  39. }  

结果:

a原值
a=12
b=hahaa
a现值
a=12
b=hahaa
b现值
a=13
b=hahab

Java中,克隆对象是通过实现`Cloneable`接口并重写`Object`类中的`clone()`方法来完成的。`clone()`方法是一个native方法,它允许Java代码调用非Java实现的功能,以便更接近操作系统层面的操作[^1]。 ### 浅克隆(Shallow Clone) 浅克隆是最简单的克隆方式,它创建一个新的对象,并将原始对象的所有字段复制到新对象中。对于基本数据类型的字段,复制的是值;而对于引用类型的字段,复制的是引用地址,因此两个对象的该字段指向同一个对象。 #### 实现步骤: 1. 让目标类实现`Cloneable`接口。 2. 重写`clone()`方法。 3. 调用父类的`clone()`方法以确保正确性。 ```java public class Person implements Cloneable { private String name; private int age; // 构造函数、getter和setter省略 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这种情况下,如果`Person`类包含了一个对另一个对象(如`Address`)的引用,则克隆后的`Person`实例与原实例共享这个`Address`对象[^4]。 ### 深克隆(Deep Clone) 深克隆不仅复制对象本身,还会递归地复制所有被引用的对象,从而保证原始对象与克隆对象之间没有任何引用关系。 #### 实现方法之一:手动克隆 针对每个引用类型字段,在`clone()`方法中进行深度复制: ```java public class Person implements Cloneable { private String name; private int age; private Address address; // 假设这是一个引用类型 @Override protected Object clone() throws CloneNotSupportedException { Person person = (Person) super.clone(); person.address = (Address) address.clone(); // 假设Address也实现了Cloneable return person; } } ``` #### 实现方法之二:使用序列化 另一种实现深克隆的方式是利用对象序列化和反序列化机制。这种方法适用于整个对象图都可以被序列化的场景。 ```java import java.io.*; public class CloneUtil { public static <T extends Serializable> T clone(T object) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); } } ``` 此方法要求所有涉及的对象都必须实现`Serializable`接口[^5]。 ### 总结 - **浅克隆**适用于不需要独立副本的情况,或者当对象结构简单且不包含可变引用时。 - **深克隆**则提供了完全独立的副本,适合复杂的数据结构或需要修改副本而不影响原始对象的情形。 选择哪种克隆策略取决于具体的应用需求以及性能考量。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值