Java之克隆机制
2015-07-22 09:06
295 查看
首先了解一下什么叫做拷贝?
Employ e1 = new Employ();
Employ e2 = e1;
这就是拷贝,原始变量与拷贝变量指向相同的引用对象,如果改变其中一个对象的状态,其他的对象变量的对象状态也会随之改变。
什么叫做克隆?
Employ e1 = new Employ();
Employ e2 = e1.clone();
克隆之后的变量,各自指向自己的对象,这个对象状态初始是相同的,只不过在改变其中一个对象的状态的时候,另一个对象状态不会再发生改变。
clone()方法在Object中是这样定义的:
[java] view
plaincopyprint?
protected native Object clone() throws CloneNotSupportedException;
他是受保护类型的,那为什么他是受保护的类型呢?
由于对具体的实现类一无所知,所以只能将全部域进行拷贝,如果变量本身是基础类型没关系,但是如果如果对象中包含其他的子对象引用,这样克隆之后的对象与原变量共享子类,同样改变一个子对象状态,另一个也发生改变(如果子对象是不可改变的,这样也没有关系,比如:String类型),所以只能Employ本身进行克隆,这就是克隆的浅拷贝。一般我们需要重写clone()方法进行深拷贝。
1、实现Cloneable接口
2、使用public修饰clone方法,对clone进行重新定义
Cloneable接口并没有clone()方法,这个方法是从Object类中继承过来的,这里接口只是作为一个标记,表明设计者要进行克隆处理(如果没有实现接口就进行克隆,会抛出一个已检验异常)。使用标记接口的唯一目的,就是通过instanceof进行类型检查。
实现默认的浅拷贝:
[java] view
plaincopyprint?
class Employ implements Cloneable{
public Employ clone(){
return super.clone();
}
如果要进行深拷贝,需要将所有可变的实例域进行克隆,假如Employ中有一birthDay(他是Date类型的,是一个对象引用):
[java] view
plaincopyprint?
public Employ clone() throws CloneNotSupportedException{
Employ cloned = (Employ) super.clone();
cloned = (Date)birthDay.clone();
return cloned;
}
需要确保子类对象也实现了Cloneable接口,否则会抛出CloneNotSupportedException。
需要谨慎使用Clone。因为如果你这样实现了Clone方法,任何人都可以通过clone方法,实现子类的Clone,如果子类中的域变量是可变的,或者是一些没有实现Cloneable接口的,就会出现问题。所以Object将clone()方法定义为protected类型(不是子类也可以实现父类protected类型的方法吗?不理解)。
Employ e1 = new Employ();
Employ e2 = e1;
这就是拷贝,原始变量与拷贝变量指向相同的引用对象,如果改变其中一个对象的状态,其他的对象变量的对象状态也会随之改变。
什么叫做克隆?
Employ e1 = new Employ();
Employ e2 = e1.clone();
克隆之后的变量,各自指向自己的对象,这个对象状态初始是相同的,只不过在改变其中一个对象的状态的时候,另一个对象状态不会再发生改变。
clone()方法在Object中是这样定义的:
[java] view
plaincopyprint?
protected native Object clone() throws CloneNotSupportedException;
他是受保护类型的,那为什么他是受保护的类型呢?
由于对具体的实现类一无所知,所以只能将全部域进行拷贝,如果变量本身是基础类型没关系,但是如果如果对象中包含其他的子对象引用,这样克隆之后的对象与原变量共享子类,同样改变一个子对象状态,另一个也发生改变(如果子对象是不可改变的,这样也没有关系,比如:String类型),所以只能Employ本身进行克隆,这就是克隆的浅拷贝。一般我们需要重写clone()方法进行深拷贝。
1、实现Cloneable接口
2、使用public修饰clone方法,对clone进行重新定义
Cloneable接口并没有clone()方法,这个方法是从Object类中继承过来的,这里接口只是作为一个标记,表明设计者要进行克隆处理(如果没有实现接口就进行克隆,会抛出一个已检验异常)。使用标记接口的唯一目的,就是通过instanceof进行类型检查。
实现默认的浅拷贝:
[java] view
plaincopyprint?
class Employ implements Cloneable{
public Employ clone(){
return super.clone();
}
如果要进行深拷贝,需要将所有可变的实例域进行克隆,假如Employ中有一birthDay(他是Date类型的,是一个对象引用):
[java] view
plaincopyprint?
public Employ clone() throws CloneNotSupportedException{
Employ cloned = (Employ) super.clone();
cloned = (Date)birthDay.clone();
return cloned;
}
需要确保子类对象也实现了Cloneable接口,否则会抛出CloneNotSupportedException。
需要谨慎使用Clone。因为如果你这样实现了Clone方法,任何人都可以通过clone方法,实现子类的Clone,如果子类中的域变量是可变的,或者是一些没有实现Cloneable接口的,就会出现问题。所以Object将clone()方法定义为protected类型(不是子类也可以实现父类protected类型的方法吗?不理解)。
相关文章推荐
- java之反射机制
- Struts2配置的Param如何调用?
- Java数组简单用法
- 深入理解Java内存模型--转载
- 【SpringMVC整合MyBatis】整合思路与工程结构
- java中异常的处理和分析
- java之线程
- java之IO处理
- 开源 java CMS - FreeCMS2.3会员我的评论
- JAVA学习第六天
- Implementing HashSet in Java
- JAVA8 十大新特性详解
- java错误提示----------类型不匹配
- JAVA的输入输出流解析
- Eclipse卸载android开发环境(ADT)
- Java Final Keyword
- Java Final, Finally, Finalize
- spring对shiro注解支持的原理
- 02 JAVA 对象补充 抽象VS接口
- Eclipse 启动不了 一闪而过