韩国网站的风格,黑龙江省建设厅官网,设计素材网站有哪些平台,橘子seo【0】README
0.1#xff09; 本文描述源代码均 转自 core java volume 1#xff0c; 旨在理解 对象拷贝 的概念 #xff0c; 特别是对 深拷贝和浅拷贝 的理解#xff1b; 0.2#xff09; 最后#xff0c;我们还要看一个 clone 的荔枝#xff1b; 【1】对象克隆相关
1…【0】README
0.1 本文描述源代码均 转自 core java volume 1 旨在理解 对象拷贝 的概念 特别是对 深拷贝和浅拷贝 的理解 0.2 最后我们还要看一个 clone 的荔枝 【1】对象克隆相关
1.1出现的问题 当copy一个变量时 原始变量和 copy 变量引用同一个对象 也就是说 改变一个变量所引用的对象将会 对另一个变量产生影响
Employee original new Employee(tang, 50000);
Employee copy original;
copy.raiseSalary(10)//oops -- also changed original 1.2解决方法
1.2.1如果创建一个对象的新的copy 它的最初状态与 original一样 但以后将可以各自改变各自的状态 那就需要使用clone 方法
Employee copy original.clone();
copy.raiseSalary(10) // OK--original unchanged
1.2.2不过事情没有那么简单。clone 方法是 Object类的 protected方法 也就是说 在用户编写的代码中不能直接调用它 只有Employee 类才能克隆 Employee 对象1.2.3浅拷贝如果对象中的所有数据域都属于数值或者基本类型 只有copy 域是没有问题的。 但是如果 在对象中包含了子对象的引用 copy 的结果 会使得域 引用同一个子对象 因此原始对象与 克隆对象共享这部分信息 这就叫做浅拷贝 要知道 Object类的clone方法克隆Employee 对象的结果 可以看到 默认的克隆操作是 浅拷贝 它并没有克隆包含在对象中的内部对象 【2】浅拷贝和深拷贝
2.1深拷贝如果原始对象 与 浅拷贝对象共享的子对象是不可变的 将不会产生任何问题然而更常见的 是 子对象是可变的 因此必须重新定义 clone 方法 以便实现 克隆子对象的 深拷贝 2.2在列举的实例中 hireDay域 属于 Date类 这就是一个可变的子对象 2.3对于每一个类 都需要做如下判断
2.3.1默认的clone方法是否满足要求2.3.2默认的 clone 方法是否能够通过 调用可变子对象的 clone 得到修补2.3.3是否不应该使用 clone
2.4实际上 选项3是默认的 如果要选择1或2 类必须
2.4.1实现 Cloneable 接口2.4.2使用 public 访问修饰符重新定义 clone方法
Attention
A1 在Object类中clone方法被说明为 protected 因此无法直接调用 anObject.clone()。但是 不是所有子类都可以访问 受保护的方法吗不是每个类都是Object的子类吗值得庆幸的是 受保护访问的规则极为微妙。子类只能调用受保护的clone方法克隆它自己。为此 必须重新定义clone方法 并将它声明为 public 这样才能够让 所有方法克隆对象A2 Cloneable接口的出现与接口的正常使用没有任何关系。尤其是 它并没有指定clone方法 这个是从 Object类继承来的。接口在这里只是作为一个标记 表明类设计者知道要进行克隆处理。如果一个对象需要克隆而没有实现Cloneable 接口就会产生一个已检验异常A3 Cloneable接口是 java提供的几个标记接口之一 我们知道 通常使用接口的目的是为了确保类实现某个特定的方法或一组特定的方法 Comparable接口就是这样一个实例。而标记接口没有方法 使用它的唯一目的是可以用 instanceof 进行类型检查 if(obj instanceof Cloneable) , 但是我们建议不这样使用
2.5即使clone 的默认实现浅拷贝能够满足需求 也应该实现 Cloneable接口 将 clone 重定义为 public 并调用super.clone()
class Employee implements Cloneable
{public Employee() throws CloneNotSupportedException{return (Employee)super.clone();}
}
2.6为了实现深拷贝 必须克隆所有可变的实例域Key
class Employee implements Cloneable
{public Employee() throws CloneNotSupportedException{Employee cloned (Employee)super.clone();cloned.hireDay (Date)hireDay.clone();}
}
2.7只要在 clone 中含有没有实现 Cloneable接口的对象Object类的 clone方法就会抛出一个CLoneNotSupportedException异常。所以我们需要声明异常
public Employee clone() throws CloneNotSupportedException
2.7.1如果将 上面的形式替换为 try-catch呢
public Employee()
{try{return (Employee)super.clone();}catch(CloneNotSupportedException e) {return null;}
}
Attention以上写法比较适用于 final类否则最好还是保留 throws的形式 2.8必须谨慎地实现子类的克隆
2.8.1如 一旦 Employee定义了clone方法那就可以用它来克隆 Manager对象。Employee的克隆方法能够完成这项任务吗 这将取决于 Manager类中包含哪些域在 Manager类中有可能存在需要深拷贝的域 或者包含一些没有实现 Cloneable 接口的域2.8.2没有人能够保证子类实现的clone 一定正确。鉴于这个原因 应该将 Object类中的clone方法声明为 protected
2.9在自定义的类中应该实现 clone方法吗 如果客户需要深拷贝那就应该实现它。而且 克隆的应用并不像人们想象的那样普遍 在标准类库中 只有不到 5%的类实现了 clone Annotation所有的数组类型均包含clone方法 这个方法被设为 public 而不是 protected。 可以利用 这个 方法创建一个包含所有数据元素拷贝的一个新数组如
int[] luckyNumbers {2, 3, 5, 7, 11, 13];
int[] cloned luckyNumbers.clone();
cloned[5] 12; // doesnt change luckyNumbers[5] 【3】看个荔枝
package com.corejava.chapter6_2;import java.util.Date;
import java.util.GregorianCalendar;public class Employee implements Cloneable
{private String name;private double salary;private Date hireDay;public Employee(String n, double s){name n;salary s;hireDay new Date();}public Employee clone() throws CloneNotSupportedException{// call Object.clone()Employee cloned (Employee) super.clone();// clone mutable fieldscloned.hireDay (Date) hireDay.clone();return cloned;}/*** Set the hire day to a given date. * param year the year of the hire day* param month the month of the hire day* param day the day of the hire day*/public void setHireDay(int year, int month, int day){Date newHireDay new GregorianCalendar(year, month - 1, day).getTime();// Example of instance field mutationhireDay.setTime(newHireDay.getTime());}public void raiseSalary(double byPercent){double raise salary * byPercent / 100;salary raise;}public String toString(){return Employee[name name ,salary salary ,hireDay hireDay ];}
}package com.corejava.chapter6_2;/*** This program demonstrates cloning.* version 1.10 2002-07-01* author Cay Horstmann*/
public class CloneTest
{public static void main(String[] args){try{Employee original new Employee(John Q. Public, 50000);original.setHireDay(2000, 1, 1);Employee copy original.clone();copy.raiseSalary(10);copy.setHireDay(2002, 12, 31);System.out.println(original original);System.out.println(copy copy);}catch (CloneNotSupportedException e){e.printStackTrace();}}
}