设计模式之原型模式(clone)

来源:互联网 发布:淘宝网充值中心在哪 编辑:程序博客网 时间:2024/05/17 07:13

一、Java的数据类型分类

Java的数据类型分为两类:Primitive类型(原始类型)和引用类型。其中Primitive类型指的是8个基本类型,它们都有自己的封装类型:
主值         大小     最小值         最大值                     封装类型
boolean     1 位         -         -                         Boolean
char         16位     Unicode 0     Unicode 2的16次方减1         Character
byte         8位         -128         127                     Byte
short         16位     -2的15次方     +2的15次方减1             Short
int         32位     -2的31次方     +2的31次方减1             Integer
long         64位     -2的63次方     +2的63次方减1             Long
float         32位     IEEE754     IEEE754                 Float
double         64位     IEEE754     IEEE754                 Double
除了原始类型,剩下的都是引用类型,包括String,但String类型稍特殊一些。引用类型的一个特点是:数据存储在堆空间中,引用在栈空间中。


二、深复制和浅复制

浅复制:
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深复制:
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

Java的clone()方法实现的是浅复制,也就是引用类型的clone只是复制了引用而已(String类型是个例外)。

三、clone方法

Object类有如下方法:
protected Object clone ()

Creates and returns a copy of this Object. The default implementation returns a so-called "shallow" copy: It creates a new instance of the same class and then copies the field values (including object references) from this instance to the new instance. A "deep" copy, in contrast, would also recursively clone nested objects. A subclass that needs to implement this kind of cloning should call super.clone() to create the new instance and then create deep copies of the nested, mutable objects.

Returns
a copy of this object.

Throws
CloneNotSupportedException     if this object's class does not implement the Cloneable interface.

需要注意以下几点:
1.这个方法是protected,因此我们需要在其子类中将访问级别改为public,这样我们才可以调用这个方法。

关于Override有几点要注意的地方:
(1).被覆盖方法的访问控制级别可以不一样。
父类的访问级别为protected的,而子类覆盖的方法访问级别为public是可以的,也就是子类的访问级别必须要高于父类被覆盖方法的访问级别,如果父类是public的而子类是protected的则是错误的。
(2).方法被定义为private或static或final的则不能被覆盖。
(3).方法的返回类型:子类的返回类型可以是更具体的对象。
(4).在方法调用时先会在子类中找覆盖的方法,如果子类中没有则会在父类中去找。

2.如果在子类中复写clone这个方法,则应该实现Cloneable接口,否则总会抛出异常。
如注释所说:如果这个类没有实现Cloneable接口,就会抛出CloneNotSupportedException。
注:Cloneable接口中并没有任何方法需要去实现。
Throws CloneNotSupportedException     if this object's class does not implement the Cloneable interface.

3.clone是浅复制
The default implementation returns a so-called "shallow" copy
这意味着如果这个类中包含除了8个原始类型及其封装类型和String类型外的其它类型,那么通过这个方法只是复制了引用,实际仍在堆中共享数据空间。

4.clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
(1)对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
(2)对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
(3)如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
但是这些都不是强制的。
我们需要什么样的clone就搞出什么样的clone好了。
一般而言,我们要的clone应该是这样的。copy和原型的内容一样,但是又是彼此隔离的。即在clone之后,改变其中一个不影响另外一个。

四、如何clone

在派生类中实现Cloneable接口
在派生类中覆盖基类的clone()方法,并声明为public
在派生类的clone()方法中,调用super.clone()

对引用类型进行深复制

//1.实现Cloneable接口public class Prototype implements Cloneable{private String name;private int age;private Car car;    //2.Override clone方法并声明为public    //????声明为protected也可以在外部引用,为什么?????@Override//protected Prototype clone() throws CloneNotSupportedException {public Prototype clone() throws CloneNotSupportedException {    //3.调用super.clone()方法Prototype prototype = (Prototype)super.clone();//4.car是引用类型,需要进行深复制:继续调用Car的clone方法,这意味着Car类也需要能够cloneprototype.car = this.car.clone();return prototype;}}public class Car implements Cloneable{private String type;private float price;@Overridepublic Car clone() throws CloneNotSupportedException {return (Car)super.clone();}}




原创粉丝点击