如果学过C++的应该对这个内容都有了解过 应该没一本C++的教材在说指针的时候都会说这个问题
为什么要拷贝? 拷贝,在Java里面叫Clone,克隆,是Object类里面就具备实现了的 其实有蛮多人觉得拷贝干嘛? 直接new一个不就得咯! 原因有以下几个: 1)效率,一个拷贝相当于“赋值”,而一个new就是执行构造函数, 如果值很简单(假如是一个int),而得到值很复杂(需要掉其它函数什么的),那么拷贝的效率比构造 高得多。(其实拷贝的实现是:如果是一般类型,就逐位(byte)复制,如果是复制类型,则复制其引用。 这样的拷贝时浅拷贝,因为引用类型,拷贝后仍指向同一个空间) 2)状态,一个拷贝,得到的是一个对象运行时候的状态!而不是初始值。 假如设计个游戏,主角打着打着(代表不是初始状态)中毒了,那么程序的逻辑是要每回合判断 是否中毒 ?然后减HP ? 更好的办法是,设计一个中毒的主角类,这个类每回合自动减HP,当主角 中毒的时候,只要把原来的状态,拷贝到中毒的主角类对象就可以了!这个就是得到对象运行时状态 的好处。 废话又多了,看代码吧,还是那个PSP的例子: public class PSP implements Cloneable{ public String getName() { 实现拷贝有几点: 1)实现Cloneable接口 2)重写Object类中的clone方法,并将可见性从protect改为public 3)克隆需要调用super.clone(),也就是Object的实现方法
PSP p = (PSP)super.clone(); 这样就可以得到一个克隆对象, PSP类里含有引用类型,如果就这样写,就是浅拷贝, 也就是新对象的Version和旧对象的Version指向的是同个空间
而如果 PSP p = (PSP)super.clone(); 即,把引用对象也拷贝一次,那么这就是深拷贝!也就是把全部引用对象都浅拷贝一次,就得到深拷贝 但是注意!! 引用对象也应遵循上面拷贝操作的3条规则: 下面是Version类: public class Version implements Cloneable{ public Version(String version){ public void setVersion(String version) { @Override
这个就是Java的深浅拷贝
提个问题,假如对象持有的应用不是自己的类,是别人的,但是别人没有实现Cloneable接口?! 怎么办?!
呵呵,可以使用一个小技巧,就是对象流!! ByteArrayOutputStream baop =new ByteArrayOutputStream(); oop.writeObject(new Object()); ois.readObject();
上面代码的意思是,先构造一个字节数组流(写到内存里面的某个地方),外面装饰一个 对象流(装饰模式),把对象直接写入内存的某处,然后把那个流得出来 这样就可以的到一个完全相同的副本!也就是深拷贝,这种方法不用实现什么接口
好了,写完了
写给一直进步的人 |
|