文章转载自:http://www.cnblogs.com/gw811/archive/2012/10/07/2712252.html
首先,看一下源码:
public class Object { protected native Object clone() throws CloneNotSupportedException; }
由源代码我们会发现:
第一: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接口
首先,看一下源码:
public interface Cloneable { }
我们奇怪的发现Cloneable竟然是空的,那么我们为什么要实现Cloneable接口呢?其 实Cloneable接口仅仅是一个标志,而且这个标志也仅仅是针对 Object类中 clone()方法的,如果 clone 类没有实 现 Cloneable 接口,并调用了 Object 的 clone() 方法(也就是调用了 super.Clone() 方法),那么 Object 的 clone() 方法就会抛出 CloneNotSupportedException 异常。
程序示例分析:
public class Person { private String name; private int age; public Person(){} public Person(String name,int age){ this.name=name; this.age=age; } public Object clone(){ Object o=null; try { o=super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
public class PersonTest { public static void main(String[] args) { Person p1=new Person("zhangsan",18); Person p2=(Person)p1.clone(); p2.setName("lis"); p2.setAge(20); System.out.println("name=" +p1.getName()+",age="+p1.getAge()); //修改p2后,没有对p1产生影响。 } }
说明:
1)为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的 clone()识别你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
2)继承自java.lang.Object.clone()方法是浅层复制。一下代码可以证明之:
public class Student implements Cloneable { private String name; private int age; private Professor pro; public Student(){} public Student(String name,int age,Professor pro){ this.name=name; this.age=age; this.pro=pro; } public Object clone(){ Object o=null; try { //Object中的clone()识别出你要复制的是哪一个对象。 o=super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Professor getPro() { return pro; } public void setPro(Professor pro) { this.pro = pro; } } class Professor{ private String name; private int age; public Professor(){} public Professor(String name,int age){ this.name=name; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
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=maer,age=40 } }
那么我们如何实现深层复制的克隆,即在修改s2.Professor时不影响s1.Professor?代码改进如下:
public class Student implements Cloneable { private String name; private int age; Professor pro; public Student(){} public Student(String name,int age,Professor pro){ this.name=name; this.age=age; this.pro=pro; } public Object clone(){ Student o=null; try { //Object中的clone()识别出你要复制的是哪一个对象。 o=(Student)super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } o.pro=(Professor)pro.clone(); return o; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Professor getPro() { return pro; } public void setPro(Professor pro) { this.pro = pro; } } class Professor implements Cloneable{ private String name; private int age; public Professor(){} public Professor(String name,int age){ this.name=name; this.age=age; } public Object clone(){ Object o=null; try { o=super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
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 } }
相关推荐
Java源码阅读之java.lang.Object Java中的Object类是所有类的父类,任何类都默认继承Object。Object类提供了多种方法,以下是其中一些重要的方法: 1. clone方法:保护方法,实现对象的浅复制,只有实现了...
- java.lang.Object#clone(),创建并返回此对象的副本。 e) 单例模式(Singleton) 单例模式保证一个类只有一个实例,并提供一个全局访问点。在JDK中的例子有: - java.lang.Runtime#getRuntime(),获取Java运行...
3. **内部实现细节**:例如,`java.lang.Object`的`clone()`方法是如何工作的,`java.util.ArrayList`和`java.util.LinkedList`的性能差异,`java.io.InputStream`和`java.io.OutputStream`的抽象设计等。...
Object 是 Java 中最顶级的父类,提供了 equals、hashCode、toString、wait、notify、clone、getClass 等方法。 二十一、指针 Java 中有指针,但是隐藏了,开发人员无法直接操作指针,由 JVM 来操作指针。Java 中...
通过以上分析,我们可以了解到Java动态代理是如何通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现的,以及它的基本应用场景和技术原理。这对于理解和使用AOP、RPC等高级特性有着...
在JDK中,`java.lang.Object#clone()`是一个典型示例,它支持浅克隆,要求实现`java.lang.Cloneable`接口。 ##### 单例模式 单例模式确保一个类只有一个实例,并提供一个全局访问点。JDK中的一些例子是: - `java...
《Java编程中的java.lang包详解》 在Java编程语言中,`java.lang`包是所有Java程序的基础,它包含了进行基本操作和对象创建所必需的类和接口。这个包的重要性在于它是每个Java应用程序的默认导入包,无需显式导入...
1. Java.lang 2. Java.io 3. Java.sql 4. Java.util 5. Java.awt 6. Java.net 7. Java.math 十二、顶级父类 1. Object 十三、Object类常用方法 1. Equals 2. Hashcode 3. toString 4. wait 5. notify 6. clone 7...
`Object`类位于Java的核心库`java.lang`包中,它提供了基本的方法来支持对象的创建、比较和字符串表示。以下是`Object`类的一些关键方法: 1. **构造器**:虽然`Object`类没有显式的构造器,但每个类在创建时都会...
2. java.lang.Object类:Object类是Java语言中所有类的根类,其他类都直接或间接地继承自Object类。Object类定义了几个重要的方法:clone()、equals(Object obj)、finalize()、toString()等。 - clone()方法:用于...
JAVA 中有许多常用的类,每个类都有其特定的方法,本文将对 java.lang.Object 类、String 类和 StringBuffer 类的常用方法进行讲解。 一、java.lang.Object类 java.lang.Object 类是 JAVA 中所有类的父类,它提供...
`clone`方法存在于Java的`java.lang.Object`基类中,所有Java类都默认继承自`Object`类,因此所有类都具备`clone`能力。 首先,要使用`clone`方法,我们需要确保类实现了`Cloneable`接口。`Cloneable`接口并没有...
### 基于commons.lang ArrayUtils类的知识点详解 #### 一、ArrayUtils类简介 `ArrayUtils`类是Apache Commons Lang库中的一个重要工具类,主要用于处理数组的各种操作。相较于Java标准库中的数组操作,`ArrayUtils`...
17. **常用包**:Java的常用包包括java.lang、java.io、java.sql、java.util、java.awt、java.net和java.math等。 18. **最顶级父类**:Java中最顶级的父类是Object,所有类都直接或间接继承自Object。 19. **...
这个方法来源于`java.lang.Object`类,所有Java类都默认继承了这个方法。本资料"Java中clone方法共6页.pdf.zip"可能包含了关于如何理解和使用`clone()`方法的详细解释,以及它在实际开发中的应用示例。 `clone()`...
Java中`Object`类提供的`clone()`方法就是原型模式的应用。 6. **适配器模式**:将一个类的接口转换成客户希望的另一个接口。适配器使原本不兼容的类可以一起工作。在Java IO中,`InputStreamReader`和`...