Object.clone()方法
来源:互联网 发布:淘宝网 话费充值 编辑:程序博客网 时间:2024/05/22 07:45
首先,看一下源码:
1 public class Object {2 protected native Object clone() throws CloneNotSupportedException;3 }
由源代码我们会发现:
第一:Object类的clone()方法是一个native方法,native方法的效率一般来说都是远高于Java中的非native方法。这也解释了为什么要用Object中clone()方法而不是先new一个类,然后把原始对象中的信息复制到新对象中,虽然这也实现了clone功能。(JNI是Java Native Interface的 缩写。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。)
第二:Object类中的 clone()方法被protected修饰符修饰。这也意味着如果要应用 clone()方 法,必须继承Object类,在 Java中所有的类是缺省继承 Object类的,也就不用关心这点了。然后重载 clone()方法。还有一点要考虑的是为了让其它类能调用这个 clone类的 clone()方法,重载之后要把 clone()方法的属性设置为 public。
第三:Object.clone()方法返回一个Object对象。我们必须进行强制类型转换才能得到我们需要的类型。
浅层复制与深层复制概念:
浅层复制: 被复制的对象的所有成员属性都有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅层复制仅仅复制所考虑的对象,而不复制它所引用的对象。(概念不好理解,请结合下文的示例去理解)
深层复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。换言之,深层复制要复制的对象引用的对象都复制一遍。
Java中对象的克隆
1)在派生类中实现Cloneable借口。
2)为了获取对象的一份拷贝,我们可以利用Object类的clone方法。
3)在派生类中覆盖积累的clone方法,声明为public。
4)在派生类的clone方法中,调用super.clone()。
实现Cloneable接口
首先,看一下源码:
1 public interface Cloneable { 2 }
我们奇怪的发现Cloneable竟然是空的,那么我们为什么要实现Cloneable接口呢?其实Cloneable接口仅仅是一个标志,而且这个标志也仅仅是针对 Object类中 clone()方法的,如果 clone 类没有实现 Cloneable 接口,并调用了 Object 的 clone() 方法(也就是调用了 super.Clone() 方法),那么Object 的 clone() 方法就会抛出 CloneNotSupportedException 异常。
程序示例分析:
1 public class Person { 2 private String name; 3 private int age; 4 public Person(){} 5 public Person(String name,int age){ 6 this.name=name; 7 this.age=age; 8 } 9 public Object clone(){10 Object o=null;11 try {12 o=super.clone();13 } catch (CloneNotSupportedException e) {14 e.printStackTrace();15 }16 return o;17 }18 public String getName() {19 return name;20 }21 public void setName(String name) {22 this.name = name;23 }24 public int getAge() {25 return age;26 }27 public void setAge(int age) {28 this.age = age;29 }30 }
1 public class PersonTest { 2 public static void main(String[] args) { 3 Person p1=new Person("zhangsan",18); 4 Person p2=(Person)p1.clone(); 5 p2.setName("lis"); 6 p2.setAge(20); 7 System.out.println("name=" 8 +p1.getName()+",age="+p1.getAge()); 9 //修改p2后,没有对p1产生影响。10 }11 }
说明:
1)为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
2)继承自java.lang.Object.clone()方法是浅层复制。一下代码可以证明之:
1 public class Student implements Cloneable { 2 private String name; 3 private int age; 4 private Professor pro; 5 public Student(){} 6 public Student(String name,int age,Professor pro){ 7 this.name=name; 8 this.age=age; 9 this.pro=pro;10 }11 public Object clone(){12 Object o=null;13 try {14 //Object中的clone()识别出你要复制的是哪一个对象。15 o=super.clone();16 } catch (CloneNotSupportedException e) {17 System.out.println(e.toString());18 }19 return o;20 }21 public String getName() {22 return name;23 }24 public void setName(String name) {25 this.name = name;26 }27 public int getAge() {28 return age;29 }30 public void setAge(int age) {31 this.age = age;32 }33 public Professor getPro() {34 return pro;35 }36 public void setPro(Professor pro) {37 this.pro = pro;38 }39 }40 class Professor{41 private String name;42 private int age;43 public Professor(){}44 public Professor(String name,int age){45 this.name=name;46 this.age=age;47 }48 public String getName() {49 return name;50 }51 public void setName(String name) {52 this.name = name;53 }54 public int getAge() {55 return age;56 }57 public void setAge(int age) {58 this.age = age;59 }60 }
1 public class StudentTest { 2 public static void main(String[] args) { 3 Professor p=new Professor("wangwu",50); 4 Student s1=new Student("zhangsan",18,p); 5 Student s2=(Student)s1.clone(); 6 s2.getPro().setName("maer"); 7 s2.getPro().setAge(40); 8 System.out.println("name="+s1.getPro().getName() 9 +",age="+s1.getPro().getAge());10 //name=maer,age=4011 }12 }
那么我们如何实现深层复制的克隆,即在修改s2.Professor时不影响s1.Professor?代码改进如下:
1 public class Student implements Cloneable { 2 private String name; 3 private int age; 4 Professor pro; 5 public Student(){} 6 public Student(String name,int age,Professor pro){ 7 this.name=name; 8 this.age=age; 9 this.pro=pro;10 }11 public Object clone(){12 Student o=null;13 try {14 //Object中的clone()识别出你要复制的是哪一个对象。15 o=(Student)super.clone();16 } catch (CloneNotSupportedException e) {17 System.out.println(e.toString());18 }19 o.pro=(Professor)pro.clone();20 return o;21 }22 public String getName() {23 return name;24 }25 public void setName(String name) {26 this.name = name;27 }28 public int getAge() {29 return age;30 }31 public void setAge(int age) {32 this.age = age;33 }34 public Professor getPro() {35 return pro;36 }37 public void setPro(Professor pro) {38 this.pro = pro;39 }40 }41 class Professor implements Cloneable{42 private String name;43 private int age;44 public Professor(){}45 public Professor(String name,int age){46 this.name=name;47 this.age=age;48 }49 public Object clone(){50 Object o=null;51 try {52 o=super.clone();53 } catch (CloneNotSupportedException e) {54 e.printStackTrace();55 }56 return o;57 }58 public String getName() {59 return name;60 }61 public void setName(String name) {62 this.name = name;63 }64 public int getAge() {65 return age;66 }67 public void setAge(int age) {68 this.age = age;69 }70 }
public class StudentTest { public static void main(String[] args) { Professor p=new Professor("wangwu",50); Student s1=new Student("zhangsan",18,p); Student s2=(Student)s1.clone(); s2.getPro().setName("maer"); s2.getPro().setAge(40); System.out.println("name="+s1.getPro().getName() +",age="+s1.getPro().getAge()); //name=wangwu,age=50 }}
- Object.clone()方法
- Object的clone方法
- Object中的clone方法
- Object.clone()方法
- Object 的clone方法
- Object的clone方法
- Object分析--1、clone()方法
- Object类中的clone方法
- Java Object的clone方法
- Object对象的通用方法-clone
- Java Object对象之clone方法
- C# 关于Object的Clone方法
- Object类(一)Clone方法
- 关于Object.clone克隆方法的测试
- java Object类 clone()方法 详解
- Cloneable接口和Object的clone()方法
- Java Object对象之clone方法
- Java Object对象之clone方法
- hdu 1102 uva 10397(最小生成树prim)
- HDU 4198 Quick out of the Harbour(优先队列 + bfs)
- Java 泛型小结
- 修改MYSQL提示符
- MongoDB学习 (五):查询操作符(Query Operators).1st
- Object.clone()方法
- 浏览器不同语言切换不同页面
- 怎么关闭指定端口 3306
- 【转载】Java之美[从菜鸟到高手演变]之设计模式二
- MySQL数据库表结构设计优化技巧总结
- HTML 5 的自定义 data-* 属性和jquery的data()方法的使用
- 多线程编程 - GCD
- 自己动手写编译器、链接器-第一章
- java中long 转换成 int